Canvas作业求助:实现点击删除选中矩形的纯JavaScript方案
Hey there! Let's get that click-to-delete feature working for your Canvas rectangles. First, let's break down the gaps in your current code, then build the solution step by step with pure JavaScript.
What's Missing in Your Current Code
- You're only storing the rectangle size in the
boxesarray (boxes.push(randomNum)), but we need complete rectangle data (x position, y position, size, color) to track which one gets clicked. - Global variable declarations are a bit messy (like
MyCanvasnot usingvar), which can lead to unexpected behavior. - The loop inside
setIntervalis unnecessary—you just need to generate one new rectangle per interval and add it to the array.
Step-by-Step Solution
1. Refactor Rectangle Data Storage
First, let's store full objects for each rectangle so we can track their positions and colors. We'll move the boxes array to the global scope so all functions can access it:
// Global variables to track rectangles and Canvas context var boxes = []; var MyCanvas; var twoDimention; var Interval; function getRandomColor() { var letters = '0123456789ABCDEF'; var color = '#'; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; } function game(){ MyCanvas = document.getElementById("MyCanvas"); twoDimention = MyCanvas.getContext("2d"); // Reset everything if we restart the game clearInterval(Interval); boxes = []; Interval = setInterval(function () { // Generate safe random positions (so rectangles don't go off-screen) var randomNumX = Math.floor(Math.random() * (MyCanvas.width - 160)); var randomNumY = Math.floor(Math.random() * (MyCanvas.height - 160)); var randomNum = Math.ceil((Math.random() * 150) + 10); var color = getRandomColor(); // Push a full rectangle object to our array boxes.push({ x: randomNumX, y: randomNumY, size: randomNum, color: color }); // Draw the new rectangle drawRect(boxes[boxes.length - 1]); }, 1000); } // Helper function to draw a single rectangle (cleaner code!) function drawRect(rect) { twoDimention.fillStyle = rect.color; twoDimention.fillRect(rect.x, rect.y, rect.size, rect.size); } function clearMe(){ clearInterval(Interval); }
2. Add Click Event Handling
Canvas doesn't have built-in element click events, so we'll listen for clicks on the Canvas itself, calculate where the click happened, and check if it overlaps with any rectangle:
// Add click listener once the page loads window.addEventListener('load', function() { MyCanvas = document.getElementById("MyCanvas"); MyCanvas.addEventListener('click', function(e) { // Get the click position relative to the Canvas (not the whole window) var canvasBounds = MyCanvas.getBoundingClientRect(); var clickX = e.clientX - canvasBounds.left; var clickY = e.clientY - canvasBounds.top; // Check rectangles from last to first (since later rectangles are on top) for (var i = boxes.length - 1; i >= 0; i--) { var box = boxes[i]; // Check if the click is inside the rectangle's bounds if (clickX >= box.x && clickX <= box.x + box.size && clickY >= box.y && clickY <= box.y + box.size) { // Remove the clicked rectangle from the array boxes.splice(i, 1); // Clear the Canvas and redraw all remaining rectangles twoDimention.clearRect(0, 0, MyCanvas.width, MyCanvas.height); boxes.forEach(drawRect); break; // Stop checking once we find the topmost clicked rectangle } } }); });
3. Key Optimizations Explained
- Reverse loop for clicks: Later-drawn rectangles are on top of earlier ones, so we check them first to make sure we delete the one the user actually clicked on.
- Safe random positions: We subtract the maximum rectangle size from the Canvas width/height so rectangles never go off-screen.
- Separate draw function: Makes the code cleaner and easier to reuse when we need to redraw all rectangles after a deletion.
Full Working JavaScript Code
Here's the complete code put together:
var boxes = []; var MyCanvas; var twoDimention; var Interval; function getRandomColor() { var letters = '0123456789ABCDEF'; var color = '#'; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; } function game(){ MyCanvas = document.getElementById("MyCanvas"); twoDimention = MyCanvas.getContext("2d"); clearInterval(Interval); boxes = []; Interval = setInterval(function () { var randomNumX = Math.floor(Math.random() * (MyCanvas.width - 160)); var randomNumY = Math.floor(Math.random() * (MyCanvas.height - 160)); var randomNum = Math.ceil((Math.random() * 150) + 10); var color = getRandomColor(); boxes.push({ x: randomNumX, y: randomNumY, size: randomNum, color: color }); drawRect(boxes[boxes.length - 1]); }, 1000); } function drawRect(rect) { twoDimention.fillStyle = rect.color; twoDimention.fillRect(rect.x, rect.y, rect.size, rect.size); } function clearMe(){ clearInterval(Interval); } window.addEventListener('load', function() { MyCanvas = document.getElementById("MyCanvas"); MyCanvas.addEventListener('click', function(e) { var canvasBounds = MyCanvas.getBoundingClientRect(); var clickX = e.clientX - canvasBounds.left; var clickY = e.clientY - canvasBounds.top; for (var i = boxes.length - 1; i >= 0; i--) { var box = boxes[i]; if (clickX >= box.x && clickX <= box.x + box.size && clickY >= box.y && clickY <= box.y + box.size) { boxes.splice(i, 1); twoDimention.clearRect(0, 0, MyCanvas.width, MyCanvas.height); boxes.forEach(drawRect); break; } } }); });
Just replace your existing functions.js code with this, and you'll have working click-to-delete functionality for your rectangles.
内容的提问来源于stack exchange,提问作者Guy

