Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如果我有多个形状,如何将鼠标悬停在画布中的形状上并更改颜色?_Javascript_Html5 Canvas - Fatal编程技术网

Javascript 如果我有多个形状,如何将鼠标悬停在画布中的形状上并更改颜色?

Javascript 如果我有多个形状,如何将鼠标悬停在画布中的形状上并更改颜色?,javascript,html5-canvas,Javascript,Html5 Canvas,我希望能够将鼠标悬停在不同的矩形上,并使矩形在悬停时改变颜色,我现在所做的工作适用于最后一个矩形,但其他矩形被清除。矩形是使用类/构造函数、数组和循环创建的。代码如下: /*Variables*/ let canvas = document.querySelector('#canvas'), ctx = canvas.getContext('2d'), square; /*Board Class*/ class Board { constructor(startX, s

我希望能够将鼠标悬停在不同的矩形上,并使矩形在悬停时改变颜色,我现在所做的工作适用于最后一个矩形,但其他矩形被清除。矩形是使用类/构造函数、数组和循环创建的。代码如下:

/*Variables*/
let canvas = document.querySelector('#canvas'),
    ctx = canvas.getContext('2d'),
    square;

/*Board Class*/
class Board {
    constructor(startX, startY, height, width, angle) {
      this.startX = startX;
      this.startY = startY;
      this.height = height;
      this.width = width;
      this.angle = angle;
    }

      drawBoard() {
        let canvasWidth = window.innerWidth * .95,
            drawWidth = canvasWidth * this.width,
            drawHeight = canvasWidth * this.height,
            drawStartX = canvasWidth * this.startX,
            drawStartY = canvasWidth * this.startY;
        
        square = new Path2D();
        ctx.rotate(this.angle * Math.PI / 180);
        square.rect(drawStartX, drawStartY, drawHeight, drawWidth);
        ctx.fillStyle = 'red';
        ctx.fill(square);
      }
  }

/*Event Listener for changing rectangle color and redrawing*/
  canvas.addEventListener('mousemove', function(event) {
    if (ctx.isPointInPath(square, event.offsetX, event.offsetY)) {
      ctx.fillStyle = 'white'; 
    }
    else {
      ctx.fillStyle = 'red';  
    }  
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fill(square);
  });

  /*Instantiate Array*/
  let b = [];
  /*Loop to create boards and push to array*/
  for(let i = 1; i < 11; i++){
    b.push(new Board(.05 * i, .25, .04, .03, 0));
    }

/*Function to loop through array and draw boards when page loads*/
function loadFunctions(){
    background.draw();
    b.forEach(function(board){
        board.drawBoard();
    })
}
/*变量*/
让canvas=document.querySelector(“#canvas”),
ctx=canvas.getContext('2d'),
广场
/*板级*/
班级委员会{
建造商(起点、起点、高度、宽度、角度){
this.startX=startX;
this.startY=startY;
高度=高度;
这个。宽度=宽度;
这个角度=角度;
}
拖板{
让canvasWidth=window.innerWidth*.95,
drawWidth=canvasWidth*this.width,
drawHeight=画布宽度*this.height,
drawStartX=画布宽度*this.startX,
drawStartY=画布宽度*this.startY;
square=新路径2d();
ctx.旋转(此角度*数学PI/180);
square.rect(drawStartX、drawStartY、drawHeight、drawWidth);
ctx.fillStyle='红色';
ctx填充(方形);
}
}
/*用于更改矩形颜色和重绘的事件侦听器*/
canvas.addEventListener('mousemove',函数(事件){
if(ctx.isPointInPath(square、event.offsetX、event.offsetY)){
ctx.fillStyle='白色';
}
否则{
ctx.fillStyle='红色';
}  
clearRect(0,0,canvas.width,canvas.height);
ctx填充(方形);
});
/*实例化数组*/
设b=[];
/*循环创建板并推送到阵列*/
for(设i=1;i<11;i++){
b、 推动(新板(.05*i、.25、.04、.03、0));
}
/*当页面加载时,用于循环通过阵列和绘图板的函数*/
函数loadFunctions(){
background.draw();
b、 forEach(功能(板){
板。拖板();
})
}
这是我第一个使用Canvas API的项目,它给我带来了很多麻烦,通常我可以通过class/id来识别形状,如果它是使用常规HTML元素生成的,但是我不确定从这里开始该怎么做

我尝试过在包含线路板信息的数组中循环,但无法使任何内容正常工作。感谢您的帮助


谢谢

让我们逐步浏览您的代码,以更好地了解正在发生的事情

当您在画布上移动鼠标时,mousemove侦听器将被触发并执行其关联的回调函数

在这个回调函数中,我们会发现这是第一行:

if (ctx.isPointInPath(square, event.offsetX, event.offsetY)) 
因此,如果该if语句检查当前鼠标位置是否在正方形内。好吧,最大的问题是:到底是什么正方形

如果我们仔细查看一下您的代码,就会发现它是一个全局变量,它在Board
drawBoard()
函数中获取一些值,如下所示:

square = new Path2D();
square.rect(drawStartX, drawStartY, drawHeight, drawWidth);
显然,它是一个包含其中一个条的矩形的路径2D,但是实际上是哪个

让我们看看这个函数:

for (let i = 0; i < 10; i++) {
  b.push(new Board(0.05 * i, 0.25, 0.04, 0.03, 0));
}
在第一个循环中,您用十个Board实例填充数组b,在forEach循环中,您调用每个Board的drawBoard()函数

这一切意味着什么?是的,square将始终保存对该条的引用,该条的drawBoard()函数上次被调用过,它将始终是数组中的最后一块板

总而言之:在mousemove回调中检查的唯一条是始终数组中的最后一条。 因此:

翻译成简单的英语意思是:如果点在正方形的边界内,将fillStyle设置为红色,清除整个屏幕,然后用红色填充一个条

您需要做的是使用阵列中的每个
板实例检查鼠标位置。不过这并不难-只要将Path2D设置为Board的类变量,并在整个数组中的回调函数循环中,将鼠标位置与每个Board的.square属性进行比较即可

下面是一个示例(只需单击“运行代码片段”):

let canvas=document.querySelector(“#canvas”),
ctx=canvas.getContext('2d');
设b=[];
班级委员会{
建造商(起点、起点、高度、宽度、角度){
this.startX=startX;
this.startY=startY;
高度=高度;
这个。宽度=宽度;
这个角度=角度;
this.square=新路径2d();
}
拖板{
让canvasWidth=window.innerWidth*0.95,
drawWidth=canvasWidth*this.width,
drawHeight=画布宽度*this.height,
drawStartX=画布宽度*this.startX,
drawStartY=画布宽度*this.startY;
ctx.旋转(此角度*数学PI/180);
this.square.rect(drawStartX、drawStartY、drawsheight、drawswidth);
ctx.fillStyle='红色';
ctx.填充(此方形);
}
}
canvas.addEventListener('mousemove',函数(事件){
clearRect(0,0,canvas.width,canvas.height);
让我们做一个正方形;
for(设i=0;i
function loadFunctions() {
  b.forEach(function(board) {
    board.drawBoard();
  })
}
if (ctx.isPointInPath(square, event.offsetX, event.offsetY)) {
  ctx.fillStyle = 'white'; 
}
else {
  ctx.fillStyle = 'red';  
}  
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fill(square);