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

时间:2016-11-09 21:06:50

标签: javascript html5 canvas

我有以下分配问题,我很难解决:

  1. 编写一个使用canvas元素的应用程序,在画布的两个不同部分创建两个圆圈(具有不同的颜色)。圆圈应该能够在画布中拖动,并且当它到达边缘时应该停止。换句话说,圆的边缘不应超过画布的边缘。应分别拖动每个圆圈。当您松开鼠标按钮时,圆圈应该停止。
  2. 到目前为止,我已经创建了两个圆圈,但是,我在制作它的部分时遇到了问题,因此可以拖动两个圆圈但不能离开画布。我非常确定这应该是通过事件监听器来完成的,但我无法弄清楚如何对此进行编码。非常感谢一些帮助或见解。

    到目前为止我所拥有的:

    
    
    <!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>
    &#13;
    &#13;
    &#13;

2 个答案:

答案 0 :(得分:2)

简单的画布拖放。

  • 通过聆听鼠标事件创建鼠标对象并设置鼠标位置和按钮状态。

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

  • 创建一个绘制圆的函数。在该功能中,您可以检查圆圈是否超出界限,如果是,则移动它。

  • 创建一个位置搜索功能,可以检查每个圆圈以及它与点之间的距离。如果圆圈位于该点之下(dist

  • 创建一个动画循环,每隔1/60秒重绘一次画布。在该检查中,鼠标是否已关闭。如果是,而不是拖动任何东西,看看鼠标是否在圆圈上。如果选择该圈子进行拖动。当鼠标向上时,放下圆圈。

由于这是一项任务,我们不应该只给你解决方案。但是,当我们不被允许寻求帮助时,学校是生命中的唯一时间,也就是我们最需要帮助的时候。我认为你对学习和学习感兴趣,在很多情况下都是最好的。

如果您有任何疑问,请询问

&#13;
&#13;
"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.
&#13;
&#13;
&#13;

答案 1 :(得分:0)

HTML5画布没有您绘制的对象的事件侦听器。一旦它们被光栅化(绘制),它们就只是图像上的像素。

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

还有其他框架,但如果您不想要框架,则需要您管理自己的场景,执行点击检测以自行对象事件处理等。