-
-
Save JonathanDn/09c3e0f037c4c52efcf56ee0878d5e4c to your computer and use it in GitHub Desktop.
<div class="canvas"> | |
<div id="totalCounter" class="total-counter"></div> | |
<div id="clap" class="clap-container"> | |
<i class="clap-icon fa fa-hand-paper-o"></i> | |
</div> | |
<div id="clicker" class="click-counter"> | |
<span class="counter"></span> | |
</div> | |
<div id="sonar-clap" class="clap-container-sonar"></div> | |
<div id="particles" class="particles-container"> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
</div> | |
<div id="particles-2" class="particles-container"> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
</div> | |
<div id="particles-3" class="particles-container"> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
<div class="triangle"> | |
<div class="square"></div> | |
</div> | |
</div> | |
</div> |
let accCounter = 0; | |
let totalCount = 127; | |
const minDeg = 1; | |
const maxDeg = 72; | |
const particlesClasses = [ | |
{ | |
class: "pop-top" | |
}, | |
{ | |
class: "pop-top-left" | |
}, | |
{ | |
class: "pop-top-right" | |
}, | |
{ | |
class: "pop-bottom-right" | |
}, | |
{ | |
class: "pop-bottom-left" | |
}, | |
]; | |
document.getElementById('totalCounter').innerText = totalCount; | |
document.getElementById('clap').onmouseover = function() { | |
let sonarClap = document.getElementById('sonar-clap'); | |
sonarClap.classList.add('hover-active'); | |
setTimeout(() => { | |
sonarClap.classList.remove('hover-active'); | |
}, 2000); | |
} | |
document.getElementById('clap').onclick = function() { | |
const clap = document.getElementById('clap'); | |
const clickCounter = document.getElementById("clicker"); | |
const particles = document.getElementById('particles'); | |
const particles2 = document.getElementById('particles-2'); | |
const particles3 = document.getElementById('particles-3'); | |
clap.classList.add('clicked'); | |
upClickCounter(); | |
runAnimationCycle(clap, 'scale'); | |
if (!particles.classList.contains('animating')) { | |
animateParticles(particles, 700); | |
} else if(!particles2.classList.contains('animating')){ | |
animateParticles(particles2, 700); | |
} else if(!particles3.classList.contains('animating')) { | |
animateParticles(particles3, 700); | |
} | |
} | |
function upClickCounter() { | |
const clickCounter = document.getElementById("clicker"); | |
const totalClickCounter = document.getElementById('totalCounter'); | |
accCounter ++; | |
clickCounter.children[0].innerText = '+' + accCounter; | |
totalClickCounter.innerText = totalCount + accCounter; | |
if (clickCounter.classList.contains('first-active')) { | |
runAnimationCycle(clickCounter, 'active'); | |
} else { | |
runAnimationCycle(clickCounter, 'first-active'); | |
} | |
runAnimationCycle(totalClickCounter, 'fader'); | |
} | |
function runAnimationCycle(el, className, duration) { | |
if (el && !el.classList.contains(className)) { | |
el.classList.add(className); | |
} else { | |
el.classList.remove(className); | |
void el.offsetWidth; // Trigger a reflow in between removing and adding the class name | |
el.classList.add(className); | |
} | |
} | |
function runParticleAnimationCycle(el, className, duration) { | |
if (el && !el.classList.contains(className)) { | |
el.classList.add(className); | |
setTimeout(() => { | |
el.classList.remove(className); | |
}, duration); | |
} | |
} | |
function animateParticles(particles, dur) { | |
addRandomParticlesRotation(particles.id, minDeg, maxDeg); | |
for(let i = 0; i < particlesClasses.length; i++) { | |
runParticleAnimationCycle(particles.children[i], particlesClasses[i].class, dur); | |
} | |
// Boolean functionality only to activate particles2, particles3 when needed | |
particles.classList.add('animating'); | |
setTimeout(() => { | |
particles.classList.remove('animating'); | |
}, dur); | |
} | |
function getRandomInt(min, max) { | |
return Math.floor(Math.random() * (max - min + 1)) + min; | |
} | |
function addRandomParticlesRotation(particlesName, minDeg, maxDeg) { | |
const particles = document.getElementById(particlesName); | |
const randomRotationAngle = getRandomInt(minDeg, maxDeg) + 'deg'; | |
particles.style.transform = `rotate(${randomRotationAngle})`; | |
} |
$default-clap-color: #03a87c; | |
.canvas { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 300px; | |
height: 300px; | |
position: relative; | |
.total-counter { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 100%; | |
position: absolute; | |
margin-top: -45px; | |
color: gray; | |
font-family: sans-serif; | |
font-size: 16px; | |
} | |
.total-counter.fader { | |
animation: fade-in 1400ms forwards; | |
} | |
.clap-container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
position: absolute; | |
width: 60px; | |
height: 60px; | |
border: 1px solid rgba(0,0,0,.15); | |
border-radius: 50%; | |
z-index: 2; | |
background: #fff; | |
cursor: pointer; | |
.clap-icon { | |
font-size: 30px; | |
color: $default-clap-color; | |
width: 30px; | |
height: 30px; | |
} | |
} | |
.clap-container:hover { | |
border: 1px solid $default-clap-color; | |
} | |
.clap-container.scale { | |
animation: scaleAndBack 700ms forwards; | |
} | |
.click-counter { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 35px; | |
height: 35px; | |
position: absolute; | |
top: 132px; | |
background-color: $default-clap-color; | |
border-radius: 50%; | |
z-index: 1; | |
.counter { | |
font-family: sans-serif; | |
font-size: 14px; | |
color: #fff; | |
} | |
} | |
.click-counter.first-active { | |
animation: first-bump-in 1s forwards; | |
} | |
.click-counter.active { | |
animation: bump-in 1s forwards; | |
} | |
.clap-container-sonar { | |
width: 60px; | |
height: 60px; | |
background: $default-clap-color; | |
border-radius: 50%; | |
position: absolute; | |
opacity: 0; | |
z-index: 0; | |
} | |
.hover-active { | |
animation: sonar-wave 2s forwards; | |
} | |
.particles-container { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 60px; | |
height: 60px; | |
position: absolute; | |
/* border: 1px solid gray; */ | |
/* z-index: 3; */ | |
.triangle { | |
border-left: 4px solid transparent; | |
border-right: 4px solid transparent; | |
border-top: 10px solid red; | |
border-bottom: 4px solid transparent; | |
position: absolute; | |
.square { | |
width: 5px; | |
height: 5px; | |
background: $default-clap-color; | |
position: absolute; | |
left: -15px; | |
top: 0; | |
} | |
} | |
.pop-top { | |
animation: pop-top 1s forwards; | |
} | |
.pop-top-left { | |
animation: pop-top-left 1s forwards; | |
} | |
.pop-top-right { | |
animation: pop-top-right 1s forwards; | |
} | |
.pop-bottom-right { | |
animation: pop-bottom-right 1s forwards; | |
} | |
.pop-bottom-left { | |
animation: pop-bottom-left 1s forwards; | |
} | |
} | |
} | |
// * * * Animations * * * // | |
@keyframes sonar-wave { | |
0% { | |
opacity: 0.7; | |
} | |
100% { | |
transform: scale(1.4); | |
opacity: 0; | |
} | |
} | |
@keyframes fade-in { | |
0% { | |
opacity: 0; | |
} | |
50% { | |
opacity: 0; | |
} | |
100% { | |
opacity: 1; | |
} | |
} | |
// * * * Pop Animations * * * // | |
@keyframes pop-top { | |
0% { | |
transform: translate(0, 0) rotate(0); | |
opacity: 0.4; | |
} | |
100% { | |
transform: translate(0, -100px) rotate(0); | |
opacity: 0; | |
} | |
} | |
@keyframes pop-top-left { | |
0% { | |
transform: translate(0, 0) rotate(-55deg); | |
opacity: 0.4; | |
} | |
100% { | |
transform: translate(-100px, -50px) rotate(-55deg); | |
opacity: 0; | |
} | |
} | |
@keyframes pop-top-right { | |
0% { | |
transform: translate(0, 0) rotate(55deg); | |
opacity: 0.4; | |
} | |
100% { | |
transform: translate(100px, -50px) rotate(55deg); | |
opacity: 0; | |
} | |
} | |
@keyframes pop-bottom-right { | |
0% { | |
transform: translate(0, 0) rotate(135deg); | |
opacity: 0.4; | |
} | |
100% { | |
transform: translate(70px, 80px) rotate(135deg); | |
opacity: 0; | |
} | |
} | |
@keyframes pop-bottom-left { | |
0% { | |
transform: translate(0, 0) rotate(-135deg); | |
opacity: 0.4; | |
} | |
100% { | |
transform: translate(-70px, 80px) rotate(-135deg); | |
opacity: 0; | |
} | |
} | |
@keyframes first-bump-in { | |
0% { | |
transform: translateY(-65px); | |
opacity: 1; | |
} | |
50% { | |
transform: translateY(-80px); | |
opacity: 1; | |
} | |
100% { | |
transform: translateY(-100px); | |
opacity: 0; | |
} | |
} | |
@keyframes bump-in { | |
0% { | |
transform: translateY(-80px) scale(0.9); | |
opacity: 1; | |
} | |
50% { | |
transform: translateY(-80px) scale(1); | |
opacity: 1; | |
} | |
100% { | |
transform: translateY(-100px) scale(1); | |
opacity: 0; | |
} | |
} | |
@keyframes scaleAndBack { | |
0% { | |
transform: scale(1); | |
} | |
50% { | |
transform: scale(1.15); | |
} | |
100% { | |
transform: scale(1); | |
} | |
} |
I'm checking this out https://stackoverflow.com/questions/9851878/is-there-a-download-function-in-jsfiddle
..Ok that was it.. just add /show to the js fiddle URL and then just save the page :-)
(not that clean though but it works)
I'm checking this out https://stackoverflow.com/questions/9851878/is-there-a-download-function-in-jsfiddle
..Ok that was it.. just add /show to the js fiddle URL and then just save the page :-)
(not that clean though but it works)
Awesome, I actually didn't know that ! I thought of uploading it all to codesandbox.io which shows the index.html
boilerplate with all the script and style tags. But I guess that helps resolved your issue as well?
- Would you suggest adding a codesandbox example would be more inviting for new devs?
@topshef By the way I would love to see what you are doing with it if you would mind sharing with me :) You can also DM me that to my twitter profile: https://twitter.com/jodoron
@JonathanDn thanks a lot, yes I'll share it back on github and DM you :-)
@JonathanDn thanks a lot, yes I'll share it back on github and DM you :-)
Awesome!
@JonathanDn
Online, vanilla JS
Thanks