2

我正在尝试创建一个简单的画布程序,用户可以在其中始终创建新形状。这只是一个基本的矩形创建器(我希望将它更多地扩展到圆形、线条,甚至可能是其他东西)。现在虽然我创造了一些以一种非常奇怪的方式工作的东西。

 <html>
    <head>
    <meta chartset="utf-8">
    <title>Dragging a square</title>
    <script type="text/javascript">
        var canvas, context, startX, endX, startY, endY;
        var mouseIsDown = 0;

        function init() {
            canvas = document.getElementById("canvas");
            context = canvas.getContext("2d");

            canvas.addEventListener("mousedown", mouseDown, false);
            canvas.addEventListener("mousemove", mouseXY, false);

            document.body.addEventListener("mouseup", mouseUp, false);
        }

        function mouseUp() {
            mouseIsDown = 0;
            //mouseXY();
        }

        function mouseDown() {
            mouseIsDown = 1;
            startX = event.clientX;
            startY = event.clientY;
            mouseXY();
        }

        function mouseXY(eve) {
            if (!eve) {
                var eve = event;
            }
            endX = event.pageX - canvas.offsetLeft;
            endY = event.pageY - canvas.offsetTop;

            drawSquare();
        }

        function drawSquare() {
            // creating a square
            var width = Math.abs(startX - endX);
            var height = Math.abs(startY - endY);

            context.beginPath();
            context.rect(startX, startY, width, height);
            context.fillStyle = "yellow";
            context.fill();
            context.lineWidth = 7;
            context.strokeStyle = 'black';
            context.stroke();

        }
    </script>
</head>
<body onload="init()">
    <canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas>
</body>
    </html>

很抱歉,当我复制和粘贴我的代码时,格式有点奇怪。我认为问题出在我的 mouseXY 函数上。我想要的是用户单击画布上的某个位置并拖动鼠标以创建一个矩形,当用户放手时,这就是该操作的结束,他们可以立即创建一个全新的矩形。此时程序只是让我单击并创建一个新矩形,但如果我放开鼠标按钮它不会停止,实际上我必须再次单击以使其停止,然后创建一个新矩形。我对此仍然很陌生,我遇到了很多麻烦,我将继续努力,如果我弄清楚了,我会告诉网站。谢谢你,祝你有美好的一天!


好吧,我得到了这个工作(感谢@Ken),但现在我正在尝试解决一个新问题。我希望能够在画布上放置多个矩形。我创建了一个代表 Rectangle 的函数,然后在 rectangle 函数中创建了一个 draw 函数来绘制一个矩形。我创建了一个名为 addShape() 的新函数,该函数理想地创建了矩形对象并将其推入名为 square 和 drawShapes() 的数组中,该数组应该擦除画布上的所有内容并重绘所有内容。这是我到目前为止所拥有的:

    <html>
    <head>
    <meta chartset="utf-8">
    <title>Dragging a square</title>
    <script type="text/javascript">
        function Rectangle(canvas, x, y, width, height,color) {
            //this.context = canvas.getContext("2d");

            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.color = color;

            this.draw = function() {

                this.context.globalAlpha = 0.85;
                this.context.beginPath();
                this.context.rect(this.x, this.y, this.width, this.height);
                this.context.fillStyle = this.color;
                this.context.strokeStyle = "black";
                this.context.lineWidth = 1;

                this.context.fill();
                this.context.stroke();
            };

        };

        // hold the canvas and context variable, as well as the 
        // starting point of X and Y and the end ones
        var canvas, context, startX, endX, startY, endY;
        var mouseIsDown = 0;

        // An array that holds all the squares
        var squares = [];

        window.onload = function() {
            canvas = document.getElementById("canvas");
            context = canvas.getContext("2d");

            canvas.addEventListener("mousedown", mouseDown, false);
            canvas.addEventListener("mousemove", mouseXY, false);
            canvas.addEventListener("mouseup", mouseUp, false);
        }

        function mouseUp(eve) {
            if (mouseIsDown !== 0) {
                mouseIsDown = 0;
                var pos = getMousePos(canvas, eve);
                endX = pos.x;
                endY = pos.y;

                //Square(); //update on mouse-up
                addShape(); // Update on mouse-up
            }
        }

        function mouseDown(eve) {
            mouseIsDown = 1;
            var pos = getMousePos(canvas, eve);
            startX = endX = pos.x;
            startY = endY = pos.y;
            // Square(); //update
            addShape();
        }

        function mouseXY(eve) {

            if (mouseIsDown !== 0) {
                var pos = getMousePos(canvas, eve);
                endX = pos.x;
                endY = pos.y;

                //Square();
                addShape();
            }
        }

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

        function addShape() {
            var w = endX - startX;
            var h = endY - startY;
            var offsetX = (w < 0) ? w : 0;
            var offsetY = (h < 0) ? h : 0;
            var width = Math.abs(w);
            var height = Math.abs(h);

            var s = new Rectangle(startX + offsetX, startY + offsetY, width, height, "yellow");

            squares.push(s);

            // Update the display
            drawShapes();
        }

        function drawShapes() {
            context.clearRect(0,0,canvas.width,canvas.height);

            for (var i = 0; i < squares.length; i++) {
                var shape = squares[i];
                shape.draw();
            };
        }

        function clearCanvas() {
            squares = [];

            drawShapes();
        }

    </script>
</head>
<body onload="addShape()">
    <canvas id="canvas" width="400" height="400" style="border: 1px solid black; cursor: pointer;"></canvas><br>
    <button onclick="clearCanvas()">Clear Canvas</button>
</body>
    </html>

我很确定我破坏了原始代码...谢谢您的帮助!

4

1 回答 1

10

您需要修改代码中的一些内容:(编辑:此代码存在很多问题。我在这里内联了其中一些,但尚未测试。如果您把它放在小提琴中,我们更容易查看)..

小提琴

当鼠标按下时,初始化起点和终点。调用一个不依赖于事件本身的通用绘图函数:

function mouseDown(eve) {
    mouseIsDown = 1;
    var pos = getMousePos(canvas, eve);
    startX = endX = pos.x;
    startY = endY = pos.y;
    drawSquare(); //update
}

在鼠标向上时,仅当 isMouseDown 为真时才注册,否则此函数将处理所有传入的向上事件(因为您已将其附加到文档,这是正确的 - 也可以使用窗口):

function mouseUp(eve) {
    if (mouseIsDown !== 0) {
        mouseIsDown = 0;
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        drawSquare(); //update on mouse-up
    }
}

仅当 mouseisdown 为 true 时才绘制:

function mouseXY(eve) {

    if (mouseIsDown !== 0) {
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;

        drawSquare();
    }
}

此外,您需要在绘制新矩形之前清除矩形的先前区域,否则当您绘制更大的矩形然后将鼠标移回绘制较小的矩形时,它不会显示。

为简单起见,您可以执行以下操作:

function drawSquare() {
    // creating a square
    var width = Math.abs(startX - endX);
    var height = Math.abs(startY - endY);

    context.clearRect(0, 0, context.width, context.height);
    //or use fillRect if you use a bg color

    context.beginPath();
    context.rect(startX, startY, width, height);
    context.fillStyle = "yellow";
    context.fill();
    context.lineWidth = 7;
    context.strokeStyle = 'black';
    context.stroke();
}

将此用于鼠标位置:

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    };
}
于 2013-06-21T01:19:45.583 回答