我正在使用画布使用 D3 线生成器,我注意到,如果
lineCap
设置为 round
或 square
,Chrome 在显示独立数据点时的行为与其他浏览器不同。
在下面的屏幕截图中,我绘制了以下数据集的三倍。
const datapoints = [0, 1, null, 3, null, 5, 6, 7, 8];
数据点
3
是孤立的,因为它的前后是 null
和线生成器组
line().defined(d => d !== null)
因此点
1-3
和 3-5
之间会有间隙。
所有三条线都使用相同的线发生器。三者之间的区别在于,红线有
lineCap = 'butt'
,蓝线有 lineCap = 'round'
,绿线有 lineCap = butt
,但它在数据点不是 null
的地方添加了圆圈。
从屏幕截图中可以看到,在 Chrome 中,蓝线呈现孤立的数据点,而在 Firefox(和 Safari)上则不然。
我承认 Chrome 的行为很方便,因为我可以在屏幕上获得孤立的数据点,而无需手动放置它们。你知道是否有办法在 Firefox(和 Safari)上达到相同的结果?
您可以在此处找到代码。
这是处理绘图的代码中有意义的部分,但是您可以在此沙箱中找到代码。
const brush = line()
.defined((d) => d !== null)
.x((d) => scale(d))
.curve(curveLinear)
.context(ctx);
function drawLine(
data,
y,
{ color = "black", lineCap = "butt", points = false }
) {
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = 2;
ctx.lineCap = lineCap;
ctx.beginPath();
brush.y(y)(data);
if (points) {
data.forEach((point) => {
ctx.moveTo(scale(point), y);
ctx.arc(scale(point), y, 1, 0, Math.PI * 2);
});
}
ctx.stroke();
ctx.restore();
}
const datapoints = [0, 1, null, 3, null, 5, 6, 7, 8];
drawLine(datapoints, 120, { color: "darkred" });
drawLine(datapoints, 140, { color: "darkblue", lineCap: "round" });
drawLine(datapoints, 160, { color: "darkgreen", points: true });
通过跟踪D3代码,我发现Chrome在时绘制了一个由线帽
组成的点通过删除第二个
moveTo
调用,不会显示任何内容。
我不确定这种行为是否应该被视为错误,因为在高级别上,我们可以看到上面描述的序列,即画笔移动到某个位置,然后再次移动,从不接触画布。
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(160, 20);
ctx.closePath();
ctx.moveTo(161, 20); // < this
ctx.stroke();
嗯,抚摸零长度线而不关闭路径,适用于 Firefox/Win 中的
'square'
和 'round'
线帽。 ('butt'
盖子不会被渲染,只是因为它们不会向最终形状添加任何区域,因此空的部分仍然是空的。)
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(0 0 0 / 10%)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
function strokeZeroLine (x, y, lineCap) {
ctx.lineCap = lineCap;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y);
ctx.stroke();
}
ctx.lineWidth = 10;
strokeZeroLine(40, 20, 'butt');
strokeZeroLine(40, 40, 'square');
strokeZeroLine(40, 60, 'round');
<canvas id="canvas" width="80" height="80"></canvas>