blob: 51ab3178addd49b3d9a19b03479d59be6aabf00b [file] [log] [blame]
simon.fraser@apple.com099f65f2016-09-09 00:51:06 +00001<!DOCTYPE html>
2
3<html>
4<head>
5 <meta name="viewport" content="initial-scale=1.0">
6 <style>
7 body {
8 margin: 0;
9 }
10 #stage {
11 position: relative;
12 width: 320px;
13 height: 320px;
14 border: 1px solid black;
15 overflow: hidden;
16 z-index: 0;
17 }
18
19 .particle-h {
20 position: absolute;
21 animation: horizontal infinite 2s alternate ease-in-out;
22 }
23
24 .particle-v {
25 position: absolute;
26 height: 20px;
27 width: 20px;
28 background-color: blue;
29 border-radius: 50%;
30 animation: vertical infinite 2s alternate ease-in-out;
31 }
32
33 @keyframes horizontal {
34 from {
35 transform: translateX(0);
36 }
37 50% {
38 transform: translateX(300px);
39 }
40 to {
41 transform: translateX(0);
42 }
43 }
44
45 @keyframes vertical {
46 from {
47 transform: translateY(0);
48 }
49 50% {
50 transform: translateY(300px);
51 }
52 to {
53 transform: translateY(0);
54 }
55 }
56 </style>
57 <script>
58
59 var animationDuration = 2;
60
61 function randomInt(min, max)
62 {
63 return Math.round(this.random(min, max));
64 }
65
66 function random(min, max)
67 {
68 return (Math.random() * (max - min)) + min;
69 }
70
71 function randomColor()
72 {
73 var min = 32;
74 var max = 256 - 32;
75 return "#"
76 + this.randomInt(min, max).toString(16)
77 + this.randomInt(min, max).toString(16)
78 + this.randomInt(min, max).toString(16);
79 }
80
81 function Point(x, y)
82 {
83 this.x = x;
84 this.y = y;
85 }
86
87 Point.pointOnCircle = function(angle, radius)
88 {
89 return new Point(radius * Math.cos(angle), radius * Math.sin(angle));
90 }
91
92 Point.prototype =
93 {
94 add: function(other)
95 {
96 if(isNaN(other.x))
97 return new Point(this.x + other, this.y + other);
98 return new Point(this.x + other.x, this.y + other.y);
99 },
100
101 subtract: function(other)
102 {
103 if(isNaN(other.x))
104 return new Point(this.x - other, this.y - other);
105 return new Point(this.x - other.x, this.y - other.y);
106 },
107
108 move: function(angle, velocity, timeDelta)
109 {
110 return this.add(Point.pointOnCircle(angle, velocity * (timeDelta / 1000)));
111 },
112
113 multiply: function(other)
114 {
115 if(isNaN(other.x))
116 return new Point(this.x * other, this.y * other);
117 return new Point(this.x * other.x, this.y * other.y);
118 },
119
120 length: function() {
121 return Math.sqrt( this.x * this.x + this.y * this.y );
122 },
123
124 normalize: function() {
125 var l = Math.sqrt( this.x * this.x + this.y * this.y );
126 this.x /= l;
127 this.y /= l;
128 return this;
129 }
130 }
131
132 function Particle(maxPosition)
133 {
134 this.horizontalContainer = document.createElement('div');
135 this.horizontalContainer.className = 'particle-h';
136
137 var delay = random(0, animationDuration);
138 this.horizontalContainer.style.animationDuration = random(animationDuration - slop, animationDuration + slop) + 's';
139 this.horizontalContainer.style.animationDelay = '-' + delay + 's';
140
141 this.element = document.createElement('div');
142 this.element.className = 'particle-v';
143 this.element.style.backgroundColor = randomColor();
144
145 this.horizontalContainer.appendChild(this.element);
146
147 var slop = 0.2;
148 this.element.style.animationDuration = random(animationDuration - slop, animationDuration + slop) + 's';
149 this.element.style.animationDelay = '-' + delay + 's';
150
151 this.maxPosition = maxPosition;
152 this.reset();
153 this.move();
154 }
155
156 Particle.prototype =
157 {
158 reset: function()
159 {
160 this.size = new Point(20, 20);
161 this.maxLocation = this.maxPosition.subtract(this.size);
162 this.position = new Point(0, 0);
163 },
164
165 move: function()
166 {
167 this.horizontalContainer.style.transform = "translateX(" + this.position.x + "px)";
168 this.element.style.transform = "translateY(" + this.position.y + "px) ";
169 }
170 }
171
172 var numParticles = 20;
173 var particles = [];
174
175 function makeParticles()
176 {
177 var stage = document.getElementById('stage');
178 var maxPosition = new Point(320, 320);
179 for (var i = 0; i < numParticles; ++i) {
180 particles.push(new Particle(maxPosition));
181 stage.appendChild(particles[i].horizontalContainer);
182 }
183 }
184
185 function setupAnimation()
186 {
187 makeParticles();
188 }
189
190 window.addEventListener('load', setupAnimation, false);
191 </script>
192</head>
193<body>
194
195<div id="stage">
196</div>
197
198</body>
199</html>