如何在 HTML canvas 元素之外绘制?
How to draw outside of an HTML canvas element?
我有一个 HTML canvas 元素并实现了一个画笔来捕获 mousedown
、mousemove
和 mouseup
事件 canvas 元素。这一切都适用于在 canvas 上绘图。但是,我不认为我喜欢如果您的鼠标离开 canvas 中间笔画就无法继续绘图的方式。它有点像切断它。这对这个人来说是非常无情的,在我看来也不是很人性化。
如果您打开 Microsoft Paint 并开始使用画笔或椭圆或其他工具绘图,只要您在 canvas 内开始,您可以将鼠标拖动到屏幕上的任意位置并重新输入 canvas无论哪里。它还可以轻松地在角落绘制四分之一圆,因为您可以将椭圆工具拖出屏幕。我希望这是有道理的。
无论如何,我想知道是否有一种方法可以使用 HTML5 canvas 来实现它,或者我将如何实现这种事情。用户永远不必实际看到那里绘制的任何东西;它主要只是一个可用性功能。
编辑:很多这些解决方案的一个问题是如何处理坐标。目前我的canvas在屏幕中间,canvas的左上角是(0, 0)
,右下角是(500, 500)
。还要考虑坐标的平移工作
Edit2:我发现显然你可以画出 canvas 边界就好了。例如,您可以提供负宽度、高度和坐标,canvas 元素会很好地处理它。所以基本上解决方案可能涉及只捕获文档的 mousemove
和 mouseup
并只翻译 x
和 y
以从 canvas 的左上角开始角落.
重新输入 canvas 时,您可以通过以下方式继续绘图:
- 创建一个全局变量并在鼠标按下时将该变量设置为 true
- 为 mouseup 添加一个全局事件,这样您就可以捕捉到有人在外面这样做
canvas,如果是,设置全局变量为false,canvas元素的mouseup当然也需要设置相同的变量
- 在 mousemove 上,在绘制之前检查全局变量是否为真
要绘制 "outside" canvas,就像角落中的四分之一圆一样,我会将所有事件作为全局处理程序移动到文档级别,并在单击时捕获 canvas 元素并传递其客户端坐标以与文档坐标一起计算。
这是一个非常粗略的初稿,说明如何在 window 而不是 canvas 上监听鼠标事件以便能够连续绘制:
var logger = document.getElementById("logger"),
mState = document.getElementById("mState"),
mX = document.getElementById("mX"),
mY = document.getElementById("mY"),
cX = document.getElementById("cX"),
cY = document.getElementById("cY"),
c = document.getElementById("canvas"),
ctx = c.getContext("2d");
var mouse = {
x: 0,
y: 0,
state: ""
};
function printCanvasLocation() {
var b = c.getBoundingClientRect();
cX.innerHTML = b.top;
cY.innerHTML = b.left;
}
function setState(mouseE, state) {
mouse.x = mouseE.clientX;
mouse.y = mouseE.clientY;
mX.innerHTML = mouseE.clientX;
mY.innerHTML = mouseE.clientY;
if (state) {
mState.innerHTML = state;
mouse.state = state;
}
}
window.addEventListener("mousedown", function(mouseE) {
setState(mouseE, "down");
});
window.addEventListener("mouseup", function(mouseE) {
setState(mouseE, "up");
});
window.addEventListener("mousemove", function(mouseE) {
var offset = c.getBoundingClientRect();
var fix = {
x1: (mouse.x - offset.left),
y1: (mouse.y - offset.top),
x2: (mouseE.clientX - offset.left),
y2: (mouseE.clientY - offset.top)
};
if (mouse.state === "down") {
ctx.moveTo(fix.x1, fix.y1);
ctx.lineTo(fix.x2, fix.y2);
ctx.strokeStyle = "#000";
ctx.stroke();
}
setState(mouseE);
});
window.addEventListener("resize", function() {
printCanvasLocation();
});
printCanvasLocation();
.center {
text-align: center;
}
canvas {
background-color: lightblue;
}
<main>
<div class="center">
<canvas id="canvas" width="128" height="128">If you can see me, you should update your browser</canvas>
</div>
<div id="logger" role="log">
<span>State: </span><span id="mState">Unknown</span>
<span>X: </span><span id="mX">Unknown</span>
<span>Y: </span><span id="mY">Unknown</span>
<span>Canvas X: </span><span id="cX">Unknown</span>
<span>Canvas Y: </span><span id="cY">Unknown</span>
</div>
</main>
一种解决方案是按字面意思使 canvas 成为 window 的大小,并随其缩放。 canvas 可以大部分透明。
我相信还有一种方法可以使鼠标事件等先通过 canvas,然后再传递到后面的元素,如果需要的话。 (参见:"js events bubbling and capturing"。)
但是这样你就可以拥有绝对的控制权,可以在任何地方画任何东西。
我有一个 HTML canvas 元素并实现了一个画笔来捕获 mousedown
、mousemove
和 mouseup
事件 canvas 元素。这一切都适用于在 canvas 上绘图。但是,我不认为我喜欢如果您的鼠标离开 canvas 中间笔画就无法继续绘图的方式。它有点像切断它。这对这个人来说是非常无情的,在我看来也不是很人性化。
如果您打开 Microsoft Paint 并开始使用画笔或椭圆或其他工具绘图,只要您在 canvas 内开始,您可以将鼠标拖动到屏幕上的任意位置并重新输入 canvas无论哪里。它还可以轻松地在角落绘制四分之一圆,因为您可以将椭圆工具拖出屏幕。我希望这是有道理的。
无论如何,我想知道是否有一种方法可以使用 HTML5 canvas 来实现它,或者我将如何实现这种事情。用户永远不必实际看到那里绘制的任何东西;它主要只是一个可用性功能。
编辑:很多这些解决方案的一个问题是如何处理坐标。目前我的canvas在屏幕中间,canvas的左上角是(0, 0)
,右下角是(500, 500)
。还要考虑坐标的平移工作
Edit2:我发现显然你可以画出 canvas 边界就好了。例如,您可以提供负宽度、高度和坐标,canvas 元素会很好地处理它。所以基本上解决方案可能涉及只捕获文档的 mousemove
和 mouseup
并只翻译 x
和 y
以从 canvas 的左上角开始角落.
重新输入 canvas 时,您可以通过以下方式继续绘图:
- 创建一个全局变量并在鼠标按下时将该变量设置为 true
- 为 mouseup 添加一个全局事件,这样您就可以捕捉到有人在外面这样做 canvas,如果是,设置全局变量为false,canvas元素的mouseup当然也需要设置相同的变量
- 在 mousemove 上,在绘制之前检查全局变量是否为真
要绘制 "outside" canvas,就像角落中的四分之一圆一样,我会将所有事件作为全局处理程序移动到文档级别,并在单击时捕获 canvas 元素并传递其客户端坐标以与文档坐标一起计算。
这是一个非常粗略的初稿,说明如何在 window 而不是 canvas 上监听鼠标事件以便能够连续绘制:
var logger = document.getElementById("logger"),
mState = document.getElementById("mState"),
mX = document.getElementById("mX"),
mY = document.getElementById("mY"),
cX = document.getElementById("cX"),
cY = document.getElementById("cY"),
c = document.getElementById("canvas"),
ctx = c.getContext("2d");
var mouse = {
x: 0,
y: 0,
state: ""
};
function printCanvasLocation() {
var b = c.getBoundingClientRect();
cX.innerHTML = b.top;
cY.innerHTML = b.left;
}
function setState(mouseE, state) {
mouse.x = mouseE.clientX;
mouse.y = mouseE.clientY;
mX.innerHTML = mouseE.clientX;
mY.innerHTML = mouseE.clientY;
if (state) {
mState.innerHTML = state;
mouse.state = state;
}
}
window.addEventListener("mousedown", function(mouseE) {
setState(mouseE, "down");
});
window.addEventListener("mouseup", function(mouseE) {
setState(mouseE, "up");
});
window.addEventListener("mousemove", function(mouseE) {
var offset = c.getBoundingClientRect();
var fix = {
x1: (mouse.x - offset.left),
y1: (mouse.y - offset.top),
x2: (mouseE.clientX - offset.left),
y2: (mouseE.clientY - offset.top)
};
if (mouse.state === "down") {
ctx.moveTo(fix.x1, fix.y1);
ctx.lineTo(fix.x2, fix.y2);
ctx.strokeStyle = "#000";
ctx.stroke();
}
setState(mouseE);
});
window.addEventListener("resize", function() {
printCanvasLocation();
});
printCanvasLocation();
.center {
text-align: center;
}
canvas {
background-color: lightblue;
}
<main>
<div class="center">
<canvas id="canvas" width="128" height="128">If you can see me, you should update your browser</canvas>
</div>
<div id="logger" role="log">
<span>State: </span><span id="mState">Unknown</span>
<span>X: </span><span id="mX">Unknown</span>
<span>Y: </span><span id="mY">Unknown</span>
<span>Canvas X: </span><span id="cX">Unknown</span>
<span>Canvas Y: </span><span id="cY">Unknown</span>
</div>
</main>
一种解决方案是按字面意思使 canvas 成为 window 的大小,并随其缩放。 canvas 可以大部分透明。
我相信还有一种方法可以使鼠标事件等先通过 canvas,然后再传递到后面的元素,如果需要的话。 (参见:"js events bubbling and capturing"。)
但是这样你就可以拥有绝对的控制权,可以在任何地方画任何东西。