Javascript 无JS库的画布上HTML5拖放路径
我想在HTML5画布上拖放路径Javascript 无JS库的画布上HTML5拖放路径,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我想在HTML5画布上拖放路径 如果我们单击形状,我没有发现SVG提供的任何事件。 有人知道我如何处理路径项上的事件吗?我想在没有任何java脚本库的情况下实现这一点 以下是我当前绘制路径的代码: var canvas = document.getElementById("html5Canvas"); var context = canvas.getContext("2d"); var drawing = false; canvas.addEventListener("mousedown",
如果我们单击形状,我没有发现SVG提供的任何事件。
有人知道我如何处理路径项上的事件吗?我想在没有任何java脚本库的情况下实现这一点 以下是我当前绘制路径的代码:
var canvas = document.getElementById("html5Canvas");
var context = canvas.getContext("2d");
var drawing = false;
canvas.addEventListener("mousedown", startDraw, false);
canvas.addEventListener("mousemove", continueDraw, false);
canvas.addEventListener("mouseup", endDraw, false
function startDraw(event)
{
drawing = true;
context.moveTo(event.clientX, event.clientY);
}
function continueDraw(event)
{
if (drawing)
{
context.lineTo(event.clientX, event.clientY);
context.stroke();
}
}
function endDraw(event)
{
if (drawing)
{
context.lineTo(event.clientX, event.clientY);
context.stroke();
drawing = false;
}
}
谢谢。准备工作
为了检测线点击,我们需要记录所有路径信息
下面的示例是原始post中提供的代码的修改版本,包括一个笔划记录器,它将每个笔划(在鼠标按下和鼠标按下之间)记录到一个包含所有笔划的数组中
为了简单起见,我们在这里听鼠标点击时,我们改变模式。在单击模式下,我们迭代笔划集合并重新构建之前记录的路径,然后检查鼠标位置是否在其中一行中
在构建路径之前,可以通过使用命中区域来优化代码,以减少开销,但为了演示,仅包含基本代码:
演示代码
为了记录,我们需要一些东西来存储线条/笔划:
var lines = [], line;
我们添加了一个事件侦听器,用于切换模式时使用的单击。请注意,通常情况下,您可能会共享鼠标向下/向上事件:
canvas.addEventListener("click", checkLine, false);
为了使线条更“可点击”,我们在这里使用了更粗的线条宽度(固定用于演示):
为了记录,我们需要修改现有的回调。还有一个错误,它会导致每移动一次鼠标,线条都会从上到下重新绘制,如果线条较长,最终会减慢绘制速度
我们还需要调整鼠标位置,使其相对于画布:
function startDraw(event) {
/// if we are in "click" mode exit from here (for demo)
if (mode.checked === true) return;
/// adjust mouse position
var pos = mouseXY(canvas, event);
drawing = true;
/// start a new path
context.beginPath();
context.moveTo(pos.x, pos.y);
/// create a new stroke and push first position to it
line = [];
line.push([pos.x, pos.y]);
}
对于我们绘制的每个部分,我们需要重置路径,以便不重画整条线(在最终渲染/重画中,您当然只需一次重画线,但不是在绘制时):
最后一行完成后,我们存储笔划:
function endDraw(event) {
if (drawing) {
var pos = mouseXY(canvas, event);
context.lineTo(pos.x, pos.y);
context.stroke();
drawing = false;
/// push stroke/line to line stack
lines.push(line);
}
}
我们使用它来调整鼠标位置::
function mouseXY(c, e) {
var r = c.getBoundingClientRect();
return {x: e.clientX - r.left, y: e.clientY - r.top};
}
检查线路点击
要检查一行,我们需要迭代我们的行集合,并将每一行重建为一条路径。无需绘制这些路径,因此速度正常。重建路径时,我们使用isPointInStroke
,对照路径检查调整后的鼠标位置:
function checkLine(e) {
if (mode.checked === false) return;
var i = 0, line, l, p, pos = mouseXY(canvas, e);
/// make sure stroke has same width as originally recorded
context.lineWidth = 3;
/// loop through line collection
for(; line = lines[i]; i++) {
/// reset path
context.beginPath();
/// begin stroke
context.moveTo(line[0][0], line[0][1]);
/// iterate through each point stored
for(l = 1; p = line[l]; l++) {
/// add a line
context.lineTo(p[0], p[1]);
}
/// then we check the point
if (context.isPointInStroke(pos.x, pos.y) === true) {
alert('hit line ' + i); /// show "ID" of line clicked
return;
}
}
}
即使是复杂的重叠线也可以毫无问题地检测到:
(是的,我知道!我随时都可以打败Dali和Munch!X-p)我们可以检测单击,但是如果我们有直线并且它们相交,如何检测哪条直线被单击?重建路径(不绘制路径),然后使用isPointInStroke()方法。对于下一个形状,重复步骤。在某些浏览器中,该方法可能需要加前缀。在未来,路径将对我们可用,这使事情变得更容易,但现在我们需要为每个检查重新构建全局路径。另见:
function mouseXY(c, e) {
var r = c.getBoundingClientRect();
return {x: e.clientX - r.left, y: e.clientY - r.top};
}
function checkLine(e) {
if (mode.checked === false) return;
var i = 0, line, l, p, pos = mouseXY(canvas, e);
/// make sure stroke has same width as originally recorded
context.lineWidth = 3;
/// loop through line collection
for(; line = lines[i]; i++) {
/// reset path
context.beginPath();
/// begin stroke
context.moveTo(line[0][0], line[0][1]);
/// iterate through each point stored
for(l = 1; p = line[l]; l++) {
/// add a line
context.lineTo(p[0], p[1]);
}
/// then we check the point
if (context.isPointInStroke(pos.x, pos.y) === true) {
alert('hit line ' + i); /// show "ID" of line clicked
return;
}
}
}