File size: 5,991 Bytes
57b3cfe d19c729 91145e2 ed6a27c 91145e2 ed6a27c 91145e2 ed6a27c 91145e2 ed6a27c 91145e2 ed6a27c d19c729 91145e2 ed6a27c 91145e2 ed6a27c 91145e2 ed6a27c 91145e2 d19c729 91145e2 57b3cfe 91145e2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
import streamlit as st
def create_animation_app():
st.title("Bouncing Balls & Jellyfish in a Sphere")
html_content = """
<style>
.container {
position: relative;
width: 800px;
height: 600px;
margin: auto;
}
#animationCanvas, #p5Canvas {
position: absolute;
top: 0;
left: 0;
}
canvas {
background-color: transparent;
}
</style>
<div class="container">
<canvas id="animationCanvas"></canvas>
<div id="p5Container"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script>
// Jellyfish Animation
const jellyfishCanvas = document.getElementById('animationCanvas');
const ctx = jellyfishCanvas.getContext('2d');
jellyfishCanvas.width = 800;
jellyfishCanvas.height = 600;
let t = 0;
function mag(x, y) {
return Math.sqrt(x * x + y * y);
}
function a(x, y) {
const k = x/8 - 25;
const e = y/8 - 25;
const d = mag(k, e)**2 / 99;
const q = x/3 + k * 0.5 / Math.cos(y*5) * Math.sin(d*d - t);
const c = d/2 - t/8;
const xPos = q * Math.sin(c) + e * Math.sin(d + k - t) + 400;
const yPos = (q + y/8 + d*9) * Math.cos(c) + 300;
return [xPos, yPos];
}
function getColor(x, y, t) {
const hue = (Math.sin(t/2) * 360 + x/3 + y/3) % 360;
const saturation = 70 + Math.sin(t) * 30;
const lightness = 50 + Math.cos(t/2) * 20;
return `hsla(${hue}, ${saturation}%, ${lightness}%, 0.5)`;
}
function drawJellyfish() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, jellyfishCanvas.width, jellyfishCanvas.height);
ctx.lineWidth = 1.5;
for(let y = 99; y < 300; y += 4) {
for(let x = 99; x < 300; x += 2) {
const [px, py] = a(x, y);
const color = getColor(x, y, t);
ctx.strokeStyle = color;
ctx.beginPath();
ctx.moveTo(px, py);
ctx.lineTo(px + 1, py + 1);
ctx.stroke();
}
}
t += Math.PI / 120;
requestAnimationFrame(drawJellyfish);
}
// Initialize jellyfish animation
drawJellyfish();
// Bouncing Balls Animation with p5.js
new p5((sketch) => {
let balls = [];
const numBalls = 100;
const sphereRadius = 200;
let rotation = {x: 0, y: 0};
class Ball {
constructor() {
this.pos = p5.Vector.random3D().mult(sphereRadius * 0.8);
this.vel = p5.Vector.random3D().mult(sketch.random(1, 3));
this.radius = 3;
}
update() {
// Update position
this.pos.add(this.vel);
// Sphere collision
let distance = this.pos.mag();
if (distance > sphereRadius - this.radius) {
let normal = this.pos.copy().normalize();
let reflection = this.vel.copy().reflect(normal);
this.vel.set(reflection);
this.pos = normal.mult(sphereRadius - this.radius);
}
}
display() {
sketch.push();
sketch.translate(this.pos.x, this.pos.y, this.pos.z);
sketch.fill(255, 255, 0);
sketch.noStroke();
sketch.sphere(this.radius);
sketch.pop();
}
}
function checkCollisions() {
for(let i = 0; i < balls.length; i++) {
for(let j = i+1; j < balls.length; j++) {
let b1 = balls[i];
let b2 = balls[j];
let d = b1.pos.dist(b2.pos);
let minDist = b1.radius + b2.radius;
if (d < minDist) {
let normal = p5.Vector.sub(b1.pos, b2.pos).normalize();
let overlap = (minDist - d) / 2;
// Position correction
b1.pos.add(p5.Vector.mult(normal, overlap));
b2.pos.sub(p5.Vector.mult(normal, overlap));
// Velocity adjustment
let velDiff = p5.Vector.sub(b1.vel, b2.vel);
let impulse = velDiff.dot(normal) / (1 + 1);
b1.vel.sub(p5.Vector.mult(normal, impulse));
b2.vel.add(p5.Vector.mult(normal, impulse));
}
}
}
}
sketch.setup = () => {
const p5Canvas = sketch.createCanvas(800, 600, sketch.WEBGL);
p5Canvas.parent('p5Container');
sketch.frameRate(30);
// Create balls
for(let i = 0; i < numBalls; i++) {
balls.push(new Ball());
}
};
sketch.draw = () => {
sketch.background(0, 0);
sketch.rotateX(rotation.x);
sketch.rotateY(rotation.y);
// Slowly rotate the sphere
rotation.x += 0.002;
rotation.y += 0.003;
// Draw wireframe sphere
sketch.push();
sketch.noFill();
sketch.stroke(255, 50);
sketch.sphere(sphereRadius);
sketch.pop();
// Update and display balls
balls.forEach(ball => {
ball.update();
ball.display();
});
checkCollisions();
};
}, 'p5Container');
</script>
"""
st.components.v1.html(html_content, height=600)
if __name__ == "__main__":
create_animation_app() |