JavaScript canvas fillRect可见边框
JavaScript canvas fillRect visible border
我正在尝试使用 js canvas 渲染直方图,它工作正常,但在使用 fillRect
时我在可见边框方面遇到了一些问题。我知道这是由于桶宽度是浮点数而不是整数引起的,但是将我的桶宽度设置为整数会导致它太大或太小(取决于桶的数量)。所以我的问题是,是否有任何解决方法可以摆脱这个边界?
// problem with bucket width being floating point
const bucketWidth = (Math.round(((desiredHistogramWidth / (data.buckets.length - 1))) * 100) / 100)
for (let i = 0; i < data.buckets.length - 1; ++i) {
ctx.fillStyle = `rgb(${colors[i][0]}, ${colors[i][1]}, ${colors[i][2]})`;
const x = histogramXOffset + i * bucketWidth;
ctx.fillRect(x, histogramHeight, bucketWidth, -data.buckets[i] * heightPixelRatio);
ctx.fillRect(x, histogramHeight + 20, bucketWidth, 20);
}
当桶宽度为浮点数时,可以在这个最小的可重现示例中观察到这种行为。
const data = [
1034,
783,
700,
699,
212,
123,
300,
323,
344,
344,
434,
344,
434,
434,
0,
0
];
const canvas = document.getElementById('histogram');
const ctx = canvas.getContext('2d');
const [ width, height ] = [ canvas.clientWidth, canvas.clientHeight ]
ctx.canvas.width = width;
ctx.canvas.height = height;
const max = Math.max(...data);
const heightPixelRatio = ((height) / max);
const bucketWidth = Math.round(width / (data.length) * 100) / 100
console.log(bucketWidth)
for (let i = 0; i < data.length; ++i) {
ctx.fillStyle = '#000';
const x = i * bucketWidth;
ctx.fillRect(x, height, bucketWidth, -data[i] * heightPixelRatio);
}
.histogram {
width: 600px;
height: 800px;
background: #ebecd2;
}
<canvas id="histogram" class="histogram"></canvas>
这样的事情怎么样:
const data = [
1034, 783, 700, 699,
212, 123, 300, 323,
344, 344, 434, 344,
434, 434, 100, 200
];
const canvas = document.getElementById('histogram');
const ctx = canvas.getContext('2d');
canvas.width = canvas.height = 180;
const heightRatio = canvas.height / Math.max(...data);
const bucketWidth = canvas.width / data.length
for (let i = 0; i < data.length; ++i) {
ctx.fillRect(
i * bucketWidth,
canvas.height,
bucketWidth + 0.5,
-data[i] * heightRatio
);
}
<canvas id="histogram" ></canvas>
要点:
- 对于 bucketWidth 我们只使用
canvas.width / data.length
- 在
fillRect
上,我们 bucketWidth + 0.5
添加了少量
我刚刚尝试的另一个选项是只填充一次:
const data = [
1034, 783, 700, 680,
212, 123, 300, 323,
354, 340, 434, 344,
444, 430, 100, 200
];
const canvas = document.getElementById('histogram');
const ctx = canvas.getContext('2d');
canvas.width = canvas.height = 180;
const heightRatio = canvas.height / Math.max(...data);
const bucketWidth = canvas.width / data.length
for (let i = 0; i < data.length; ++i) {
ctx.rect(
i * bucketWidth,
canvas.height,
bucketWidth,
-data[i] * heightRatio
);
}
ctx.fill()
<canvas id="histogram" ></canvas>
对于有大量桶的情况,你不能一次显示它们,必须有一个下一步按钮或创建某种无限侧滚动,没有太多选择。
0.01
的值不能是不会显示任何内容的有效 bucketWidth
我正在尝试使用 js canvas 渲染直方图,它工作正常,但在使用 fillRect
时我在可见边框方面遇到了一些问题。我知道这是由于桶宽度是浮点数而不是整数引起的,但是将我的桶宽度设置为整数会导致它太大或太小(取决于桶的数量)。所以我的问题是,是否有任何解决方法可以摆脱这个边界?
// problem with bucket width being floating point
const bucketWidth = (Math.round(((desiredHistogramWidth / (data.buckets.length - 1))) * 100) / 100)
for (let i = 0; i < data.buckets.length - 1; ++i) {
ctx.fillStyle = `rgb(${colors[i][0]}, ${colors[i][1]}, ${colors[i][2]})`;
const x = histogramXOffset + i * bucketWidth;
ctx.fillRect(x, histogramHeight, bucketWidth, -data.buckets[i] * heightPixelRatio);
ctx.fillRect(x, histogramHeight + 20, bucketWidth, 20);
}
当桶宽度为浮点数时,可以在这个最小的可重现示例中观察到这种行为。
const data = [
1034,
783,
700,
699,
212,
123,
300,
323,
344,
344,
434,
344,
434,
434,
0,
0
];
const canvas = document.getElementById('histogram');
const ctx = canvas.getContext('2d');
const [ width, height ] = [ canvas.clientWidth, canvas.clientHeight ]
ctx.canvas.width = width;
ctx.canvas.height = height;
const max = Math.max(...data);
const heightPixelRatio = ((height) / max);
const bucketWidth = Math.round(width / (data.length) * 100) / 100
console.log(bucketWidth)
for (let i = 0; i < data.length; ++i) {
ctx.fillStyle = '#000';
const x = i * bucketWidth;
ctx.fillRect(x, height, bucketWidth, -data[i] * heightPixelRatio);
}
.histogram {
width: 600px;
height: 800px;
background: #ebecd2;
}
<canvas id="histogram" class="histogram"></canvas>
这样的事情怎么样:
const data = [
1034, 783, 700, 699,
212, 123, 300, 323,
344, 344, 434, 344,
434, 434, 100, 200
];
const canvas = document.getElementById('histogram');
const ctx = canvas.getContext('2d');
canvas.width = canvas.height = 180;
const heightRatio = canvas.height / Math.max(...data);
const bucketWidth = canvas.width / data.length
for (let i = 0; i < data.length; ++i) {
ctx.fillRect(
i * bucketWidth,
canvas.height,
bucketWidth + 0.5,
-data[i] * heightRatio
);
}
<canvas id="histogram" ></canvas>
要点:
- 对于 bucketWidth 我们只使用
canvas.width / data.length
- 在
fillRect
上,我们bucketWidth + 0.5
添加了少量
我刚刚尝试的另一个选项是只填充一次:
const data = [
1034, 783, 700, 680,
212, 123, 300, 323,
354, 340, 434, 344,
444, 430, 100, 200
];
const canvas = document.getElementById('histogram');
const ctx = canvas.getContext('2d');
canvas.width = canvas.height = 180;
const heightRatio = canvas.height / Math.max(...data);
const bucketWidth = canvas.width / data.length
for (let i = 0; i < data.length; ++i) {
ctx.rect(
i * bucketWidth,
canvas.height,
bucketWidth,
-data[i] * heightRatio
);
}
ctx.fill()
<canvas id="histogram" ></canvas>
对于有大量桶的情况,你不能一次显示它们,必须有一个下一步按钮或创建某种无限侧滚动,没有太多选择。
0.01
的值不能是不会显示任何内容的有效 bucketWidth