【发布时间】:2017-02-01 21:03:34
【问题描述】:
我有一个canvas,我可以在其中用鼠标绘图。
有时我可以旋转和缩放画布容器。
我想要的是仍然可以绘制,但我现在遇到的问题是鼠标坐标被旋转和缩放。
unrotate 和 unscale 鼠标坐标以便从用户的角度正常渲染新绘图的正确方法是什么?
我尝试将X 坐标切换为Y,但无法正确计算。
代码和小提琴
HTML
<div id="canvasDiv">
<canvas id="canvas"></canvas>
</div>
<button>Rotate & Scale</button>
CSS
div
{
outline: 1px solid red;
text-align: center;
width: 250px;
height: 250px;
position: relative;
}
canvas
{
outline: 1px solid blue;
width: 250px;
height: 250px;
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
z-index: 5;
}
.transformed
{
transform: rotate(90deg) scale(1.4);
margin-top: 75px;
margin-left: 75px;
}
JS
isMouseDown = false;
canvas_offset = {left: 0, top: 0};
mouse = {x1: 0, y1: 0, x2: 0, y2: 0};
ppts = [];
canvas = $('#canvas').get(0);
ctx = canvas.getContext('2d');
canvas_container = $('#canvasDiv').get(0);
canvas_container_style = getComputedStyle(canvas_container);
canvas.width = parseInt(canvas_container_style.getPropertyValue('width'));
canvas.height = parseInt(canvas_container_style.getPropertyValue('height'));
var offset = $('#canvas').offset();
canvas_offset.left = offset.left;
canvas_offset.top = offset.top;
// Creating a tmp canvas
tmp_canvas = document.createElement('canvas');
tmp_ctx = tmp_canvas.getContext('2d');
tmp_canvas.id = 'tmp_canvas';
tmp_canvas.width = canvas.width;
tmp_canvas.height = canvas.height;
tmp_canvas.area = tmp_canvas.getBoundingClientRect();
canvas_container.appendChild(tmp_canvas);
$(document).on("mousedown", tmp_canvas, function(e)
{
mouse.x1 = parseInt(e.clientX - tmp_canvas.area.left);
mouse.y1 = parseInt((e.clientY - tmp_canvas.area.top - canvas_offset.top) + $(document).scrollTop());
ppts.push({
x: mouse.x1,
y: mouse.y1,
size: 1,
color: "#000000"
});
isMouseDown = true;
});
$(document).on("mouseup", tmp_canvas, function(e)
{
isMouseDown = false;
ctx.drawImage(tmp_canvas, 0, 0);
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
ppts = [];
});
$(document).on("mousemove", tmp_canvas, function(e)
{
mouse.x2 = parseInt(e.clientX - tmp_canvas.area.left);
mouse.y2 = parseInt((e.clientY - tmp_canvas.area.top - canvas_offset.top) + $(document).scrollTop());
if(isMouseDown)
{
onPaint();
}
});
var onPaint = function()
{
// Saving all the points in an array
ppts.push({
x: mouse.x2,
y: mouse.y2,
size: 1,
color: "#000000"
});
if(ppts.length < 3)
{
var b = ppts[0];
tmp_ctx.beginPath();
//ctx.moveTo(b.x, b.y);
//ctx.lineTo(b.x+50, b.y+50);
tmp_ctx.arc(b.x, b.y, tmp_ctx.lineWidth / 2, 0, Math.PI * 2, !0);
tmp_ctx.fill();
tmp_ctx.closePath();
return;
}
// Tmp canvas is always cleared up before drawing.
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.beginPath();
tmp_ctx.moveTo(ppts[0].x, ppts[0].y);
for(var i = 1; i < ppts.length - 2; i++)
{
var c = (ppts[i].x + ppts[i + 1].x) / 2;
var d = (ppts[i].y + ppts[i + 1].y) / 2;
tmp_ctx.lineWidth = ppts[i].size;
tmp_ctx.strokeStyle = ppts[i].color;
tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
}
// For the last 2 points
tmp_ctx.quadraticCurveTo(
ppts[i].x,
ppts[i].y,
ppts[i + 1].x,
ppts[i + 1].y
);
tmp_ctx.stroke();
};
$("button").click(function()
{
$("div").addClass("transformed");
});
【问题讨论】:
-
您需要将相同的变换应用到您应用到画布的鼠标位置。如果您将画布旋转 90 度,那么您需要计算它也旋转 90 度的补偿鼠标位置。如果画布已经缩放了 1.4,那么鼠标位置需要缩放 1.4 等等。
-
您将需要应用逆变换矩阵。请参阅此答案。 stackoverflow.com/a/34598847/3877726
-
@Blindman67 这看起来很有希望!我会测试一下,然后再回来
-
Matias,只需确认@Blindman67 的信息是正确的——使用变换矩阵跟踪您所做的旋转,然后反转该矩阵以“取消旋转”鼠标坐标。请参阅显示 A Transformation Matrix to track translated, rotated & scaled shape(s) 的此文档。
-
@markE 感谢您的确认和链接。我很难实现逆矩阵,因为我是画布和 css3 的新手。一旦我让它工作,我会发布并回答
标签: javascript html canvas html5-canvas