HTML5 Javascript:如何确保绘制的对象不能离开画布

HTML5 Javascript: How to Make Sure a Drawn Object Cannot Leave the Canvas

本文关键字:对象 绘制 不能 离开 确保 Javascript 何确保 HTML5      更新时间:2023-09-26

我有以下分配问题,我正在努力解决:

    编写一个应用程序,使用canvas元素在画布的两个不同部分创建两个圆圈(颜色不同)。圆圈应该能够在画布内拖动,当它到达边缘时应该停止。换句话说,圆的边缘不应该超过画布的边缘。每个圆应该单独拖动。当你松开鼠标按钮时,圆圈应该停止。

到目前为止,我已经创建了两个圆圈,然而,我有麻烦的部分,我必须使它,使两个圆圈可以被拖动,但不能离开画布。我很确定这应该是一个事件监听器,但我不知道如何编码。如果您能提供帮助或见解,我将不胜感激。

目前为止我有什么:

<!DOCTYPE html>
<html>
<head>
<script>
window.onload = draw;
function draw(){
var canvas = document.getElementById("circleCanvas");
var ctx = canvas.getContext("2d");
ctx.arc(100,75,50,0,2*Math.PI);
ctx.fillStyle = "green";
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.arc(100,200,50,0,2*Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.stroke();
ctx.closePath();
}
</script>
</head>
<body>
<canvas id="circleCanvas" width="500" height="500"></canvas>
</body>
</html>

简单的画布拖放操作。

  • 创建一个鼠标对象,通过监听鼠标事件设置鼠标位置和按钮状态

  • 创建一个圆数组,描述每个圆的位置和大小。

  • 创建一个函数来绘制一个圆。在这个函数中,你可以检查圆圈是否超出了界限,如果超出了界限,就移动它。

  • 创建一个位置搜索功能,检查每个圆以及它离点的距离。如果圆在点(dist <</p>

  • 创建一个动画循环,每1/60秒重新绘制画布。检查一下鼠标是否按下。如果是,并且没有拖动任何东西看看鼠标是否在一个圆上。如果是,选择那个圆圈进行拖动。当鼠标向上时,放下圆圈

因为这是一个作业,我们不应该直接给你答案。但是学校是我们一生中唯一不被允许寻求帮助的时候,是我们最需要帮助的时候。我认为你对学习很感兴趣,在很多情况下,以身作则是最好的方法。

如果你有任何问题,请问

"use strict";
const canvas = document.createElement("canvas"); 
canvas.height = innerHeight;
canvas.width = innerWidth;
canvas.style.position = "absolute"; 
canvas.style.top = canvas.style.left = "0px";
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
ctx.font = "48px arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
var w = canvas.width;
var h = canvas.height;
var renderUpdate  = true; // flags if there is a need to render
var globalTime = 0;
const mouse = {
    x:0,y:0,button:false
};
const circles = [{
        x : 100,
        y : 100,
        radius : 40,
        col : "red",
        lineWidth : 4,
        highlight : false,
    },{
        x : 200,
        y : 100,
        radius : 40,
        col : "green",
        lineWidth : 4,
        highlight : false,
    },        
];
var closestCircle; // holds result of function findClosestCircle2Point
const drag = {  // if dragging this holds the circle being dragged
    circle : null,
    offsetX : 0, // distance from mouse to circle center when drag started
    offsetY : 0,
}
const message = { // a message to inform of problems.
    time : 120,   // 60 ticks per second
    text: "Click drag circles",
}
// adds mouse events listeners
canvas.addEventListener("mousemove",mouseEvent)
canvas.addEventListener("mousedown",mouseEvent)
canvas.addEventListener("mouseup",mouseEvent)
// function to handle all mouse events
function mouseEvent(e){
    var m = mouse;
    var bounds = canvas.getBoundingClientRect();
    m.x = e.clientX - bounds.left; 
    m.y = e.clientY - bounds.top;     
    if(e.type === "mousedown"){
        m.button = true;
    }else if(e.type === "mouseup"){
        m.button = false;
    }
    renderUpdate = true; // flag that there could be a render change.
}
// this finds the closest circle under x,y if nothing under the point then retVal.circle = null
function findClosestCircle2Point(x, y, retVal){
    if(retVal === undefined){
        retVal = {};
    }
    var minDist = Infinity;
    var dist;
    var xx,yy;
    retVal.circle = null;
    for(var i = 0; i < circles.length; i ++){
        xx = x - circles[i].x;
        yy = y - circles[i].y;
        dist = Math.sqrt(xx*xx+yy*yy);
        if(dist < minDist && dist <= circles[i].radius){
            minDist = dist;
            retVal.circle = circles[i];
        }
    }
    return retVal;
}
// this draws a circle, adds highlight if needed and makes sure the circle does not go outside the canvas
function drawCircle(circle){
    var c = circle;
    var rad = c.radius + c.lineWidth / 2; // get radius plus half line width
    // keep circle inside canvas
    c.x = c.x - rad < 0 ? c.x = rad : c.x + rad >= w ? c.x = w-rad : c.x;
    c.y = c.y - rad < 0 ? c.y = rad : c.y + rad >= h ? c.y = h-rad : c.y;
    ctx.lineWidth = 4;
    if(c.highlight){  // highlight the circle if needed
        ctx.strokeStyle = "#0F0";
        ctx.globalAlpha = 0.5;
        ctx.beginPath();
        ctx.arc(c.x,c.y,c.radius + c.lineWidth,0,Math.PI * 2);
        ctx.stroke();
        c.highlight = false;
    }
    // draw the circle
    ctx.fillStyle = c.col;
    ctx.strokeStyle = c.col;
    ctx.globalAlpha = 0.5;
    ctx.beginPath();
    ctx.arc(c.x,c.y,c.radius,0,Math.PI * 2);
    ctx.fill();
    ctx.globalAlpha = 1;
    ctx.stroke();
}
// main update function
function update(time){
    globalTime = time;
    requestAnimationFrame(update); // get the next animation frame.
    if(!renderUpdate  ){  // don't render if there is no need
        return;
    }
    renderUpdate = false;
    ctx.clearRect(0,0,w,h);
    // when not dragging look for the closest circle under the mouse and highlight it
    if(drag.circle === null){
        closestCircle = findClosestCircle2Point(mouse.x,mouse.y,closestCircle); 
        if(closestCircle.circle !== null){
            closestCircle.circle.highlight = true;
        }
    }
    if(mouse.button){  // if the mouse is down start dragging if circle is under mouse
        if(drag.circle === null){
            if(closestCircle.circle !== null){
                drag.circle = closestCircle.circle;
                drag.offsetX = mouse.x - drag.circle.x;
                drag.offsetY = mouse.y - drag.circle.y;
            }else{
                mouse.button = false;
            }
        }else{
            drag.circle.x = mouse.x - drag.offsetX;
            drag.circle.y = mouse.y - drag.offsetY;
        }
    }else{   // drop circle 
        drag.circle = null;
    }
    for(var i = 0; i < circles.length; i ++){  // draw all circles
        drawCircle(circles[i]);
    }
    
    // display any messages if needed.
    if(message.time > 0){
        message.time -= 1;
        ctx.fillStyle = "black";
        ctx.fillText(message.text,w/2,h/2);
        renderUpdate = true; // while message is up need to render.
    }
    
}
requestAnimationFrame(update);  // start the whole thing going.

HTML5 canvas没有针对您绘制的对象的事件监听器。一旦它们被栅格化(绘制),它们就只是图像上的像素。

这意味着你必须独立处理对画布的点击,然后通过javascript对象处理屏幕上的事件,然后重新绘制画布。像fabric.js这样的框架可以让这个过程变得非常轻松。http://fabricjs.com/

还有其他框架,但如果你不想要一个框架,它将要求你管理自己的场景,执行点击检测对象事件处理等。