2016-04-06 103 views
1

我正在使用坐标数组在画布上绘制一系列点。检查鼠标光标是否在坐标数组范围内

var points = [[102, 267], [254, 163], [343, 318], [522, 112], [610, 163], [681, 112]]; 

var canvas = document.getElementById('graph'); 
var c = canvas.getContext('2d'); 

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

function drawPoints(){ 
    for (i = 0; i < points.length; i++) { 
    c.beginPath(); 
    c.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI, true); 
    c.fillStyle = "black"; 
    c.fill(); 
    } 
} 
drawPoints(); 

我想写一个函数来识别这些点,并将它们标记为鼠标悬停在画布上。

canvas.addEventListener('mousemove', function(evt) { 
    var mousePos = getMousePos(canvas, evt); 
    var currMouseX = mousePos.x; 
    var currMouseY = mousePos.y; 

    for (i = 0; i < points.length; i++){ 
    if ((points[i][0] >= currMouseX-4 && points[i][0] <= currMouseX+4) && (points[i][1] >= currMouseY-4 && points[i][1] <= currMouseY+4)) { 
      console.log('in range of '+points[i]); 
     c.beginPath(); 
     c.arc(points[i][0], points[i][1], 8, 0, 2 * Math.PI, true); 
     c.fillStyle = "red"; 
     c.fill(); 
    } 

    } 
}); 

我遇到的问题是我想在鼠标光标离开点的范围时删除标记。

如果我在最后设置了一条简单的else语句,则循环仅适用于数组中的最后一个点,因为for循环的其余部分仍然执行。我需要检查点是否已经命中,停止for循环,检查鼠标是否离开了点的范围,如果是,清除画布并重新绘制点。

也许一个循环不是处理这个问题的最好方法,也许针/干草堆aproach会更好地工作,但我不知道如何实现这个时,搜索范围而不是嵌套数组内的单个值。

FIDDLE

回答

2

你基本上需要一个循环来重新绘制在画布上所有的时间:

setInterval(drawPoints, 1000/30); // redraw at 30 fps 

然后,你必须清除画布在drawPoints:

function drawPoints(){ 
    c.clearRect(0, 0, canvas.width, canvas.height); 

    for (i = 0; i < points.length; i++) { 
    c.beginPath(); 
    c.arc(points[i][0], points[i][1], 5, 0, 2 * Math.PI, true); 
    c.fillStyle = "black"; 
    c.fill(); 
    } 
} 

哪会导致一个新问题,当您移动鼠标时该点只会变成红色。这就是你要的points从数组的数组改为对象的数组:

points = [{x: 123, y: 234, hovered: false}]; 

而且在drawPoints:

function drawPoints(){ 
    c.clearRect(0, 0, canvas.width, canvas.height); 

    for (i = 0; i < points.length; i++) { 
    c.beginPath(); 
    c.arc(points[i].x, points[i].y, 5, 0, 2 * Math.PI, true); 
    c.fillStyle = "black"; 
    if (points[i].hovered) { 
     c.fillStyle = 'red'; 
    } 
    c.fill(); 
    } 
} 

最后你改变你的移动功能来切换hovered标志。我把那件作品留给你。

+0

听起来是资源密集的 – timo

+0

这是,请注意,我刚刚更新了我的答案。 –

+0

但它不是计算机上的资源密集型。你有这种循环运行每个HTML/JS游戏,他们这样做很好。 –

0

我添加了一个变量,用于存储点或不点与布尔值。我添加了一个变量来存储被击中点的索引。

var checkHit = true; 
var saveIndex = ""; 

然后我写了另一个if语句来检查的checkHit变量,如果是假的,我检查了鼠标光标仍范围内,它不再在范围内,我重绘帆布和重置变量。

if(!checkHit){ 
    if ((points[saveIndex][0] >= currMouseX-4 && points[saveIndex][0] <= currMouseX+4) && (points[saveIndex][1] >= currMouseY-4 && points[saveIndex][1] <= currMouseY+4)) { 
     console.log('point stil in range'); 
    } 
    else { 
     c.clearRect(0, 0, canvas.width, canvas.height); 
     drawPoints(); 
     checkHit = true; 
      saveIndex = ""; 
     console.log('Redraw'); 
    } 
    } 

FIDDLE

如果有人知道一个不太资源密集型的方法如针/大海捞针的方式,我很开放的建议/改进。

相关问题