DeepSeek
DeepSeek R1 0528 (May '25)
Respuesta final
# Bouncing Balls in a Spinning Hexagon
I'll create an animation with 10 balls bouncing inside a rotating hexagon using pure JavaScript and Canvas API.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bouncing Balls in Spinning Hexagon</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #1a1a2e, #16213e);
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.container {
position: relative;
width: 800px;
max-width: 95%;
text-align: center;
}
canvas {
background: rgba(0, 0, 0, 0.2);
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}
h1 {
color: #fff;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
margin-bottom: 20px;
font-weight: 600;
letter-spacing: 1px;
}
.controls {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 20px;
flex-wrap: wrap;
}
button {
background: #4cc9f0;
color: #1a1a2e;
border: none;
padding: 10px 20px;
border-radius: 50px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
button:hover {
background: #4361ee;
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
}
button:active {
transform: translateY(1px);
}
.info {
color: rgba(255, 255, 255, 0.7);
margin-top: 15px;
font-size: 14px;
}
</style>
</head>
<body>
<div class="container">
<h1>Bouncing Balls in a Spinning Hexagon</h1>
<canvas id="canvas" width="700" height="500"></canvas>
<div class="controls">
<button id="speedUp">Speed Up</button>
<button id="slowDown">Slow Down</button>
<button id="reset">Reset</button>
</div>
<div class="info">Click anywhere to add more balls (max 20)</div>
</div>
<script>
// Canvas setup
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
// Hexagon properties
const hexRadius = 180;
let hexRotation = 0;
let rotationSpeed = 0.005;
// Ball properties
const balls = [];
const maxBalls = 20;
const colors = [
'#FF5252', '#FF4081', '#E040FB', '#7C4DFF',
'#536DFE', '#448AFF', '#40C4FF', '#18FFFF',
'#64FFDA', '#69F0AE', '#B2FF59', '#EEFF41'
];
// Initialize balls
function initBalls(count) {
for (let i = 0; i < count; i++) {
createBall();
}
}
// Create a new ball
function createBall() {
if (balls.length >= maxBalls) return;
const radius = 10 + Math.random() * 10;
const angle = Math.random() * Math.PI * 2;
const distance = Math.random() * (hexRadius - radius - 20);
const ball = {
x: centerX + Math.cos(angle) * distance,
y: centerY + Math.sin(angle) * distance,
radius: radius,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
color: colors[Math.floor(Math.random() * colors.length)]
};
balls.push(ball);
}
// Get hexagon vertices
function getHexagonVertices() {
const vertices = [];
for (let i = 0; i < 6; i++) {
const angle = hexRotation + i * Math.PI / 3;
vertices.push({
x: centerX + hexRadius * Math.cos(angle),
y: centerY + hexRadius * Math.sin(angle)
});
}
return vertices;
}
// Get hexagon edges
function getHexagonEdges(vertices) {
const edges = [];
for (let i = 0; i < 6; i++) {
edges.push({
start: vertices[i],
end: vertices[(i + 1) % 6]
});
}
return edges;
}
// Calculate distance from point to line segment
function distanceToSegment(point, edge) {
const A = point.x - edge.start.x;
const B = point.y - edge.start.y;
const C = edge.end.x - edge.start.x;
const D = edge.end.y - edge.start.y;
const dot = A * C + B * D;
const lenSq = C * C + D * D;
let param = -1;
if (lenSq !== 0) {
param = dot / lenSq;
}
let xx, yy;
if (param < 0) {
xx = edge.start.x;
yy = edge.start.y;
} else if (param > 1) {
xx = edge.end.x;
yy = edge.end.y;
} else {
xx = edge.start.x + param * C;
yy = edge.start.y + param * D;
}
const dx = point.x - xx;
const dy = point.y - yy;
return Math.sqrt(dx * dx + dy * dy);
}
// Calculate normal vector for an edge
function getEdgeNormal(edge) {
const dx = edge.end.x - edge.start.x;
const dy = edge.end.y - edge.start.y;
const length = Math.sqrt(dx * dx + dy * dy);
// Normal vector (perpendicular to the edge)
return {
x: -dy / length,
y: dx / length
};
}
// Update ball positions and handle collisions
function updateBalls(edges) {
for (const ball of balls) {
// Update position
ball.x += ball.vx;
ball.y += ball.vy;
// Check collision with hexagon edges
for (const edge of edges) {
const distance = distanceToSegment(ball, edge);
if (distance < ball.radius) {
const normal = getEdgeNormal(edge);
// Reflect velocity vector
const dot = ball.vx * normal.x + ball.vy * normal.y;
ball.vx = ball.vx - 2 * dot * normal.x;
ball.vy = ball.vy - 2 * dot * normal.y;
// Move ball outside collision
const overlap = ball.radius - distance;
ball.x += normal.x * overlap;
ball.y += normal.y * overlap;
}
}
// Add some gravity effect
ball.vy += 0.05;
// Damping to prevent infinite bouncing
ball.vx *= 0.995;
ball.vy *= 0.995;
}
}
// Draw hexagon
function drawHexagon(vertices) {
ctx.beginPath();
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let i = 1; i < 6; i++) {
ctx.lineTo(vertices[i].x, vertices[i].y);
}
ctx.closePath();
ctx.strokeStyle = 'rgba(76, 201, 240, 0.8)';
ctx.lineWidth = 3;
ctx.stroke();
// Draw center point
ctx.beginPath();
ctx.arc(centerX, centerY, 5, 0, Math.PI * 2);
ctx.fillStyle = '#4cc9f0';
ctx.fill();
}
// Draw balls
function drawBalls() {
for (const ball of balls) {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = ball.color;
ctx.fill();
// Add shine effect
ctx.beginPath();
ctx.arc(ball.x - ball.radius/3, ball.y - ball.radius/3, ball.radius/3, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
ctx.fill();
}
}
// Draw background effects
function drawBackground() {
// Draw grid
ctx.strokeStyle = 'rgba(76, 201, 240, 0.05)';
ctx.lineWidth = 1;
// Vertical lines
for (let x = 0; x < canvas.width; x += 30) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
// Horizontal lines
for (let y = 0; y < canvas.height; y += 30) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
// Draw center circle
ctx.beginPath();
ctx.arc(centerX, centerY, hexRadius - 20, 0, Math.PI * 2);
ctx.strokeStyle = 'rgba(76, 201, 240, 0.1)';
ctx.stroke();
}
// Animation loop
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Update hexagon rotation
hexRotation += rotationSpeed;
// Get hexagon vertices and edges
const vertices = getHexagonVertices();
const edges = getHexagonEdges(vertices);
// Update and draw
drawBackground();
drawHexagon(vertices);
updateBalls(edges);
drawBalls();
requestAnimationFrame(animate);
}
// Event listeners
document.getElementById('speedUp').addEventListener('click', () => {
rotationSpeed = Math.min(rotationSpeed + 0.002, 0.02);
});
document.getElementById('slowDown').addEventListener('click', () => {
rotationSpeed = Math.max(rotationSpeed - 0.002, 0.001);
});
document.getElementById('reset').addEventListener('click', () => {
balls.length = 0;
initBalls(10);
rotationSpeed = 0.005;
});
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Create a ball at click position
if (balls.length < maxBalls) {
balls.push({
x: x,
y: y,
radius: 8 + Math.random() * 12,
vx: (Math.random() - 0.5) * 4,
vy: (Math.random() - 0.5) * 4,
color: colors[Math.floor(Math.random() * colors.length)]
});
}
});
// Initialize and start animation
initBalls(10);
animate();
</script>
</body>
</html>
```
## Features of this Animation:
1. **Spinning Hexagon**: A blue hexagon rotates smoothly at the center of the canvas
2. **10 Bouncing Balls**: Colorful balls with random sizes and velocities bounce realistically inside the hexagon
3. **Physics Simulation**: Balls collide with the hexagon walls using proper reflection physics
4. **Interactive Controls**:
- Speed Up: Increases hexagon rotation speed
- Slow Down: Decreases hexagon rotation speed
- Reset: Clears all balls and resets to initial state
5. **Click to Add Balls**: Click anywhere on the canvas to add more balls (up to 20)
6. **Visual Effects**:
- Subtle grid background
- Ball shine effects
- Smooth animations
The balls bounce realistically off the rotating hexagon walls, with gravity and damping effects to create natural-looking motion. The interface is clean and modern with a dark gradient background that makes the colorful balls stand out.