为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

ITMISS 2023-07-06 10:15:19
我希望能够将鼠标悬停在不同的矩形上,并使矩形在悬停时改变颜色,我现在适用于最后一个矩形,但其他矩形被清除。这些矩形是使用类/构造函数、数组和循环创建的。代码如下:/*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 API 的第一个项目,它给我带来了很多麻烦,通常我可以通过类/id 来识别形状(如果它是用常规 HTML 元素制作的),但我不知道从这里该去哪里。 。我尝试循环遍历包含主板信息的数组,但无法让任何东西起作用。任何帮助表示赞赏!
查看完整描述

1 回答

?
Qyouu

TA贡献1786条经验 获得超11个赞

让我们逐步检查您的代码,以便更好地了解正在发生的情况。


一旦您将鼠标移到画布上,mousemove侦听器就会被触发并执行其关联的回调函数。


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


if (ctx.isPointInPath(square, event.offsetX, event.offsetY)) 

所以这个 if 语句检查当前鼠标位置是否在square内部。好吧,最大的问题是:正方形实际上是什么?


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


square = new Path2D();

square.rect(drawStartX, drawStartY, drawHeight, drawWidth);

显然它是一个Path2D,保存着其中一个条形的矩形 - 但实际上是哪一个呢?


我们来看看这个函数:


for (let i = 0; i < 10; i++) {

  b.push(new Board(0.05 * i, 0.25, 0.04, 0.03, 0));

}


function loadFunctions() {

  b.forEach(function(board) {

    board.drawBoard();

  })

}

在第一个循环中,您将使用Board的十个实例填充数组b,并且在 forEach 循环中,您将调用每个 Board 的drawBoard()函数。


这是什么意思呢?是的,square将始终保留对 bar 的引用,该 bar 函数上次被调用 - 它始终是数组中的最后一个 Board。


总结一下:您在 mousemove 回调中检查的唯一栏始终是数组中的最后一个栏。所以:


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);

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


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


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


let canvas = document.querySelector('#canvas'),

  ctx = canvas.getContext('2d');

let b = [];


class Board {

  constructor(startX, startY, height, width, angle) {

    this.startX = startX;

    this.startY = startY;

    this.height = height;

    this.width = width;

    this.angle = angle;

    this.square = new Path2D();

  }


  drawBoard() {

    let canvasWidth = window.innerWidth * 0.95,

      drawWidth = canvasWidth * this.width,

      drawHeight = canvasWidth * this.height,

      drawStartX = canvasWidth * this.startX,

      drawStartY = canvasWidth * this.startY;


    ctx.rotate(this.angle * Math.PI / 180);

    this.square.rect(drawStartX, drawStartY, drawHeight, drawWidth);

    ctx.fillStyle = 'red';

    ctx.fill(this.square);

  }

}


canvas.addEventListener('mousemove', function(event) {

  ctx.clearRect(0, 0, canvas.width, canvas.height);

  let currentSquare;

  for (let i = 0; i < b.length; i++) {

    currentSquare = b[i].square;

    if (ctx.isPointInPath(currentSquare, event.offsetX, event.offsetY)) {

      ctx.fillStyle = 'white';

    } else {

      ctx.fillStyle = 'red';

    }

    ctx.fill(currentSquare);

  }

});


for (let i = 0; i < 10; i++) {

  b.push(new Board(0.05 * i, 0.25, 0.04, 0.03, 0));

}


function loadFunctions() {

  b.forEach(function(board) {

    board.drawBoard();

  })

}

loadFunctions();

<canvas id="canvas" width=500 height=300></canvas>


查看完整回答
反对 回复 2023-07-06
  • 1 回答
  • 0 关注
  • 51 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信