【问题标题】:Let users draw rectangles with mouse in canvas with Javascript让用户使用 Javascript 在画布中用鼠标绘制矩形
【发布时间】:2020-12-20 11:34:14
【问题描述】:

我将创建一个画布,让用户可以在画布中绘制一些矩形。它可以在用户拖动鼠标时显示矩形。此外,它允许用户在画布中绘制一个或多个矩形。我找到了这样的解决方案:

// get references to the canvas and context
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

// style the context
ctx.strokeStyle = "blue";
ctx.lineWidth = 3;

// calculate where the canvas is on the window
// (used to help calculate mouseX/mouseY)
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();

// this flage is true when the user is dragging the mouse
var isDown = false;

// these vars will hold the starting mouse position
var startX;
var startY;


function handleMouseDown(e) {
    e.preventDefault();
    e.stopPropagation();

    // save the starting x/y of the rectangle
    startX = parseInt(e.clientX - offsetX);
    startY = parseInt(e.clientY - offsetY);

    // set a flag indicating the drag has begun
    isDown = true;
}

function handleMouseUp(e) {
    e.preventDefault();
    e.stopPropagation();

    // the drag is over, clear the dragging flag
    isDown = false;
}

function handleMouseOut(e) {
    e.preventDefault();
    e.stopPropagation();

    // the drag is over, clear the dragging flag
    isDown = false;
}

function handleMouseMove(e) {
    e.preventDefault();
    e.stopPropagation();

    // if we're not dragging, just return
    if (!isDown) {
        return;
    }

    // get the current mouse position
    mouseX = parseInt(e.clientX - offsetX);
    mouseY = parseInt(e.clientY - offsetY);

    // Put your mousemove stuff here

    // clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // calculate the rectangle width/height based
    // on starting vs current mouse position
    var width = mouseX - startX;
    var height = mouseY - startY;

    // draw a new rect from the start position 
    // to the current mouse position
    ctx.strokeRect(startX, startY, width, height);

}

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

http://jsfiddle.net/m1erickson/6E2yd/

但是,该解决方案只能允许用户绘制一个矩形。如果用户绘制第二个矩形,前一个矩形将被清除,因为每次拖动鼠标时都会调用 ctx.clearRect()。

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    编辑:对不起我的错误。我错过了容器的 position:relative 属性。现在它应该可以工作了。

    您的 jsfiddle 中的代码反复重绘以指示矩形。我认为最好将此指示画布分离到一个新图层,并使用重叠图层来显示绘制的矩形。 JS:

    // get references to the canvas and context
    var canvas = document.getElementById("canvas");
    var overlay = document.getElementById("overlay");
    var ctx = canvas.getContext("2d");
    var ctxo = overlay.getContext("2d");
    
    // style the context
    ctx.strokeStyle = "blue";
    ctx.lineWidth = 3;
    ctxo.strokeStyle = "blue";
    ctxo.lineWidth = 3;
    
    // calculate where the canvas is on the window
    // (used to help calculate mouseX/mouseY)
    var $canvas = $("#canvas");
    var canvasOffset = $canvas.offset();
    var offsetX = canvasOffset.left;
    var offsetY = canvasOffset.top;
    var scrollX = $canvas.scrollLeft();
    var scrollY = $canvas.scrollTop();
    
    // this flage is true when the user is dragging the mouse
    var isDown = false;
    
    // these vars will hold the starting mouse position
    var startX;
    var startY;
    
    var prevStartX = 0;
    var prevStartY = 0;
    
    var prevWidth  = 0;
    var prevHeight = 0;
    
    function handleMouseDown(e) {
        e.preventDefault();
        e.stopPropagation();
    
        // save the starting x/y of the rectangle
        startX = parseInt(e.clientX - offsetX);
        startY = parseInt(e.clientY - offsetY);
    
        // set a flag indicating the drag has begun
        isDown = true;
    }
    
    function handleMouseUp(e) {
        e.preventDefault();
        e.stopPropagation();
    
        // the drag is over, clear the dragging flag
        isDown = false;
        ctxo.strokeRect(prevStartX, prevStartY, prevWidth, prevHeight);
    }
    
    function handleMouseOut(e) {
        e.preventDefault();
        e.stopPropagation();
    
        // the drag is over, clear the dragging flag
        isDown = false;
    }
    
    function handleMouseMove(e) {
        e.preventDefault();
        e.stopPropagation();
    
        // if we're not dragging, just return
        if (!isDown) {
            return;
        }
    
        // get the current mouse position
        mouseX = parseInt(e.clientX - offsetX);
        mouseY = parseInt(e.clientY - offsetY);
    
        // Put your mousemove stuff here
    
        
    
        // calculate the rectangle width/height based
        // on starting vs current mouse position
        var width = mouseX - startX;
        var height = mouseY - startY;
    
            // clear the canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        // draw a new rect from the start position 
        // to the current mouse position
        ctx.strokeRect(startX, startY, width, height);
        
            prevStartX = startX;
            prevStartY = startY;
    
            prevWidth  = width;
            prevHeight = height;
    }
    
    // listen for mouse events
    $("#canvas").mousedown(function (e) {
        handleMouseDown(e);
    });
    $("#canvas").mousemove(function (e) {
        handleMouseMove(e);
    });
    $("#canvas").mouseup(function (e) {
        handleMouseUp(e);
    });
    
    $("#canvas").mouseout(function (e) {
        handleMouseOut(e);
    });
    

    HTML:

    <h4>Drag the mouse to create a rectangle</h4>
    <div id = "canvasWrapper">
     <canvas id="overlay" width=300 height=300></canvas>
     <canvas id="canvas" width=300 height=300></canvas>
    </div>
    

    CSS:

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

    http://jsfiddle.net/xkmqz9ho/

    【讨论】:

    • 这个例子对我帮助很大,但请确保您了解 mouseout 和 mouseleave 事件之间的区别。我还能够从传递给处理程序的事件对象中获取我的偏移值,我不需要为它设置一个全局变量。
    【解决方案2】:

    我从未在画布上尝试过任何东西,但您可以尝试将 ctx.save() 添加到 mouseout 函数并将 ctx.clear(...) 替换为 ctx.restore()。

    更多信息请访问:https://developer.mozilla.org/es/docs/Web/API/CanvasRenderingContext2D/save

    【讨论】:

    • 我刚刚尝试过,但它会在拖动过程中显示很多矩形。 jsfiddle.net/yj01fLwu
    • 另外,这两个函数只是用于画布的状态。他们不会保存和恢复画布的内容。
    猜你喜欢
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    相关资源
    最近更新 更多