由于您的变换似乎没有倾斜或旋转属性,因此最简单的可能是不转换上下文,而是缩放和转换所有坐标。
目前,你将lineWidth设置为1 / zoom,考虑到编码器对数学精度的好处,你将很难用最终画出一个完美的1px笔画,只有几个缩放值,如果你想限制你的缩放到这些值,你会得到不稳定的变焦。
相反,始终将lineWidth保持在1px,缩放并平移所有坐标,然后将它们舍入到最近的像素边界。
context.setTransform(1,0,0,1,0,0);
context.lineWidth = 1;
context.beginPath();
for (let i = from; i < to; ++i) {
let v1 = instructions.f32[i 4 + 1];
let v2 = instructions.f32[i 4 + 2];
// scale and translate
v1 = (v1 + transform.x) transform.k;
v2 = (v2 + transform.y) transfrom.k;
// round
const r1 = Math.round(v1);
const r2 = Math.round(v2);
// to nearest px boundary
v1 = r1 + (0.5 Math.sign(r1 - v1) || 0.5);
v2 = r2 + (0.5 Math.sign(r2 - v2) || 0.5);
// lineTo…
}
</code>
const pts = [60, 60, 60, 110, 100,110, 100, 90, 220, 90];
const zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on(“zoom”, zoomed);
const transform = {k: 1, x: 0, y: 0};
const context = canvas.getContext(‘2d’);
d3.select(‘canvas’)
.call(zoom);
draw();
function draw() {
context.setTransform(1,0,0,1,0,0);
context.clearRect(0,0,canvas.width, canvas.height);
context.lineWidth = 1;
context.beginPath();
for (let i = 0; i < pts.length; i+=2) {
let v1 = pts[i];
let v2 = pts[i + 1];
// scale and translate
v1 = (v1 + transform.x) * transform.k;
v2 = (v2 + transform.y) * transform.k;
// round
const r1 = Math.round(v1);
const r2 = Math.round(v2);
// to nearest px boundary
v1 = r1 + (0.5 * Math.sign(r1 - v1) || 0.5);
v2 = r2 + (0.5 * Math.sign(r2 - v2) || 0.5);
context.lineTo(v1, v2);
}
context.stroke();
}
function zoomed() {
const evt = d3.event;
transform.k = evt.scale;
transform.x = evt.translate[0];
transform.y = evt.translate[1];
draw();
}
canvas {border: 1px solid}
zoom with mousewheel and pan by dragging
但是你可能更喜欢不那么精确但也不那么锯齿和更简单的地板:
v1 = (v1 + transform.x) transform.k;
v2 = (v2 + transform.y) transform.k;
// floor
v1 = Math.floor(v1) + 0.5;
v2 = Math.floor(v2) + 0.5;
// lineTo
</code>
const pts = [60, 60, 60, 110, 100,110, 100, 90, 220, 90];
const zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on(“zoom”, zoomed);
const transform = {k: 1, x: 0, y: 0};
const context = canvas.getContext(‘2d’);
d3.select(‘canvas’)
.call(zoom);
draw();
function draw() {
context.setTransform(1,0,0,1,0,0);
context.clearRect(0,0,canvas.width, canvas.height);
context.lineWidth = 1;
context.beginPath();
for (let i = 0; i < pts.length; i+=2) {
let v1 = pts[i];
let v2 = pts[i + 1];
// scale and translate
v1 = (v1 + transform.x) * transform.k;
v2 = (v2 + transform.y) * transform.k;
// floor
v1 = Math.floor(v1) + 0.5;
v2 = Math.floor(v2) + 0.5;
context.lineTo(v1, v2);
}
context.stroke();
}
function zoomed() {
const evt = d3.event;
transform.k = evt.scale;
transform.x = evt.translate[0];
transform.y = evt.translate[1];
draw();
}
canvas {border: 1px solid}
zoom with mousewheel and pan by dragging