如何在HTML5画布中创建可拖动线? [英] How to Create a Draggable Line in HTML5 Canvas?

查看:106
本文介绍了如何在HTML5画布中创建可拖动线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,如果您在HTML5画布上画一条线,使其在onMouseDrag上可拖动的最佳方法是什么?我知道您可以在SVG中很容易地做到这一点,但是由于画布并不是那么容易使用,所以我想知道一个很好的解决方案.

So if you draw a line on an HTML5 canvas, what is the best way to make it draggable onMouseDrag? I know you can do this very easily in SVG, but since the canvas is not as easy to work with, I would like to know a good solution to this.

推荐答案

这是在html5画布上创建可拖动线条的一种方法.

关于html5画布的注释:您不能真正移动已经在html5画布上绘制的任何内容.相反,您可以通过清除画布并在新位置重新绘制所有内容来模拟运动.

A Note about html5 canvas: You can't really move anything that has already been drawn on html5 canvas. Instead you simulate movement by clearing the canvas and redrawing everything in it's new position.

这是让用户在画布上拖动"一行的方法:

This is how to let the user "drag" a line on the canvas:

  1. 创建定义一些行的对象数组:{x0:,y0:,x1:,y1:}.

mousedown上,计算最接近鼠标位置的那一行.

On mousedown, calculate which line is closest to the mouse position.

设置一个标志,指示正在拖动一行.

Set a flag indicating that a line is being dragged.

mousemove上,将拖动线的X,Y更改为鼠标具有的距离 从上一个mousemove开始移动.然后清除画布,并在其当前位置重新绘制所有线条.

On mousemove, change the dragged line's X,Y by the distance the mouse has moved since the last mousemove. Then clear the canvas and redraw all lines in their current position.

mouseupmouseout上,清除拖动标记.

On mouseup or mouseout, clear the dragging flag.

以下是带注释的代码和演示:

// canvas vars
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

// dragging vars
var isDown=false;
var startX,startY;

// line vars
var nearest;
var lines=[];
lines.push({x0:75, y0:25, x1:125,y1:25});
lines.push({x0:75, y0:100, x1:125, y1:100});
lines.push({x0:50, y0:35, x1:50,y1:85});
lines.push({x0:150,y0:35, x1:150,y1:85});

draw();

// listen for mouse events
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUpOut(e);});
$("#canvas").mouseout(function(e){handleMouseUpOut(e);});


// functions
//////////////////////////

// select the nearest line to the mouse
function closestLine(mx,my){
    var dist=100000000;
    var index,pt;
    for(var i=0;i<lines.length;i++){
        //
        var xy=closestXY(lines[i],mx,my);
        //
        var dx=mx-xy.x;
        var dy=my-xy.y;
        var thisDist=dx*dx+dy*dy;
        if(thisDist<dist){
            dist=thisDist;
            pt=xy;
            index=i;
        }
    }
    var line=lines[index];
    return({ pt:pt, line:line, originalLine:{x0:line.x0,y0:line.y0,x1:line.x1,y1:line.y1} });
}

// linear interpolation -- needed in setClosestLine()
function lerp(a,b,x){return(a+x*(b-a));}

// find closest XY on line to mouse XY
function closestXY(line,mx,my){
    var x0=line.x0;
    var y0=line.y0;
    var x1=line.x1;
    var y1=line.y1;
    var dx=x1-x0;
    var dy=y1-y0;
    var t=((mx-x0)*dx+(my-y0)*dy)/(dx*dx+dy*dy);
    t=Math.max(0,Math.min(1,t));
    var x=lerp(x0,x1,t);
    var y=lerp(y0,y1,t);
    return({x:x,y:y});
}

// draw the scene
function draw(){
    ctx.clearRect(0,0,cw,ch);
    // draw all lines at their current positions
    for(var i=0;i<lines.length;i++){
        drawLine(lines[i],'black');
    }
    // draw markers if a line is being dragged
    if(nearest){
        // point on line nearest to mouse
        ctx.beginPath();
        ctx.arc(nearest.pt.x,nearest.pt.y,5,0,Math.PI*2);
        ctx.strokeStyle='red';
        ctx.stroke();
        // marker for original line before dragging
        drawLine(nearest.originalLine,'red');
        // hightlight the line as its dragged
        drawLine(nearest.line,'red');
    }
}

function drawLine(line,color){
    ctx.beginPath();
    ctx.moveTo(line.x0,line.y0);
    ctx.lineTo(line.x1,line.y1);
    ctx.strokeStyle=color;
    ctx.stroke();
}

function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  // mouse position
  startX=parseInt(e.clientX-offsetX);
  startY=parseInt(e.clientY-offsetY);
  // find nearest line to mouse
  nearest=closestLine(startX,startY);
  draw();
  // set dragging flag
  isDown=true;
}

function handleMouseUpOut(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  // clear dragging flag
  isDown=false;
  nearest=null;
  draw();
}

function handleMouseMove(e){
    if(!isDown){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // mouse position
    mouseX=parseInt(e.clientX-offsetX);
    mouseY=parseInt(e.clientY-offsetY);
    // calc how far mouse has moved since last mousemove event
    var dx=mouseX-startX;
    var dy=mouseY-startY;
    startX=mouseX;
    startY=mouseY;
    // change nearest line vertices by distance moved
    var line=nearest.line;
    line.x0+=dx;
    line.y0+=dy;
    line.x1+=dx;
    line.y1+=dy;
    // redraw
    draw();
}

body{ background-color: ivory; }
#canvas{border:1px solid red; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Drag the lines...</h4>
<canvas id="canvas" width=300 height=300></canvas>

这篇关于如何在HTML5画布中创建可拖动线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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