如何在html画布中检测和移动/拖动自由流动绘制的线条? [英] how to detect and move/drag the free flow drawn lines in html canvas?

查看:146
本文介绍了如何在html画布中检测和移动/拖动自由流动绘制的线条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的实现是:


  1. 检测mousedown和mousemove是否为true,然后绘制并保存数组中的点。

  2. 在我的mousemove中,我将转换将在

  1. Detect if mousedown and mousemove and if true then draw and saved the points in an array.
  2. In my mousemove I will convert the points that will be drawn in

我转换了 curPath (日期,价值)然后到(X和Y轴 )这样它们就会保存在我画布的实现中。

I converted the curPath to (Date,value) then to (X and Y-axis) so that they will be saved in the implementation in my canvas.

我的问题我将如何检测点[]?这样我就可以突出显示它并拖动它。

My problem is that how will I detect points[] ? so that I can highlight it and drag as well.

推荐答案

更新。

这比我预期的要大。我会继续提高答案的质量。请参阅答案底部的状态。

This is bigger than I expected. I will continue to improve the quality of the answer as I go. See the bottom of the answer for status.

选择。
最简单的方法是检查鼠标距离每个鼠标的距离指向该行,并突出显示具有最近点的线。问题是,当你有很多行和很多点时,它会变慢并变得无法使用。

Picking. The simplest way is to check how far the mouse is from each point in the line, and highlight the line that has the closest point. The problem is that when you have many lines and lots of points it slows down and become unusable.

另一种方法是在每一行存储一些额外的信息以帮助你审查不会被挑选的行。在示例中,我为每一行创建一个边界框,并检查鼠标是在该框内部还是附近。如果是这样,那么我会搜索一行,检查每个线段并保持最接近鼠标的线。

Another ways is to store some extra info on each line to help you vet lines that are not going to be picked. In the example I create a bounding box for each line and check if the mouse is inside or near that box. If so then I search the line some more checking each line segment and keeping the line that is closest to the mouse.

要查看的一些功能。

Helpers.prototype.resetExtent();
Helpers.prototype.extent();
Helpers.prototype.copyOfExtent();

用于查找边界框。 (范围)

Used to find the bounding box. (extent)

function refreshLine(line);

在绘制一条线后调用,需要绘制一组点并添加边界框(范围) ),以及演示的其他内容。

Called after a line is drawn, it takes a set of points drawn and adds the bounding box (extent), plus other stuff for the demo.

function findLineAt(x,y){

此函数获取鼠标的 x,y 位置(或任何)和返回20像素内最近的行。它首先检查边界框,如果它通过它调用

This function takes the x,y position of the mouse (or what ever) and returns the closest line within 20 pixels. It first checks the bounding box, if that passes it calls

Helpers.prototype.getDistToPath = function (line,x,y) {

这使得这条线只是一组点并检查到每条线中心的距离。它还检查检查是否需要更多细节并调用该函数。

This gets the line as just a set of points and checks the distance to the center of each line. It also checks if the check needs more details and calls the function.

Helpers.prototype.distPointToLine = function (x, y, x1, y1, x2, y2) {

此函数将返回从一个点到另一个点的最短距离线。 x,y 是点 x1,y1,x2,y2 是该行。它不检查线段而是检查无限长的线。 Helpers.lineSegPos 属性将保持该行上最近点的标准化位置。如果你需要它。

This function will return the shortest distance from a point to a line. x,y is the point x1,y1,x2,y2 is the line. It does not check the line segment but the line which is infinitely long. Helpers.lineSegPos property will hold the normalised position of the closest point on the line. If you need it.

所以回到 findLineAt(x,y),在所有这些调用之后它将返回如果找到该行,或者如果没有,则为未定义。

So back to findLineAt(x,y), after all those calls it will return the line if found or undefined if not.

突出显示并拖动。

突出显示取决于你。我只是非常快地循环最接近线的色调。你可能希望在它周围放一个边界框。操作简单,只需重新绘制每次更新的最近一行。

Highlighting is up to you. I just cycle the hue of the line closest very quickly. You may wish to put a bounding box around it. Easy to do as all you do is redraw the closest line each update.

工作原理

主循环。
update()

The main loop. update()

处理主循环,每秒调用60次,必须是零件,Draw部分用于绘图和挑选。看看(drawMode ===Pick)。鼠标只在更新中读取,鼠标由鼠标监听器独立设置。在每个循环结束时,我保存鼠标按钮状态 mouse.lastButton ,以便我可以检查鼠标向下和向上移动的时间。

Handles the main loop, is called 60 times a second and has to parts, the Draw section is for drawing and pick for picking. See if(drawMode==="Pick"). The mouse is only read in the update, the mouse is set independently by the mouse listener. At the end of every loop I save the mouse button state mouse.lastButton so that I can check when the mouse moves down and up.

如果鼠标未关闭,在选择部分中我会调用 findLineAt 函数。如果我找到一行(行!== undefined),我会通过更改颜色并绘制它来突出显示该行。

In the pick part if the mouse is not down I call the findLineAt function. If I find a line (line !== undefined) I highlight the line by changing its colour and drawing it.

因为每次更新我都有当前的mouseButton状态和什么这是最后一次更新,我会知道当鼠标按钮第一次向下移动时因为 mouse.button 为真且 mouse.lastButton 是假的。如果鼠标附近有一条线,我在 dragOffX dragOffY 中记录鼠标位置,并设置一个标志拖动到true。我还将画布绘制到另一个画布上作为背景。此时我还会检查哪个鼠标按钮已关闭。如果右键我复制该行并将其设置为要拖动的行,或者如果中间按钮我搜索所有行以在 lineArray 中查找其索引并将其删除,然后只是重绘。

Because every update I have the current mouseButton state and what it was last update, I will know when the mouse button first moves down because mouse.button is true and mouse.lastButton is false. If there is a line near the mouse, I record the mouse position in dragOffX and dragOffY and set a flag dragging to true. I also draw the canvas onto another canvas to keep as background. At this point I also check which mouse button is down. If right button I copy the line and set it as the line to be dragged, or if the middle button I search all the lines to find its index in the lineArray and delete it, then just redraw.

下次更新(1/60秒后)和拖动标志为真 mouse.button 为true且 lastLine (最接近的行)未定义我知道我正在拖动一行。我清除了画布,绘制了画布的保存副本(绘制它的速度更快,然后重新绘制所有的线条,特别是如果你有100条带有1000点的线条),然后重绘我拖动的线条。

Next update (1/60th second later) and dragging flag is true mouse.button is true and lastLine (the line that was closest) is not undefined I know I am dragging a line. I clear the canvas, draw the saved copy of the canvas (it's faster to draw that then redraw all the lines again especially if you have 100's of lines with 1000's of points), and then redraw the line I am dragging.

要练习绘制拖动线的位置,我得到鼠标的距离 dragOffX dragOffY 并设置的转置部分setTransform(1,0,0,1,mouse.x - dragOffX,mouse.y - dragOffY)到那个距离。这具有通过拖动量移动线的效果。我一直这样做,直到鼠标按钮启动。

To workout where to draw the dragged line I get the distance the mouse is from dragOffX and dragOffY and set the transpose part of setTransform(1, 0 , 0, 1, mouse.x - dragOffX, mouse.y - dragOffY) to that distance. That has the effect of moving the line by the drag amount. I keep doing this until the mouse button is up.

删除
下次更新并且mouse.button启动。
如果鼠标按钮已启动并且拖动标志为true,那么我必须放弃该行。此时,从 dragOffX dragOffY 获取鼠标距离,并将其添加到该行中的每个点。有效地移动线。我也更新了边界框。然后我清除屏幕并重新绘制所有线条,从画布上移除线条的旧位置并将其放在新家中。

Drop Next update and mouse.button is up. If the mouse button is up and the dragging flag is true then I must drop the line. At this point a get the mouse distance from dragOffX dragOffY and add it to each point in the line. Effectively moving the line. I also update the bounding box. I then clear the screen and redraw all the line, that removes the old position of the line from the canvas and put it at it's new home.

完成。

代码增长了一点。如果这个答案得到了一些支持,那么我会再清理一下。如果不好则无关紧要..

The code grew a little long. If this answer gets some support then I will clean it up some more. If not well then it does not matter..

它涵盖了你的问题的基础知识,通过鼠标操作检测和移动点。突出显示和移动由点组成的线条。我的观点是每个都有x和y的对象数组。每行存储在 lineArray 中,一行有样式,范围,id 属性,以及一个名为<$ c的数组$ c>行包含所有点。

It covers the basics of your question, detecting and moving points via mouse action. Highlighting and moving lines made of sets of points. My point are arrays of objects each with an x and y. Each line is stored in the lineArray a line has style, extent, id properties, and an array called line with all the points.

有一个鼠标处理程序可以获取所需的鼠标事件。移动,鼠标向下和向上,鼠标移出。鼠标移开可通过关闭鼠标按钮来停止鼠标锁定。当鼠标悬停在画布上时,我也会停止上下文菜单。

There is one mouse handler that takes the required mouse events. Move, mouse down and up, and mouse out. Mouse out stops the mouse locking up by turning the mouse buttons off. I also stop the context menu while the mouse is over the canvas.

我使用requestAnimationFrame来调用更新以使其保持平稳运行。

I use requestAnimationFrame to call update to keep it all running smoothly.

我希望这会对你有所帮助。如果它是你所追求的,我会改进它。如果不是,你将不得不提供更多信息。请问你是否有问题。

I hope this helps you. I will improve it if it is what you are after. If not you will have to give a litte more info. Please do ask if you have problems.

更新。
添加了边框并改进了 Helpers.prototype.getDistToPath(line,x,y)我昨晚忘记修复了。现在它更快,不会错过与x和y轴平行的线。移动屏幕重绘以容纳边界框并添加更多注释。

Updates. Added bounding box and improved the Helpers.prototype.getDistToPath(line,x,y) which I forgot to fix last night. Now its quicker and does not miss lines parallel to x and y axis. Moved screen redraw to accommodate the bounding box and add more comments.

请不要犹豫,询问您是否对此问题有疑问。

Please do not hesitate to ask if you have question to this problem.

function log(){}; // duck up the logs

customCursors ={
encoding:"url('data:image/png;base64,",
drag_small : {
    center : " 25 25,",
    image : "iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAACQElEQVRoQ+2azW7DIAyAYZdJW6vlVmmnvcLe/yH2CjtN6i1Tu0m9rIMsJIYChmCvCWkuqZSA/fkPQyoF83VWl5RSqJtQd8kpjnVyB4QdiA0GghhvcHuIBcYH8h9A5DAxEG4gUhgN8rzbiY/9Hs1zjpAjg0nxiEtIDUQCMwWEI+SKYfJBzorDFkvloSvAXKZTs92K9nAoXlTJYFwV9YofunyNAEWHQALjU9qETijpA2OK9CkaHLJ8NYumBrzBoMss/sK6wkyHDLRJyp6EKsxyZUc9Y5R62mzE5/GYvB+hhNFVMVV+EMZVKGeVpoYxwYHp4IUp3VhxwehwjwFdwIQUwawC84oTJgZkwaQogRfIvzcA/DCkb1m63Eu9sE4CFqQBxgty+hLi/mHocnMOVyzFf96EuHv1AkKopmlE27YW5wiuDHD6Vvo8Ds/daOlggh7pYMbBqdaEnon9zpmve9ejDwSS0f3IRBgYGqOwF2W0dysEKWCskO4dkz1vbADMF9PaQ6OF8qBECT1ndZ6pJ2eMa6upZlGg/mFunF91ncGAFtcBxIDmApPVm4WA5gCD6bCO/Qz0EFzMFrvTnLoip3TfKUbJlb+uA41c60S7cPUQS+Ip8syYm2eg9dzjoMFK/edy19KxTqI0j4o9Y5LdVXqxXwFy+zYXfHbfZ9IPKWb85QyrXlh1oqxuxTmDdduJ22sSPUgmgUBV/A8gx0OUoWX1jVhMT3leVW8WKgpcHmFtZ3whxw2iZZIWAF9IOod/rPJ+AQ3iOFgpekFcAAAAAElFTkSuQmCC')"
},
}
function setCursor (name){
if(name === undefined){
    canvas.style.cursor = "default";
}
if(customCursors[name] !== undefined){
    var cur = customCursors[name];
    canvas.style.cursor = customCursors.encoding + cur.image + cur.center + " pointer";
}else{
    canvas.style.cursor = name;
}
}
// get canvas button and creat context2D
var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");
var but = document.getElementById("redrawAllID");
but.addEventListener("click",function(){
if(drawMode === "Pick"){
    drawMode = "Draw";
    but.value = "Draw Mode";
}else{
    drawMode = "Pick";
    but.value = "Pick Mode";
    lastLine = undefined;
    backGroundImage.ctx.clearRect(0,0,backGroundImage.width,backGroundImage.height);
    backGroundImage.ctx.drawImage(canvas,0,0);
}
})
// Groover Bitmaps API dependency replacement
// Extracted from Groover.Bitmaps
var createImage= function(w,h){ // create a image of requier size
var image = document.createElement("canvas"); 
image.width = w;
image.height =h;
image.ctx = image.getContext("2d");  // tack the context onto the image
return image;
} 

var backGroundImage = createImage(canvas.width,canvas.height);
if(!mouse){
// get all the mouse events
canvas.addEventListener('mousemove',mouseMoveEvent);
canvas.addEventListener('mousedown',mouseMoveEvent);
canvas.addEventListener('mouseup'  ,mouseMoveEvent);  
canvas.addEventListener('mouseout'  ,mouseMoveEvent);  
canvas.addEventListener("contextmenu", function(e){ e.preventDefault();}, false);

// helper for random colour
var mouse = {  // mouse data 
    x:0,
    y:0,
    button:false,
    lastButton:false,  // need this to see when the mouse goes down 
    which:[false,false,false],
};
}    
function mouseMoveEvent(event){// handle all canvas mouse events as they come in
// get new mouse positions
mouse.x = event.offsetX; 
mouse.y = event.offsetY; 
if(mouse.x === undefined){ // if firefox
    mouse.x = event.clientX;
    mouse.y = event.clientY;
}    
if(event.type === "mouseout"){
    mouse.button = false;
    mouse.which[0] = false;
    mouse.which[1] = false;
    mouse.which[2] = false;
}
if(event.type === "mousedown"){  // now see if there is extra info
    mouse.button = true;
    mouse.which[event.which-1] = true;
}
if(event.type === "mouseup"){  // now see if there is extra info
    mouse.button = false;
    mouse.which[event.which-1] = false;
}
event.preventDefault();
}

// because forEach is too slow
if (Array.prototype.each === undefined) {
Object.defineProperty(Array.prototype, 'each', {
    writable : false,
    enumerable : false,
    configurable : false,
    value : function (func) {
        var i,
        returned;
        var len = this.length;
        for (i = 0; i < len; i++) {
            returned = func(this[i], i);
            if (returned !== undefined) {
                this[i] = returned;
            }
        }
    }
});
}
// helper functions
function Helpers(){
}
Helpers.prototype.randomColour = function(){
return "hsl("+Math.floor(Math.random()*360)+",100%,50%)";
}
Helpers.prototype.occilatingColour = function(){
var t = (new Date()).valueOf()
return "hsl("+(Math.floor(t/2)%360)+",100%,50%)";
}

// used for building up the extent of a cloud of points
Helpers.prototype.resetExtent = function(){
if(this.extentObj === undefined){  // check if the extentObj is there
    this.extentObj = {};  // if not create it
}
this.extentObj.minX = Infinity;
this.extentObj.minY = Infinity;
this.extentObj.maxX = -Infinity;
this.extentObj.maxY = -Infinity;
}
Helpers.prototype.extent = function( p) { // add a point to the extent
this.extentObj.minX = Math.min(this.extentObj.minX, p.x);
this.extentObj.minY = Math.min(this.extentObj.minY, p.y);
this.extentObj.maxX = Math.max(this.extentObj.maxX, p.x);
this.extentObj.maxY = Math.max(this.extentObj.maxY, p.y);
}
Helpers.prototype.copyOfExtent = function () {  // get a copy of the extent object
return {
    minX : this.extentObj.minX,
    minY : this.extentObj.minY,
    maxX : this.extentObj.maxX,
    maxY : this.extentObj.maxY,
    centerX : (this.extentObj.maxX-this.extentObj.minX)/2,
    centerY : (this.extentObj.maxY-this.extentObj.minY)/2,
    width:this.extentObj.maxX-this.extentObj.minX,
    height:this.extentObj.maxY-this.extentObj.minY,
};
}
Helpers.prototype.getID = function(){  // return a unique ID for this session
if(this.id === undefined){
    this.id = 0;
}
this.id += 1;
return this.id;
}
// function to get distance of point to a line
Helpers.prototype.distPointToLine = function (x, y, x1, y1, x2, y2) {
var px = x2 - x1;
var py = y2 - y1;
var u = this.lineSegPos =  Math.max(0, Math.min(1, ((x - x1) * px + (y - y1) * py) / (this.distSqr1 = (px * px + py * py))));
return Math.sqrt(Math.pow((x1 + u * px) - x, 2) + Math.pow((y1 + u * py) - y, 2));
}
// function to get the distance of a point to a set of point describing a line
Helpers.prototype.getDistToPath = function (line,x,y) {
var i,len, lineLen,dist;
len = line.length;
x1 = line[0].x;
y1 = line[0].y;
var minDist = Infinity;
for(i = 1; i < len-1; i++){
    var near = false;
    x2 =  line[i].x;
    y2 =  line[i].y;
    lineLen = Math.hypot(x1-x2,y1-y2);
    dist = Math.hypot((x1+x2)/2-x,(y1+y2)/2-y);
    minDist = Math.min(minDist,dist); 
    if(dist < lineLen ){
        minDist = Math.min(minDist,helpers.distPointToLine(x,y,x1,y1,x2,y2));
    }
    if(minDist < minDistToPass){
        return minDist;
    }
    x1 = x2;
    y1 = y2;
}
return minDist;
}
var helpers = new Helpers();
// Stuff for paths and drawing
var lineArray = [];  // list of paths
var lastLine; // last line drawn
var points;  // current recording path
var drawing = false;  // flag is mouse down and drawing
var dragging = false;
var dragOffX;
var dragOffY;
var drawMode = "Draw";
var minDistToPass = 2; // If a line is closer than this then stop search we found the winning line

// functions to redraw all recorded lines
function redrawAll(){  // style to draw in
ctx.clearRect(0,0,canvas.width,canvas.height);
lineArray.each(function(p){ // draw each one point at atime
    redraw(p,p.style);
})
}

// lineDesc is a line and its description
// style is a the style to draw the line in.
// withBox if true draw bounding box [optional]
function redraw(lineDesc,style,withBox){ // draws a single line with style
var line = lineDesc.line;
var len = line.length;
var i;
ctx.beginPath();   // 
ctx.strokeStyle = style.colour;  // set style and colour
ctx.lineWidth = lineDesc.style.width;
ctx.lineJoin = "round";
ctx.lineCap = "round";

ctx.moveTo(line[0].x,line[0].y);  // move to the first pont
for(i = 1; i < line.length; i++){   // lineto all the rest
    ctx.lineTo(line[i].x,line[i].y);
};
ctx.stroke(); // stroke
if(withBox){
    var w = Math.ceil(lineDesc.style.width/2); // need the lines width to expand the bounding box
    ctx.lineWidth = 1;
    ctx.strokeStyle = "black";
    ctx.strokeRect(  // draw the box around the line
        lineDesc.extent.minX-w,
        lineDesc.extent.minY-w,
        lineDesc.extent.width+w*2,
        lineDesc.extent.height+w*2
    )
}
// done
}

// Finds the closest line and returns it. If no line can be found it returns undefined.
function findLineAt(x,y){
var minDist = 20; // Set the cutoff limit. Lines further than this are ignored
var minLine;
var w;
lineArray.each(function(line){ // do ech line one at a time
    w = line.style.width;
    if(x >= line.extent.minX-w && x <= line.extent.maxX+w && // is the point inside the bounding
       y >= line.extent.minY-w && y <= line.extent.maxY+w){  // boc
        var dist = helpers.getDistToPath(line.line,x,y);  // if so then do a detailed distance check
        if(dist < minDist){   // is the distance to the line less than any other distance found
            minDist = dist;   // if so remember the line
            minLine = line;
        }
    }
    dist = Math.hypot(line.extent.centerX-x,line.extent.centerY-y); // check the distance to the 
    if(dist<minDist){                                               // center of the bounding boc
        minDist = dist;   // use this one if bound box center if close
        minLine = line;
    }
});
return minLine;
   
}
function refreshLine(line){ // updates the line to get extend and add stuff if needed
// a good place to smooth the line if need
if(!line.isLine){  
    var newLine = {};   // new object
    newLine.isLine = true; // flag to indicate that the line has been updated
    newLine.line = line;  // attach the line
    newLine.id = helpers.getID();   // get a unique Id for the line
    newLine.style = {  // give it a style
        colour:helpers.randomColour(),
        width:Math.random()*4+10,
    };
}else{
    var newLine = line;
}
var extent = helpers.extent.bind(helpers)
helpers.resetExtent();
line.each(extent);
newLine.extent = helpers.copyOfExtent();
return newLine;
}
function update(){  // one animframe
if(drawMode === "Draw"){
if(!mouse.lastButton && mouse.button ){ // if the mouse but just down;
    points = []; // create an new array     
    drawing = true; // flag drawinf

    lineArray.push(points);  // save the point array onto the pointsArray
    points.push({x:mouse.x,y:mouse.y}); // add the first point
    setCursor("none");
}else
if(drawing && mouse.button){  // while the mouse is down keep drawing
    points.push({x:mouse.x,y:mouse.y});  // save new point
    var p1 = points[points.length-2];  // get last line seg and draw it
    var p2 = points[points.length-1];
    ctx.lineWidth = 1;
    ctx.strokeStyle = "black";
    ctx.beginPath();
    ctx.moveTo(p1.x,p1.y);
    ctx.lineTo(p2.x,p2.y);
    ctx.stroke();
}else{
    if(drawing){ // if drawing and mouse up
        points.push({x:mouse.x,y:mouse.y}); // add the last point
        lineArray.push(points = refreshLine(lineArray.pop()))
        // redraw the newly draw line
        redraw(points,points.style);
        drawing = false; // flag that drawing is off.

    }else{
        setCursor("crosshair");
    }
}
}else
if(drawMode = "Pick"){
    if(!dragging && !mouse.button){  // is the mouse near a line and not dragging
        ctx.clearRect(0,0,canvas.width,canvas.height); // clear background
        ctx.drawImage(backGroundImage,0,0);           // draw copy of existing lines
        var line = findLineAt(mouse.x,mouse.y);  // find the line 
        if(line !== undefined){   // is a line is near 
            setCursor("drag_small"); // highlight it
            lastLine = line;          // remember it
            // draw it hightlighted with bounding box.
            redraw(lastLine,{colour:helpers.occilatingColour(),width:lastLine.width},true);
        }else{
            setCursor();  // not near a line so turn of cursoe
        }
    }else  // next check if the mouse has jsut been click to start a drag.
    if(lastLine !== undefined && !mouse.lastButton && mouse.button){
        if(mouse.which[2]){  // Check which button. Right? then copy
            var newLine = [];
            lastLine.line.each(function(p){newLine.push({x:p.x,y:p.y})});
            newLine = refreshLine(newLine)
            newLine.style = lastLine.style;
            lastLine = newLine;
            lineArray.push(newLine)

        }else
        if(mouse.which[1]){ // Check which button. Middle? then delete
            var index;
            lineArray.each(function(line,i){
                if(line.id === lastLine.id){
                    index = i;
                }
            })
            if(index !== undefined){
                lineArray.splice(index,1);
            }
            ctx.clearRect(0,0,canvas.width,canvas.height);
            redrawAll();                
            lastLine = undefined;
            if(lineArray.length === 0){
                drawMode = "Draw";
                but.value = "Draw Mode";
            }
        }
        if(lastLine !== undefined){
            dragging = true;
            dragOffX = mouse.x;
            dragOffY = mouse.y;
           // backGroundImage.ctx.clearRect(0,0,canvas.width,canvas.height);
           // backGroundImage.ctx.drawImage(canvas,0,0);
        }
    }else{
        if(dragging && !mouse.button){ // Drop is dragging true and not mouse down
            dragging = false;
            var ox = mouse.x-dragOffX;  // Find the drag offset
            var oy = mouse.y-dragOffY;
            helpers.resetExtent();     // get ready for new bounding box.
            lastLine.line.each(function(p){  // move each point of the line
                p.x += ox;
                p.y += oy;
                helpers.extent(p);  // and test the bounding box
                return p;
            })
            lastLine.extent = helpers.copyOfExtent();  // get the new boundong box
            ctx.clearRect(0,0,canvas.width,canvas.height);
            redrawAll();
            backGroundImage.ctx.clearRect(0,0,backGroundImage.width,backGroundImage.height);
            backGroundImage.ctx.drawImage(canvas,0,0);                
        }else
        if(dragging){  // if dragging 
            ctx.clearRect(0,0,canvas.width,canvas.height); // clear
            ctx.drawImage(backGroundImage,0,0);  // draw existing lines
            var ox = mouse.x-dragOffX;   // get the drag offset
            var oy = mouse.y-dragOffY;
            ctx.setTransform(1,0,0,1,ox,oy);  // translate by drag offset
            redraw(lastLine,lastLine.style);  //draw the dragged line
            ctx.setTransform(1,0,0,1,0,0);  // reset transform
        }
    }
}
mouse.lastButton = mouse.button; // set the last button state
window.requestAnimationFrame(update); // request a new frame
}
window.requestAnimationFrame(update)

.canC {
    width:256px;
    height:256px;
    border:black 2px solid;
}
.info{
  font-size:x-small;
}

<input type="button" id="redrawAllID" value="Click to Pick"></input>
<div class="info">Mouse down to draw.In pick mode mouse hover over line.<br> Left Button drag,middle delete, right copy.</div>
<canvas class="canC" id="canV" width=256 height=256></canvas>

这篇关于如何在html画布中检测和移动/拖动自由流动绘制的线条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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