我正在开发一款需要扩展(通过style.width
,而不是scale(...)
),翻译(translate(x, y)
)和转动(例如rotate(90deg)
}的应用)一个画布元素。然后我需要在画布上计算正确的鼠标点击位置。也就是说,我需要这样做,以便行的末尾实际出现在用户点击的位置。现在,当我尝试合并翻译时,我的计算结果略有不同,您可以通过在下面的演示画布中点击两次来看到。
让我感到困惑的一部分是我应该做哪些顺序来翻译,取消旋转和不缩小以产生正确的结果。
演示代码:
var canvas = document.getElementById("canvas");
var scaleX = 0.5;
var scaleY = 0.5;
var rot = 1;
var dispWidth = (canvas.width * scaleX);
var dispHeight = (canvas.height * scaleY);
var xlateX = Math.floor((dispHeight - dispWidth) / 2);
var xlateY = Math.floor((dispWidth - dispHeight) / 2);
var transform = "translate(" + xlateX + "px, " + xlateY + "px) rotate(" + (rot * 90) + "deg)";
canvas.style.width = dispWidth + "px";
canvas.style.height = dispHeight + "px";
canvas.style.transform = transform;
var context = canvas.getContext("2d");
var stack = [];
canvas.onclick = function (e) {
var rect = canvas.getBoundingClientRect();
console.log('rect', rect.left, rect.top);
// position within canvas, ignoring scroll
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
console.log('original', x, y);
// scale
x /= scaleX;
y /= scaleY;
console.log('scaled', x, y);
// translate
x -= xlateX;
y -= xlateY;
console.log('translated', x, y);
var tmp;
switch (rot % 4) {
case 1:
tmp = x;
x = y;
y = canvas.height - tmp;
break;
case 2:
y = canvas.height - tmp;
x = canvas.width - tmp;
break;
case 3:
tmp = y;
y = x;
x = canvas.width - tmp;
break;
default:
break;
}
console.log('rotated', x, y);
stack.push({x: x, y: y});
if (stack.length > 1) {
context.beginPath();
context.moveTo(stack[0].x, stack[0].y);
context.lineTo(stack[1].x, stack[1].y);
context.stroke();
stack = [];
}
};

Click once to start a line. Click again to finish it.
<br>
<canvas id="canvas" width="600" height="400" style="border: 1px solid black;"></canvas>
&#13;