簡體   English   中英

如果我有多個形狀,如何將鼠標懸停在畫布中的形狀上並更改顏色?

[英]How can I hover over a shape in canvas and change the color if I have multiple shapes?

我希望能夠將鼠標懸停在不同的矩形上,並在懸停時讓矩形改變顏色,我現在對最后一個矩形有效,但其他矩形被清除。 矩形是使用類/構造函數、數組和循環創建的。 代碼如下:

/*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 的第一個項目,它給我帶來了很多麻煩,通常我可以通過 class/id 識別形狀,如果它是用常規 HTML 元素制作的,但我不知道從哪里開始.. .

我試過遍歷包含電路板信息的數組,但無法獲得任何工作。 任何幫助表示贊賞!

謝謝

讓我們逐步完成您的代碼,以更好地了解正在發生的事情。

只要您將鼠標移到畫布上, 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 的引用,即上次調用 drawBoard() 函數時 - 這將始終是數組中的最后一個 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM