如何将HTML元素动画转为JS变量,用PhysicsJS实现墙体反弹小球且无碰撞?
解决方案:用PhysicsJS替代CSS动画实现可控物理墙体
Got it, let's fix this up so your walls are fully controlled by PhysicsJS instead of CSS animations—this way we can handle proper physics interactions like ball bouncing and wall collision prevention. Here's the adjusted approach:
Key Changes Made:
- Removed all CSS animations (we'll handle wall movement via PhysicsJS forces for smoother, physics-aware motion)
- Defined each wall (left, right, top, bottom) as a heavy PhysicsJS
rectanglebody so they don't get knocked around by the ball - Added keyboard controls to move walls while keeping them within window bounds
- Updated the physics world to include proper collision detection between all bodies (walls + ball)
Full Updated Code
HTML (Cleaned-Up Styles):
<!DOCTYPE html> <html> <head> <style> html, body, #viewport { margin: 0; background: #ffffff; height: 100%; overflow: hidden; } canvas { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } </style> <script data-main="scripts/config.js" src="scripts/require.js"></script> </head> <body> <canvas id="viewport"></canvas> </body> </html>
JavaScript (config.js):
require(['full'], function(Physics) { Physics(function(world) { // Get initial viewport dimensions let viewWidth = window.innerWidth; let viewHeight = window.innerHeight; let viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight); // Create canvas renderer const renderer = Physics.renderer('canvas', { el: 'viewport', width: viewWidth, height: viewHeight }); world.add(renderer); world.on('step', () => world.render()); // Edge bounce to keep objects inside window const edgeBounce = Physics.behavior('edge-collision-detection', { aabb: viewportBounds, restitution: 0.99, cof: 0.8 }); // Handle window resize window.addEventListener('resize', function() { viewWidth = window.innerWidth; viewHeight = window.innerHeight; renderer.el.width = viewWidth; renderer.el.height = viewHeight; viewportBounds = Physics.aabb(0, 0, viewWidth, viewHeight); edgeBounce.setAABB(viewportBounds); // Reposition walls to stay on screen edges leftWall.state.pos.set(50, viewHeight / 2); rightWall.state.pos.set(viewWidth - 50, viewHeight / 2); topWall.state.pos.set(viewWidth / 2, 50); bottomWall.state.pos.set(viewWidth / 2, viewHeight - 50); }, true); // Define wall properties const wallThickness = 100; const wallMass = 1000; // Heavy mass prevents ball from moving walls // Create wall bodies const leftWall = Physics.body('rectangle', { width: wallThickness, height: viewHeight, x: wallThickness / 2, y: viewHeight / 2, mass: wallMass, restitution: 0.99, cof: 0.8, label: 'wall', styles: { fillStyle: 'black' } }); const rightWall = Physics.body('rectangle', { width: wallThickness, height: viewHeight, x: viewWidth - wallThickness / 2, y: viewHeight / 2, mass: wallMass, restitution: 0.99, cof: 0.8, label: 'wall', styles: { fillStyle: 'black' } }); const topWall = Physics.body('rectangle', { width: viewWidth, height: wallThickness, x: viewWidth / 2, y: wallThickness / 2, mass: wallMass, restitution: 0.99, cof: 0.8, label: 'wall', styles: { fillStyle: 'black' } }); const bottomWall = Physics.body('rectangle', { width: viewWidth, height: wallThickness, x: viewWidth / 2, y: viewHeight - wallThickness / 2, mass: wallMass, restitution: 0.99, cof: 0.8, label: 'wall', styles: { fillStyle: 'black' } }); // Add walls to physics world world.add([leftWall, rightWall, topWall, bottomWall]); // Keyboard controls for wall movement const moveSpeed = 0.06; document.onkeydown = function(evt) { evt = evt || window.event; evt.preventDefault(); switch (evt.keyCode) { // Left arrow: move left wall left (stay within window) case 37: if (leftWall.state.pos.x - wallThickness / 2 > 0) { leftWall.applyForce({ x: -moveSpeed, y: 0 }); } break; // Right arrow: move right wall right case 39: if (rightWall.state.pos.x + wallThickness / 2 < viewWidth) { rightWall.applyForce({ x: moveSpeed, y: 0 }); } break; // Up arrow: move top wall up case 38: if (topWall.state.pos.y - wallThickness / 2 > 0) { topWall.applyForce({ x: 0, y: -moveSpeed }); } break; // Down arrow: move bottom wall down case 40: if (bottomWall.state.pos.y + wallThickness / 2 < viewHeight) { bottomWall.applyForce({ x: 0, y: moveSpeed }); } break; } }; // Keep your original interactive attractor feature const attractor = Physics.behavior('attractor', { order: 0, strength: 0.002 }); world.on({ 'interact:poke': (pos) => { world.wakeUpAll(); attractor.position(pos); world.add(attractor); }, 'interact:move': (pos) => attractor.position(pos), 'interact:release': () => { world.wakeUpAll(); world.remove(attractor); } }); // Add core physics behaviors world.add([ Physics.behavior('interactive', { el: renderer.container }), Physics.behavior('constant-acceleration'), // Simulate gravity Physics.behavior('body-collision-detection'), // Detect all body collisions Physics.behavior('sweep-prune'), // Optimize collision performance Physics.behavior('body-impulse-response'), // Handle collision bounces edgeBounce ]); // Add the bouncing ball world.add(Physics.body('circle', { x: viewWidth * 0.5, y: viewHeight * 0.5, vx: 0.15, vy: 0.1, radius: 40, restitution: 0.99, styles: { fillStyle: 'red' } })); // Start the physics ticker Physics.util.ticker.on((time) => world.step(time)); Physics.util.ticker.start(); }); });
How This Works:
- Wall Physics: Walls are heavy bodies so they remain stable when hit by the ball, and their movement is controlled via applied forces for natural motion.
- Collision Safety: We check wall positions before moving them to ensure they never go outside the window or overlap with each other (you can extend this with wall-to-wall collision detection if needed).
- Smooth Bounces: The
body-collision-detectionandbody-impulse-responsebehaviors handle realistic ball-wall interactions automatically.
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

