1"use strict"; 2window.onload = function() { 3 setTimeout(start, 200); 4}; 5 6function start() { 7 8 //Helpers 9 function lineToAngle(x1, y1, length, radians) { 10 var x2 = x1 + length * Math.cos(radians), 11 y2 = y1 + length * Math.sin(radians); 12 return { x: x2, y: y2 }; 13 } 14 15 function randomRange(min, max) { 16 return min + Math.random() * (max - min); 17 } 18 19 function degreesToRads(degrees) { 20 return degrees / 180 * Math.PI; 21 } 22 23 //Particle 24 var particle = { 25 x: 0, 26 y: 0, 27 vx: 0, 28 vy: 0, 29 radius: 0, 30 31 create: function(x, y, speed, direction) { 32 var obj = Object.create(this); 33 obj.x = x; 34 obj.y = y; 35 obj.vx = Math.cos(direction) * speed; 36 obj.vy = Math.sin(direction) * speed; 37 return obj; 38 }, 39 40 getSpeed: function() { 41 return Math.sqrt(this.vx * this.vx + this.vy * this.vy); 42 }, 43 44 setSpeed: function(speed) { 45 var heading = this.getHeading(); 46 this.vx = Math.cos(heading) * speed; 47 this.vy = Math.sin(heading) * speed; 48 }, 49 50 getHeading: function() { 51 return Math.atan2(this.vy, this.vx); 52 }, 53 54 setHeading: function(heading) { 55 var speed = this.getSpeed(); 56 this.vx = Math.cos(heading) * speed; 57 this.vy = Math.sin(heading) * speed; 58 }, 59 60 update: function() { 61 this.x += this.vx; 62 this.y += this.vy; 63 } 64 }; 65 66 //Canvas and settings 67 var canvas = document.getElementById("canvas"), 68 context = canvas.getContext("2d"), 69 width = canvas.width = window.innerWidth, 70 height = canvas.height = window.innerHeight, 71 stars = [], 72 shootingStars = [], 73 layers = [ 74 { speed: 0.015, scale: 0.2, count: 320 }, 75 { speed: 0.03, scale: 0.5, count: 50 }, 76 { speed: 0.05, scale: 0.75, count: 30 } 77 ], 78 starsAngle = 145, 79 shootingStarSpeed = { 80 min: 15, 81 max: 20 82 }, 83 shootingStarOpacityDelta = 0.01, 84 trailLengthDelta = 0.01, 85 shootingStarEmittingInterval = 2000, 86 shootingStarLifeTime = 500, 87 maxTrailLength = 300, 88 starBaseRadius = 2, 89 shootingStarRadius = 3, 90 paused = false; 91 92 //Create all stars 93 for (var j = 0; j < layers.length; j += 1) { 94 var layer = layers[j]; 95 for (var i = 0; i < layer.count; i += 1) { 96 var star = particle.create(randomRange(0, width), randomRange(0, height), 0, 0); 97 star.radius = starBaseRadius * layer.scale; 98 star.setSpeed(layer.speed); 99 star.setHeading(degreesToRads(starsAngle)); 100 stars.push(star); 101 } 102 } 103 104 function createShootingStar() { 105 var shootingStar = particle.create(randomRange(width / 2, width), randomRange(0, height / 2), 0, 0); 106 shootingStar.setSpeed(randomRange(shootingStarSpeed.min, shootingStarSpeed.max)); 107 shootingStar.setHeading(degreesToRads(starsAngle)); 108 shootingStar.radius = shootingStarRadius; 109 shootingStar.opacity = 0; 110 shootingStar.trailLengthDelta = 0; 111 shootingStar.isSpawning = true; 112 shootingStar.isDying = false; 113 shootingStars.push(shootingStar); 114 } 115 116 function killShootingStar(shootingStar) { 117 setTimeout(function() { 118 shootingStar.isDying = true; 119 }, shootingStarLifeTime); 120 } 121 122 function update() { 123 if (!paused) { 124 context.clearRect(0, 0, width, height); 125 context.fillStyle = "rgba(255, 255, 255, 0)"; 126 context.fillRect(0, 0, width, height); 127 context.fill(); 128 129 for (var i = 0; i < stars.length; i += 1) { 130 var star = stars[i]; 131 star.update(); 132 drawStar(star); 133 if (star.x > width) { 134 star.x = 0; 135 } 136 if (star.x < 0) { 137 star.x = width; 138 } 139 if (star.y > height) { 140 star.y = 0; 141 } 142 if (star.y < 0) { 143 star.y = height; 144 } 145 } 146 147 for (i = 0; i < shootingStars.length; i += 1) { 148 var shootingStar = shootingStars[i]; 149 if (shootingStar.isSpawning) { 150 shootingStar.opacity += shootingStarOpacityDelta; 151 if (shootingStar.opacity >= 1.0) { 152 shootingStar.isSpawning = false; 153 killShootingStar(shootingStar); 154 } 155 } 156 if (shootingStar.isDying) { 157 shootingStar.opacity -= shootingStarOpacityDelta; 158 if (shootingStar.opacity <= 0.0) { 159 shootingStar.isDying = false; 160 shootingStar.isDead = true; 161 } 162 } 163 shootingStar.trailLengthDelta += trailLengthDelta; 164
165 shootingStar.update(); 166 if (shootingStar.opacity > 0.0) { 167 drawShootingStar(shootingStar); 168 } 169 } 170 171 //Delete dead shooting shootingStars 172 for (i = shootingStars.length -1; i >= 0 ; i--){ 173 if (shootingStars[i].isDead){ 174 shootingStars.splice(i, 1); 175 } 176 } 177 } 178 requestAnimationFrame(update); 179 } 180 181 function drawStar(star) { 182 context.fillStyle = "rgb(255, 221, 157)"; 183 context.beginPath(); 184 context.arc(star.x, star.y, star.radius, 0, Math.PI * 2, false); 185 context.fill(); 186 } 187 188 function drawShootingStar(p) { 189 var x = p.x, 190 y = p.y, 191 currentTrailLength = (maxTrailLength * p.trailLengthDelta), 192 pos = lineToAngle(x, y, -currentTrailLength, p.getHeading()); 193 194 context.fillStyle = "rgba(255, 255, 255, " + p.opacity + ")"; 195 // context.beginPath(); 196 // context.arc(x, y, p.radius, 0, Math.PI * 2, false); 197 // context.fill(); 198 var starLength = 5; 199 context.beginPath(); 200 context.moveTo(x - 1, y + 1); 201 202 context.lineTo(x, y + starLength); 203 context.lineTo(x + 1, y + 1); 204 205 context.lineTo(x + starLength, y); 206 context.lineTo(x + 1, y - 1); 207 208 context.lineTo(x, y + 1); 209 context.lineTo(x, y - starLength); 210 211 context.lineTo(x - 1, y - 1); 212 context.lineTo(x - starLength, y); 213 214 context.lineTo(x - 1, y + 1); 215 context.lineTo(x - starLength, y); 216 217 context.closePath(); 218 context.fill(); 219 220 //trail 221 context.fillStyle = "rgba(255, 221, 157, " + p.opacity + ")"; 222 context.beginPath(); 223 context.moveTo(x - 1, y - 1); 224 context.lineTo(pos.x, pos.y); 225 context.lineTo(x + 1, y + 1); 226 context.closePath(); 227 context.fill(); 228 } 229 230 //Run 231 update(); 232 233 //Shooting stars 234 setInterval(function() { 235 if (paused) return; 236 createShootingStar(); 237 }, shootingStarEmittingInterval); 238 239 window.onfocus = function () { 240 paused = false; 241 }; 242 243 window.onblur = function () { 244 paused = true; 245 }; 246 247} 248 249 250/* ì¶ì² : https://codepen.io/frexuz/pen/BvHsk */
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.