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

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


/*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 元素制作的),但我不知道从这里该去哪里。 。


我尝试循环遍历包含主板信息的数组,但无法让任何东西起作用。任何帮助表示赞赏!


ITMISS
浏览 55回答 1
1回答

Qyouu

让我们逐步检查您的代码,以便更好地了解正在发生的情况。一旦您将鼠标移到画布上,mousemove侦听器就会被触发并执行其关联的回调函数。在这个回调函数中,我们会发现它是第一行:if (ctx.isPointInPath(square, event.offsetX, event.offsetY))&nbsp;所以这个 if 语句检查当前鼠标位置是否在square内部。好吧,最大的问题是:正方形实际上是什么?如果我们进一步查看您的代码,我们会发现它是一个全局变量,它在 Board类函数中获取一些值drawBoard(),如下所示:square = new Path2D();square.rect(drawStartX, drawStartY, drawHeight, drawWidth);显然它是一个Path2D,保存着其中一个条形的矩形 - 但实际上是哪一个呢?我们来看看这个函数:for (let i = 0; i < 10; i++) {&nbsp; b.push(new Board(0.05 * i, 0.25, 0.04, 0.03, 0));}和function loadFunctions() {&nbsp; b.forEach(function(board) {&nbsp; &nbsp; board.drawBoard();&nbsp; })}在第一个循环中,您将使用Board的十个实例填充数组b,并且在 forEach 循环中,您将调用每个 Board 的drawBoard()函数。这是什么意思呢?是的,square将始终保留对 bar 的引用,该 bar 函数上次被调用 - 它始终是数组中的最后一个 Board。总结一下:您在 mousemove 回调中检查的唯一栏始终是数组中的最后一个栏。所以:if (ctx.isPointInPath(square, event.offsetX, event.offsetY)) {&nbsp; ctx.fillStyle = 'white';&nbsp;}else {&nbsp; ctx.fillStyle = 'red';&nbsp;&nbsp;}&nbsp;&nbsp;ctx.clearRect(0, 0, canvas.width, canvas.height);ctx.fill(square);翻译成简单的英语意味着:如果该点在正方形的边界内,则将 fillStyle 设置为红色,清除整个屏幕,然后用红色填充一个栏。您需要做的是检查数组中每个Board 实例的鼠标位置。但这并不难 - 只需将 Path2D 设为 Board 的类变量,并在回调函数内循环遍历整个数组,并将鼠标位置与每个 Board 的 .square属性进行比较。这是一个示例(只需单击“运行代码片段”):let canvas = document.querySelector('#canvas'),&nbsp; ctx = canvas.getContext('2d');let b = [];class Board {&nbsp; constructor(startX, startY, height, width, angle) {&nbsp; &nbsp; this.startX = startX;&nbsp; &nbsp; this.startY = startY;&nbsp; &nbsp; this.height = height;&nbsp; &nbsp; this.width = width;&nbsp; &nbsp; this.angle = angle;&nbsp; &nbsp; this.square = new Path2D();&nbsp; }&nbsp; drawBoard() {&nbsp; &nbsp; let canvasWidth = window.innerWidth * 0.95,&nbsp; &nbsp; &nbsp; drawWidth = canvasWidth * this.width,&nbsp; &nbsp; &nbsp; drawHeight = canvasWidth * this.height,&nbsp; &nbsp; &nbsp; drawStartX = canvasWidth * this.startX,&nbsp; &nbsp; &nbsp; drawStartY = canvasWidth * this.startY;&nbsp; &nbsp; ctx.rotate(this.angle * Math.PI / 180);&nbsp; &nbsp; this.square.rect(drawStartX, drawStartY, drawHeight, drawWidth);&nbsp; &nbsp; ctx.fillStyle = 'red';&nbsp; &nbsp; ctx.fill(this.square);&nbsp; }}canvas.addEventListener('mousemove', function(event) {&nbsp; ctx.clearRect(0, 0, canvas.width, canvas.height);&nbsp; let currentSquare;&nbsp; for (let i = 0; i < b.length; i++) {&nbsp; &nbsp; currentSquare = b[i].square;&nbsp; &nbsp; if (ctx.isPointInPath(currentSquare, event.offsetX, event.offsetY)) {&nbsp; &nbsp; &nbsp; ctx.fillStyle = 'white';&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; ctx.fillStyle = 'red';&nbsp; &nbsp; }&nbsp; &nbsp; ctx.fill(currentSquare);&nbsp; }});for (let i = 0; i < 10; i++) {&nbsp; b.push(new Board(0.05 * i, 0.25, 0.04, 0.03, 0));}function loadFunctions() {&nbsp; b.forEach(function(board) {&nbsp; &nbsp; board.drawBoard();&nbsp; })}loadFunctions();<canvas id="canvas" width=500 height=300></canvas>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript