DOM可移动形状的boundaryChecker函数故障求助
Hey there! I feel your pain—stuck on a boundary checker when you know the general issue (pass by value vs reference) but can't nail the implementation is super frustrating. Let's break this down step by step to get those shapes staying on screen properly.
First, Let's Clarify the Pass-by-Value vs Reference Issue
In JavaScript, objects are passed by reference, so if you were passing your dx/dy object directly into boundaryChecker and modifying it inside the function, you'd be altering the original object elsewhere in your code. Instead, we want to pass the numeric values of dx and dy (which are passed by value), calculate the valid movement, and return a new set of delta values if needed.
Pseudo-Code to Outline the Logic
Let's start with a clear pseudo-code blueprint so you can see the flow:
// Define the boundary checker function function boundaryChecker(shape, proposedDx, proposedDy) { // Calculate where the shape would end up if we apply this movement newX = shape.x + proposedDx newY = shape.y + proposedDy // Check if this new position is within screen bounds // (Assume we know screen width/height, and shape has width/height properties) if newX >= 0 AND newX + shape.width <= screenWidth AND newY >=0 AND newY + shape.height <= screenHeight: // Movement is valid—return the original proposed delta return { dx: proposedDx, dy: proposedDy } else: // Movement would push the shape out—calculate corrected delta correctedDx = proposedDx correctedDy = proposedDy // Fix horizontal position if needed if newX < 0: correctedDx = -shape.x // Push shape to left edge if newX + shape.width > screenWidth: correctedDx = screenWidth - shape.x - shape.width // Push shape to right edge // Fix vertical position if needed if newY < 0: correctedDy = -shape.y // Push shape to top edge if newY + shape.height > screenHeight: correctedDy = screenHeight - shape.y - shape.height // Push shape to bottom edge // Return the safe, corrected movement return { dx: correctedDx, dy: correctedDy } } // How to use it: 1. Get the desired movement values (e.g., from user input or animation steps) 2. Pass the shape, desired dx, and desired dy to boundaryChecker 3. Apply the returned safe delta to the shape's position
Working JavaScript Example
Here's a concrete implementation that works with DOM elements. I'll set up 4 shapes, a boundary checker, and a way to move them with keyboard input:
// Our 4 shapes stored as objects with position/size/color data const shapes = [ { x: 50, y: 50, width: 40, height: 40, color: 'crimson' }, { x: 200, y: 100, width: 50, height: 50, color: 'royalblue' }, { x: 350, y: 200, width: 30, height: 60, color: 'forestgreen' }, { x: 100, y: 300, width: 70, height: 30, color: 'goldenrod' } ]; // Get screen bounds (we'll use the window size here) const screenBounds = { width: window.innerWidth, height: window.innerHeight }; // The boundary checker function function boundaryChecker(shape, dx, dy) { const newX = shape.x + dx; const newY = shape.y + dy; let correctedDx = dx; let correctedDy = dy; // Check left/right boundaries if (newX < 0) { correctedDx = -shape.x; } else if (newX + shape.width > screenBounds.width) { correctedDx = screenBounds.width - shape.x - shape.width; } // Check top/bottom boundaries if (newY < 0) { correctedDy = -shape.y; } else if (newY + shape.height > screenBounds.height) { correctedDy = screenBounds.height - shape.y - shape.height; } // Return a NEW object with safe movement values (no reference issues!) return { dx: correctedDx, dy: correctedDy }; } // Function to move a shape and update the DOM function moveShape(shapeIndex, desiredDx, desiredDy) { const shape = shapes[shapeIndex]; const safeMove = boundaryChecker(shape, desiredDx, desiredDy); // Apply the safe movement shape.x += safeMove.dx; shape.y += safeMove.dy; // Re-render shapes to reflect new positions renderShapes(); } // Render shapes to the DOM function renderShapes() { const container = document.getElementById('shape-container'); container.innerHTML = ''; // Clear old shapes shapes.forEach(shape => { const shapeEl = document.createElement('div'); shapeEl.style.position = 'absolute'; shapeEl.style.left = `${shape.x}px`; shapeEl.style.top = `${shape.y}px`; shapeEl.style.width = `${shape.width}px`; shapeEl.style.height = `${shape.height}px`; shapeEl.style.backgroundColor = shape.color; container.appendChild(shapeEl); }); } // Initialize rendering renderShapes(); // Add keyboard control for the first shape (Arrow keys) document.addEventListener('keydown', (e) => { const step = 12; // Movement step size let dx = 0; let dy = 0; switch(e.key) { case 'ArrowLeft': dx = -step; break; case 'ArrowRight': dx = step; break; case 'ArrowUp': dy = -step; break; case 'ArrowDown': dy = step; break; } if (dx !== 0 || dy !== 0) { moveShape(0, dx, dy); } });
Key Tips to Avoid Reference Issues
- Pass numeric values, not objects: Instead of passing your
deltaobject into the checker, passdelta.dxanddelta.dyas separate numbers. This avoids accidentally modifying the original object. - Return new objects: When you need to return corrected movement values, create a new object (like
return { dx: correctedDx, dy: correctedDy }) instead of modifying the input object. - Check full shape bounds: Don't just check
shape.xandshape.y—remember to account for the shape's width and height to prevent edges from going off-screen. - Calculate first, move second: Always compute the potential new position before modifying the shape's actual position. This prevents visual glitches where shapes briefly go off-screen before being corrected.
内容的提问来源于stack exchange,提问作者kantor9991

