Click the scene to reset the snow.
A Pen by Louis Hoebregts on CodePen.
Click the scene to reset the snow.
A Pen by Louis Hoebregts on CodePen.
<!-- Click the scene to reset the snow --> | |
<!-- Images from www.freepik.com --> | |
<div id="globe"> | |
<canvas id="town"></canvas> | |
<canvas id="snowFlakes"></canvas> | |
</div> |
var canvas = document.querySelector("#town"), | |
ctx = canvas.getContext('2d'), | |
data, canvas2, ctx2, rafAnim = null; | |
canvas.width = canvas.offsetWidth; | |
canvas.height = canvas.offsetWidth, | |
amount = 1000; | |
var img = new Image(); | |
img.onload = function() { | |
ctx.drawImage(img, 0, 0, 800, 800, 0, 0, canvas.width, canvas.height); | |
data = ctx.getImageData(0, 0, canvas.width, canvas.height).data; | |
canvas2 = document.querySelector("#snowFlakes"); | |
ctx2 = canvas2.getContext('2d'); | |
canvas2.width = canvas.offsetWidth; | |
canvas2.height = canvas.offsetWidth; | |
initSnow(); | |
} | |
img.crossOrigin = "Anonymous"; | |
img.src = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/town.svg"; | |
var flakes; | |
function initSnow() { | |
window.addEventListener("click", shakeGlobe); | |
window.addEventListener("touchstart", shakeGlobe); | |
ctx2.fillStyle = "rgba(255,255,255,0.7)"; | |
var radius = canvas.width * 0.2875; | |
var offsetX = canvas.width / 2; | |
var offsetY = canvas.width * 0.4; | |
flakes = []; | |
for (var i = 0; i < amount; i++) { | |
x = Math.random() * 2 * radius - radius; | |
ylim = Math.sqrt(radius * radius - x * x); | |
y = Math.random() * ylim - ylim; | |
flakes.push(new Flake(x + offsetX, y + offsetY)); | |
} | |
if (rafAnim === null) { | |
rafAnim = requestAnimationFrame(render); | |
} | |
} | |
function Flake(x, y, color) { | |
this.x = Math.floor(x); | |
this.y = Math.floor(y); | |
for (var i = this.y; i < canvas.width; i++) { | |
if (data[((this.x + (canvas.width * i)) * 4 + 3)] > 10) { | |
destination = parseInt(i - 1); | |
i = canvas.width; | |
} else { | |
destination = canvas.width; | |
} | |
} | |
this.finalY = destination; | |
this.r = Math.random() * 2; | |
this.speedY = Math.random() + 0.2; | |
} | |
Flake.prototype.render = function() { | |
if (this.finalY > this.y) { | |
this.y += this.speedY; | |
} | |
ctx2.beginPath(); | |
ctx2.arc(this.x, this.y, this.r, Math.PI * 2, false); | |
ctx2.fill(); | |
} | |
function render(a) { | |
requestAnimationFrame(render); | |
ctx2.clearRect(0, 0, canvas2.width, canvas2.height); | |
for (var i = 0; i < amount; i++) { | |
flakes[i].render(); | |
} | |
}; | |
function shakeGlobe() { | |
window.removeEventListener("click", shakeGlobe); | |
window.removeEventListener("touchstart", shakeGlobe); | |
var globe = document.querySelector("#globe"); | |
TweenMax.to(canvas2, 0.5, { | |
opacity: 0 | |
}); | |
TweenMax.to(globe, .1, { | |
rotationZ: 25, | |
ease: Quad.easeInOut, | |
yoyo: true, | |
repeat: 5, | |
onComplete: initSnow | |
}) | |
TweenMax.to(canvas2, 0.5, { | |
opacity: 1, | |
delay: "0.6" | |
}); | |
} |
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script> |
body { | |
margin: 0; | |
background: #73b4ab; | |
height: 100vh; | |
width: 100vw; | |
overflow: hidden; | |
cursor: pointer; | |
} | |
#globe { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
width: 80vmin; | |
height: 80vmin; | |
transform-origin: 50% 60%; | |
} | |
#globe:before { | |
content: ""; | |
display: block; | |
position: absolute; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
right: 0; | |
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/127738/globe.svg) center center / contain no-repeat; | |
z-index: 10; | |
} | |
canvas { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
} |