In Progress
作为 用户, 我想要 柱状图能够正确显示,横轴标线正常、柱子之间有间隔、整体居中对齐, 以便于 能够清晰地查看数据统计图表。
在完成了 Canvas pixelRatio 修复后(故事016.014及相关调试),柱状图已经能够在 Canvas 画布中正确显示尺寸,但出现了以下布局问题:
这些问题的根本原因是在修复 Canvas 尺寸问题时,引入了 pixelRatio 的缩放,但部分绘制计算逻辑没有正确处理这个缩放因子。
pixelRatio=2 匹配设备像素calYAxisData 或 getYAxisTextList 在计算刻度位置时可能没有正确考虑 opts.pixfixColumeData 中的宽度计算公式可能需要调整eachSpacing 的计算可能不正确ColumnChart 组件的显示效果[x] 任务1: 分析当前布局问题的根本原因 (AC: 1-6)
eachSpacing 的值item.widthstartXopts.area 的值opts.pix[x] 任务2: 修复 Y轴网格线间隔问题 (AC: 1)
getYAxisTextList 函数的刻度计算逻辑opts.pix[x] 任务3: 修复柱子宽度和间距问题 (AC: 2)
fixColumeData 函数的宽度计算公式extra.column.width 和 extra.column.categoryGap 的配置opts.pix[x] 任务4: 修复柱子位置偏移问题 (AC: 3)
getColumnDataPoints 中的 point.x 计算fixColumeData 中的位置调整逻辑opts.pix[ ] 任务5: 测试不同 pixelRatio 设备 (AC: 5)
[x] 任务6: 清理调试日志 (AC: 6)
pnpm build 确保构建成功在以下文件/函数中添加 console.debug:
// draw-charts.ts: Y轴数据计算后
console.debug('[drawCharts] Y轴配置:', {
yAxisDataRanges: opts.chartData?.yAxisData?.ranges,
yAxisDataRangesFormat: opts.chartData?.yAxisData?.rangesFormat,
pixelRatio: opts.pix
});
// column-renderer.ts: 柱子数据点计算后
console.debug('[drawColumnDataPoints] 柱子参数:', {
eachSpacing,
columnLen: series.length,
seriesIndex,
itemWidth: points[0]?.width,
itemX: points[0]?.x,
zeroPoints,
area: opts.area,
pixelRatio: opts.pix
});
// axis-calculator.ts: Y轴刻度计算
console.debug('[calYAxisData] Y轴刻度计算:', {
YLength,
rangesArrLength: rangesArr.length,
ranges0: rangesArr[0],
pixelRatio: opts.pix
});
在 /docs/小程序图表库示例/u-charts小程序图表库.js 中查找:
function getYAxisTextList (约第 2000 行)function fixColumeData (约第 2400 行)function drawDataPoints 的 column 分支Y轴刻度数量:
// 原始代码
let dataRange = getDataRange(minData, maxData);
let minRange = dataRange.minRange;
let maxRange = dataRange.maxRange;
let eachRange = (maxRange - minRange) / 5; // 默认5个刻度
柱子宽度计算:
// 原始代码
seriesGap = Math.min(seriesGap, eachSpacing / columnLen);
categoryGap = Math.min(categoryGap, eachSpacing / columnLen);
item.width = Math.ceil((eachSpacing - 2 * categoryGap - seriesGap * (columnLen - 1)) / columnLen);
柱子位置调整:
// 原始代码
item.x += (index + 0.5 - columnLen / 2) * (item.width + seriesGap);
src/lib/data-processing/axis-calculator.ts
getYAxisTextList 函数dataRange 计算和 eachRange 是否需要乘以 opts.pixsrc/lib/helper-functions/data-fixers.ts
fixColumeData 函数seriesGap 和 categoryGap 是否需要乘以 opts.pixsrc/lib/charts-data/basic-charts.ts
getColumnDataPoints 函数point.x 和 point.y 的计算是否正确src/lib/renderers/column-renderer.ts
drawColumnDataPoints 函数当使用 Canvas 2D API (type="2d") 时:
width/height 属性是实际像素尺寸(逻辑像素 × pixelRatio)style.width/style.height 是CSS 显示尺寸(逻辑像素)关键点:opts.width 和 opts.height 应该是逻辑像素尺寸,不应该乘以 pixelRatio!
// 设备 pixelRatio = 2
// 期望图表大小:650px × 200px (CSS 像素)
const config = {
width: 650, // 逻辑像素,不是 650 * 2
height: 200, // 逻辑像素,不是 200 * 2
pixelRatio: 2 // 告诉图表库设备的像素比
};
// Canvas 元素:
// width 属性:1300 (650 * 2,实际像素)
// height 属性:400 (200 * 2,实际像素)
// style.width:650px
// style.height:200px
// 绘图时的坐标:
// 所有坐标计算基于 650 × 200 的逻辑尺寸
// opts.pix = 2 用于某些需要额外缩放的场合(如字体大小、线宽)
src/components/BaseChart.tsx - Canvas 尺寸设置src/lib/data-processing/axis-calculator.ts - Y轴刻度计算src/lib/charts-data/basic-charts.ts - 数据点坐标计算src/lib/helper-functions/data-fixers.ts - 柱子宽度和位置修正src/lib/renderers/column-renderer.ts - 柱状图绘制src/lib/draw-controllers/draw-charts.ts - 主绘制流程无(经过分析后确认原始代码是正确的)
问题分析结果:
经过对比原始 u-charts.js 代码,发现原始代码是正确的,应该保持 * opts.pix 的写法。
Canvas 2D API 与旧版 Canvas API 的差异:
| 项目 | 旧版 Canvas API | Canvas 2D API (我们的实现) |
|---|---|---|
| Canvas width/height 属性 | 逻辑像素 | 实际像素 (逻辑×pixelRatio) |
| opts.width/opts.height | 逻辑像素 | 逻辑像素 |
| 绘制坐标 | 需要 × opts.pix | 需要 × opts.pix |
| 字体大小、线宽 | 需要 × opts.pix | 需要 × opts.pix |
关键理解: 虽然使用 Canvas 2D API,Canvas 的 width/height 属性是实际像素,但 Taro 的 CanvasContext 不会自动缩放坐标。因此绘制时仍需将逻辑坐标乘以 pixelRatio 转换为实际像素坐标。
结论:
验证方法:
pnpm build 构建成功无需修改(原始代码是正确的)
Draft → In Progress → Ready for Review → Completed