HTML5在没有JS库的画布上拖放路径 [英] HTML5 drag and drop path on canvas without JS library

查看:114
本文介绍了HTML5在没有JS库的画布上拖放路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在HTML5画布上拖放路径。

我没有发现任何东西像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;
.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 ;
}
}

谢谢。

解决方案

准备



为了检测线单击,我们需要记录所有路径信息。 p>

以下示例是原始帖子中提供的代码的修改版本,包括一个笔划记录器,其将每个笔划(在鼠标向下和鼠标向下之间)记录到包含所有



为了简单起见,当我们改变模式时,我们在这里听到鼠标点击。在点击模式中,我们迭代笔画集合,重新创建我们之前记录的路径,以检查我们的鼠标位置是否在这些行之一。



代码可以通过在构建路径之前使用命中区域来优化,以减少开销,但是为了演示仅包括基本代码:



演示代码



在线示范



要记录,我们需要有一些东西来存储行/笔划:

  var lines = [],line; 

我们为切换模式时使用的点击添加了一个事件监听器。注意,通常你会共享mousedown / up事件,可能改为:

  canvas.addEventListener(click,checkLine,false); 

为了使线条更可点击,我们在这里使用更粗的线宽

  context.lineWidth = 3; 

为了记录,我们需要修改现有的回调。它还有一个错误,它导致线重新绘制彼此的顶部每个鼠标移动,如果线是长的,最终会减慢绘图。



我们还需要调整鼠标位置,使其相对于画布:

  function startDraw(event){

///如果我们在点击模式退出从这里(演示)
if(mode.checked === true)return;

///调整鼠标位置
var pos = mouseXY(canvas,event);

drawing = true;

///开始一个新路径
context.beginPath();
context.moveTo(pos.x,pos.y);

///创建一个新笔画并将第一个位置推送到它
line = [];
line.push([pos.x,pos.y]);
}

对于我们绘制的每个部分,我们需要重置路径,整个行(在你的最终渲染/重画你当然只是重新绘制一行,但不是在绘制它):

  function continueDraw(event){
if(drawing){

///调整鼠标位置
var pos = mouseXY

///完成一个线段从鼠标开始
context.lineTo(pos.x,pos.y);
context.stroke();

///重置路径并从我们结束这一行开始
context.beginPath();
context.moveTo(pos.x,pos.y);

///存储当前点到行/线
line.push([pos.x,pos.y]);
}
}

最后当行结束时,

  function endDraw(event){
if(drawing){
var pos = mouseXY事件);
context.lineTo(pos.x,pos.y);
context.stroke();
drawing = false;

/// push stroke /行到行栈
lines.push(line);
}
}



我们使用这个来调整鼠标位置: p>

  function mouseXY(c,e){
var r = c.getBoundingClientRect
return {x:e.clientX - r.left,y:e.clientY - r.top};
}



检查行点击次数



要检查一行,我们需要遍历我们的行集合并重建每一行作为一个路径。没有必要绘制这些路径,所以速度是OK。当重建路径时,我们通过使用 isPointInStroke

 code> function checkLine(e){
if(mode.checked === false)return;

var i = 0,line,l,p,pos = mouseXY(canvas,e);

///确保笔画与原始记录的宽度相同
context.lineWidth = 3;

///循环通过行集合
for(; line = lines [i]; i ++){

///重置路径
.beginPath();

/// begin stroke
context.moveTo(line [0] [0],line [0] [1]);

///遍历每个点存储
for(l = 1; p = line [l]; l ++){
///添加一行
context.lineTo(p [0],p [1]);
}

///然后我们检查点
if(context.isPointInStroke(pos.x,pos.y)=== true){
alert ('hit line'+ i); /// showIDof line clicked
return;
}
}
}

检测到没有问题:



(是的,我知道!我可以打败大利和蒙克的任何一天!Xp)


I want to drag and drop path on HTML5 canvas.
I didn't find any thing like SVG provides events if we click on shape.
Anyone know how I can handle events on path item here? I want to do this without any java script library.

Following is my current code to draw path:

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;
    }
}

Thanks.

解决方案

Preparations

In order to detect line-clicks we need to record all path information.

The following example is a modified version of the code provided in original post and includes a stroke recorder which records each stroke (between mouse down and mouse down) to an array which contains all strokes.

For simplicity we listen here to mouse clicks when we alter mode. When in click mode we iterate the stroke collection and re-build the paths we previously recorded for then to check if our mouse position is in one of these lines.

The code can be optimized by using a hit region before building paths to reduce overhead but for the sake of demo only the essential code is included:

Demo code

ONLINE DEMO HERE

To record we need to have something to store the lines/strokes in:

var lines = [], line;

We add an event listener for clicks that we'll use when we switch mode. Note that normally you would share mousedown/up events perhaps instead:

canvas.addEventListener("click", checkLine, false);

To make the lines more "clickable" we use a thicker line width here (fixed for demo):

context.lineWidth = 3;

In order to record we need to modify the existing callbacks. There is also a bug in it which causes the line to be redrawn of top of each other for each mouse move which eventually will slow down the drawing if the line is long.

We also need to adjust mouse positions so it becomes relative to canvas:

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]);
}

For each part we draw we need to reset path so we don't redraw the whole line (in your final render/redraw you would of course just redraw the line in one go, but not while drawing it):

function continueDraw(event) {
    if (drawing) {

        /// adjust mouse position
        var pos = mouseXY(canvas, event);

        /// complete one line segment started in mouse down
        context.lineTo(pos.x, pos.y);    
        context.stroke();

        /// reset path and start from where we ended this line
        context.beginPath();
        context.moveTo(pos.x, pos.y);

        /// store current point to stroke/line
        line.push([pos.x, pos.y]);
    }
}

And finally when line is finished we store our stroke:

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);
    }
}

We use this to adjust mouse position::

function mouseXY(c, e) {
    var r = c.getBoundingClientRect();
    return {x: e.clientX - r.left, y: e.clientY - r.top};
}

Checking line clicks

To check a line we need to iterate through our line collection and rebuild each line as a path. There is no need to draw these paths so the speed is OK. When a path is rebuilt we check the adjusted mouse position against the path by using 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;
        }
    }
}

Even complex overlapping lines can be detected with no problem:

(Yes I know! I could beat Dali and Munch any day! X-p )

这篇关于HTML5在没有JS库的画布上拖放路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆