如何在JavaScript中创建可调整大小的矩形?

时间:2017-01-19 15:04:21

标签: javascript html html5-canvas

我的意思是用户在HTML画布上的点xy处按下鼠标按钮,并且在按下鼠标按钮时,可以根据光标的移动来调整矩形的大小,并固定点xy。就像突出工作一样。

这是我到目前为止所得到的,但它似乎并没有起作用:

 canvas.addEventListener('mousedown', function(e){

var rectx = e.clientX;
var recty = e.clientY;

canvas.onmousemove = function(e){     



    var df = e.clientX;
    var fg = e.clientY;
};


context.rect(rectx, recty, df-rectx, fg-recty);
context.stroke();




}, false);              

2 个答案:

答案 0 :(得分:1)

假设画布上下文中没有变换(scaletranslate)。

具有可调整大小的矩形的基本步骤如下:

  1. 创建一个mousedown侦听器,设置一个标志,指示使用按住鼠标按钮,以及设置"锚点,"或初始坐标。

  2. 创建一个取消设置标志的mouseup侦听器。

  3. 创建一个mousemove侦听器,如果该标志指示鼠标已关闭,则重绘画布,并根据鼠标坐标更改矩形的大小。

  4. 一个重要的注意事项是event对象中的客户端坐标是相对于页面的,不是相对于您的画布元素。您经常需要将clientXclientY转换为画布坐标:

    var getCanvasCoords = function (clientX, clientY) {
        var rect = canvas.getBoundingClientRect();
    
        return {
            x: clientX - rect.left,
            y: clientY - rect.top
        };
    };
    

    前两个步骤看起来像这样:

    var anchorX;
    var anchorY;
    var mouseDown = false;    
    
    canvas.addEventListener('mousedown', function (event) {
        var coords = getCanvasCoords(event.clientX, event.clientY);
        anchorX = coords.x;
        anchorY = coords.y;
    
        mouseDown = true;
    });
    
    canvas.addEventListener('mouseup', function (event) {
        mouseDown = false;
    });
    

    mousemove处理程序:

    canvas.addEventListener('mousemove', function (event) {
        var coords = getCanvasCoords(event.clientX, event.clientY);
    
        var width = coords.x - anchorX;
        var height = coords.y - anchorY;
    
        // clear canvas for redrawing
        context.clearRect(0, 0, canvas.width, canvas.height);
    
        context.fillRect(anchorX, anchorY, width, height);
    });
    

答案 1 :(得分:0)

不要从鼠标事件中渲染!

给出的答案是正确的,但这不是最好的方法。

有两个原因。首先,mousemove事件每秒最多可触发600次,但显示屏每秒仅刷新60次。从输入事件中渲染很多时间只是浪费CPU时间,因为在有机会显示之前,结果将被下一个鼠标事件覆盖。

第二个原因是将事件监听器专用于单个任务会使添加更多功能变得困难。您最终会在mousemove事件中添加越来越多的代码来处理所有类型的输入,由于鼠标的更新速度很快,因此大多数输入都可以被忽略。

鼠标侦听器

鼠标事件侦听器尽可能少。他们只记录鼠标状态而不再记录。此外,所有鼠标事件都返回鼠标位置。您不应忽略鼠标按下和向上等事件的鼠标位置

以下函数为元素创建鼠标对象。鼠标对象具有相对于元素左侧的x,y位置,当前按钮表示3个按钮,它从左到右按钮1,按钮2,按钮3。

此外,当鼠标离开元素然后释放鼠标按钮时,元素的鼠标将不会看到mouseup事件,也不知道鼠标按钮已启动。为防止鼠标按键卡住,请在鼠标离开元素时关闭按钮。

最好的鼠标监听器是整个页面,因为它可以跟踪即使鼠标在窗口/标签之外发生的鼠标事件(如果窗口/标签有焦点),但对于这个答案来说这有点复杂

为元素创建鼠标的功能

function createMouse(element){
    var mouse = {
       x : 0,
       y : 0,
       button1 : false,
       button2 : false,
       button3 : false,
       over : false,
    };
    function mouseEvent(event){
        var bounds = element.getBoundingClientRect();
        mouse.x = event.pageX - bounds.left - scrollX;
        mouse.y = event.pageY - bounds.top - scrollY;
        if(event.type === "mousedown"){
            mouse["button"+event.which] = true;
        } else if(event.type === "mouseup"){
            mouse["button"+event.which] = false;
        } else if(event.type === "mouseover"){
            mouse.over = true;
        } else if(event.type === "mouseout"){
            mouse.over = false;
            mouse.button1 = false;  // turn of buttons to prevent them locking
            mouse.button2 = false;
            mouse.button3 = false;
        }
        event.preventDefault(); // stops default mouse behaviour.
    }
    var events = "mousemove,mousedown,mouseup,mouseout,mouseover".split(',');
    events.forEach(eventType => element.addEventListener(eventType,mouseEvent));
    mouse.remove = function(){
        events.forEach(eventType => element.removeEventListener(eventType, mouseEvent));
    }
    return mouse;
}

使用鼠标

现在只需要为元素创建鼠标

var canMouse = createMouse(canvas);

然后在你的主渲染循环中进行拖动。

var drag = { 
    x : 0,
    y : 0,
    x1 : 0,
    y1 : 0,
    dragging : false,
    top : 0,
    left : 0,
    width : 0,
    height : 0,
}

function mainLoop(){
     if(canMouse.button1){  // is button down
         if(!drag.dragging){ // is dragging
             drag.x = canMouse.x;
             drag.y = canMouse.y;
             drag.dragging = true;
         }
         drag.x1  = canMouse.x;
         drag.y1  = canMouse.y;
         drag.top = Math.min(drag.y, drag.y1);
         drag.left = Math.min(drag.x, drag.x1);
         drag.width = Math.abs(drag.x - drag.x1);
         drag.height = Math.abs(drag.y - drag.y1);
     }else{
         if(drag.dragging){
             drag.dragging = false;
         }
     }
 }

全部放在一起



    function createMouse(element){
        var mouse = {
           x : 0,
           y : 0,
           button1 : false,
           button2 : false,
           button3 : false,
           over : false,
        };
        function mouseEvent(event){
            var bounds = element.getBoundingClientRect();
          
            // NOTE getting the border should not be done like this as
            // it will not work in all cases. 
            var border = Number(element.style.border.split("px")[0])
            
            mouse.x = event.pageX - bounds.left - scrollX - border;
            mouse.y = event.pageY - bounds.top - scrollY - border;
            if(event.type === "mousedown"){
                mouse["button"+event.which] = true;
            } else if(event.type === "mouseup"){
                mouse["button"+event.which] = false;
            } else if(event.type === "mouseover"){
                mouse.over = true;
            } else if(event.type === "mouseout"){
                mouse.over = false;
                mouse.button1 = false;  // turn of buttons to prevent them locking
                mouse.button2 = false;
                mouse.button3 = false;
            }
            event.preventDefault(); // stops default mouse behaviour.
        }
        var events = "mousemove,mousedown,mouseup,mouseout,mouseover".split(',');
        events.forEach(eventType => element.addEventListener(eventType,mouseEvent));
        mouse.remove = function(){
            events.forEach(eventType => element.removeEventListener(eventType, mouseEvent));
        }
        return mouse;
    }
    var drag = {
        x : 0,
        y : 0,
        x1 : 0,
        y1 : 0,
        dragging : false,
        top : 0,
        left : 0,
        width : 0,
        height : 0,
    }
    var ctx = canvas.getContext("2d");
    ctx.strokeStyle = "black";
    ctx.lineWidth = 1;
    var mouse = createMouse(canvas);
    function update(){
         ctx.clearRect(0,0,canvas.width,canvas.height);
         if(mouse.button1){  // is button down
             if(!drag.dragging){ // is dragging
                 drag.x = mouse.x;
                 drag.y = mouse.y;
                 drag.dragging = true;
             }
             drag.x1  = mouse.x;
             drag.y1  = mouse.y;
             drag.top = Math.min(drag.y, drag.y1);
             drag.left = Math.min(drag.x, drag.x1);
             drag.width = Math.abs(drag.x - drag.x1);
             drag.height = Math.abs(drag.y - drag.y1);
         }else{
             if(drag.dragging){
                 drag.dragging = false;
             }
         }
      
         if(drag.dragging){
            ctx.strokeRect(drag.left, drag.top, drag.width, drag.height);
         }
         requestAnimationFrame(update);
     }
     requestAnimationFrame(update);

canvas {
  border : 1px solid black;
}

Click drag to draw rectangle.<br>
<canvas id="canvas" width= "512" height = "256"></canvas>
&#13;
&#13;
&#13;