【问题标题】:How do I make a HTML canvas rectangle resize along with mouse drag?如何使HTML Canvas矩形调整大小以及鼠标拖动?
【发布时间】:2018-06-11 20:54:06
【问题描述】:

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

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

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

以下是执行该功能的代码sn-p:

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

【问题讨论】:

    标签: javascript html html5-canvas mouseevent


    【解决方案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/

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

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

    目前仍有一些错误,但我会尽快修复这些错误!

    编辑

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

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

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

    【讨论】:

    • js fiddle 不做可调整大小的矩形。
    【解决方案2】:

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

    你有几个选项来实现一个可拖动的矩形:

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

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

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

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

    // 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 2021-08-26
      • 2015-11-30
      • 2013-11-23
      • 2014-08-08
      相关资源
      最近更新 更多