如何使HTML画布矩形与鼠标拖动一起调整大小?

时间:2018-01-02 05:44:20

标签: javascript html html5-canvas mouseevent

我正在创建一个基于Web的注释应用程序,用于通过HTML canvas元素和Javascript注释图像。我希望用户向下鼠标指示矩形的开始,拖动到所需的结束坐标,然后松开指示矩形的另一端。

目前,我可以使用起始坐标和结束坐标在图像上使用 context.rects()函数创建一个矩形,但是由于我不确定如何调整特定的大小画布上的矩形,只有在用户释放鼠标后才会绘制矩形。

如何在拖动时调整在mousedown上创建的特定矩形的大小?

以下是执行该功能的代码片段:

var isMouseDown = false;
    var startX;
    var startY;
    canvas.onmousedown = function(e) { 
        if(annMode){
            isMouseDown = true;
            var offset = $(this).offset();
            startX = parseInt(e.pageX - offset.left);
            startY = parseInt(e.pageY - offset.top);
        }
    };
    canvas.onmousemove = function(e) { 
        if(isMouseDown) { 
            var offset = $(this).offset();
            var intermediateX = parseInt(e.pageX - offset.left);
            var intermediateY = parseInt(e.pageY - offset.top);
            console.log(intermediateX);
        } 
    };
    canvas.onmouseup   = function(e) { 
        if(annMode&&isMouseDown){
            isMouseDown = true;
            var offset = $(this).offset();
            var endX = parseInt(e.pageX - offset.left);
            var endY = parseInt(e.pageY - offset.top);
            var width = endX - startX;
            var height = endY - startY;
            context.strokeStyle = "#FF0000";
            context.rect(startX, startY, width, height);
            context.stroke();
        }
        isMouseDown = false 
    };

2 个答案:

答案 0 :(得分:1)

canvas API不会保留对使用它绘制的特定形状的引用(与SVG不同)。 canvas API只是提供了方便的功能,可以将操作应用于canvas元素的各个像素。

您有几个选项可以实现可拖动的矩形:

  1. 您可以在用户拖动时将样式化的div放在画布上。为您的画布和div创建一个容器,并更新div的位置和大小。当用户释放时,绘制矩形。您的容器需要position: relativediv需要绝对定位。确保div的z-index高于canvas

    在您的鼠标按下方法中,将div.style.display设置为block。然后在拖动鼠标时更新位置(style.leftstyle.topstyle.widthstyle.height)。释放鼠标后,再次隐藏它(style.display = 'none')。

  2. 您可以手动存储对要绘制的每个项目的引用,清除画布(context.clearRect),并在每个帧上重绘画布上的每个项目。这种设置通常通过递归使用window.requestAnimationFrame方法来实现。此方法接受回调并在浏览器的下一个绘制周期执行。

  3. 在您的情况下,第一个选项可能更容易实现。如果您计划进一步扩展应用程序的功能,第二个将提供更多功能。基本循环将如下实现:

    // setup code, create canvas & context
    
    function mainLoop() {
    
        context.clearRect(0, 0, canvas.width, canvas.height);
    
        /** do your logic here and re-draw **/
    
        requestAnimationFrame(mainLoop);
    }
    
    function startApp() {
        requestAnimationFrame(mainLoop)
    }
    

    本教程详细介绍了HTML canvas的事件循环:http://www.isaacsukin.com/news/2015/01/detailed-explanation-javascript-game-loops-and-timing

    我的GitHub上还有一个功能齐全的实现,它是我写的渲染引擎的一部分:https://github.com/thunder033/mallet/blob/master/src/mallet/webgl/webgl-app.ts#L115

答案 1 :(得分:1)

这里我方便的前端脚本派上用场了!

当我理解这个问题时,您希望能够将鼠标移动到画布上的任意位置,按住鼠标左键,然后向任意方向拖动以在起点和任何新鼠标位置之间形成一个矩形。当你松开鼠标按钮时它就会停留。

可帮助您完成目标的脚本:

https://github.com/GustavGenberg/handy-front-end/blob/master/README.md#canvasjs https://github.com/GustavGenberg/handy-front-end/blob/master/README.md#pointerjs

这两个脚本只是使代码更清晰,更容易理解,所以我使用了这些。

这是一个简单的小提琴,你可以真正使用

const canvas = new Canvas([]);

const mouse = new Pointer();

https://jsfiddle.net/0y8cbao3/

我是否正确理解了您的问题?

你想要一个带有评论的版本描述每一行吗?

目前仍有一些漏洞,但我很快就会解决这些问题!

修改

在再次阅读你的问题之后,我做出了反应:“......但是我不确定如何在画布上调整特定矩形的大小...”。

Canvas就像一个图像。一旦你吸引它,你就不能“调整”不同的形状。你只能清除整个画布并重新开始(当然你也可以清除一小部分)。

这就是Canvas助手如此有用的原因。为了能够“动画”画布,你必须创建一个循环,用每个16ms(60 fps)的新帧重绘画布。