The medium clap effect 👏 recreated with code. Yeah!
A Pen by Ohans Emmanuel on CodePen.
| <button id="clap" class="clap"> | |
| <span> | |
| <!-- SVG Created by Luis Durazo from the Noun Project --> | |
| <svg id="clap--icon" xmlns="http://www.w3.org/2000/svg" viewBox="-549 338 100.1 125"> | |
| <path d="M-471.2 366.8c1.2 1.1 1.9 2.6 2.3 4.1.4-.3.8-.5 1.2-.7 1-1.9.7-4.3-1-5.9-2-1.9-5.2-1.9-7.2.1l-.2.2c1.8.1 3.6.9 4.9 2.2zm-28.8 14c.4.9.7 1.9.8 3.1l16.5-16.9c.6-.6 1.4-1.1 2.1-1.5 1-1.9.7-4.4-.9-6-2-1.9-5.2-1.9-7.2.1l-15.5 15.9c2.3 2.2 3.1 3 4.2 5.3zm-38.9 39.7c-.1-8.9 3.2-17.2 9.4-23.6l18.6-19c.7-2 .5-4.1-.1-5.3-.8-1.8-1.3-2.3-3.6-4.5l-20.9 21.4c-10.6 10.8-11.2 27.6-2.3 39.3-.6-2.6-1-5.4-1.1-8.3z"/> | |
| <path d="M-527.2 399.1l20.9-21.4c2.2 2.2 2.7 2.6 3.5 4.5.8 1.8 1 5.4-1.6 8l-11.8 12.2c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l34-35c1.9-2 5.2-2.1 7.2-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l28.5-29.3c2-2 5.2-2 7.1-.1 2 1.9 2 5.1.1 7.1l-28.5 29.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.4 1.7 0l24.7-25.3c1.9-2 5.1-2.1 7.1-.1 2 1.9 2 5.2.1 7.2l-24.7 25.3c-.5.5-.4 1.2 0 1.7.5.5 1.2.5 1.7 0l14.6-15c2-2 5.2-2 7.2-.1 2 2 2.1 5.2.1 7.2l-27.6 28.4c-11.6 11.9-30.6 12.2-42.5.6-12-11.7-12.2-30.8-.6-42.7m18.1-48.4l-.7 4.9-2.2-4.4m7.6.9l-3.7 3.4 1.2-4.8m5.5 4.7l-4.8 1.6 3.1-3.9"/> | |
| </svg> | |
| </span> | |
| <span id="clap--count" class="clap--count"></span> | |
| <span id="clap--count-total" class="clap--count-total"></span> | |
| </button> | |
| <aside id="message">In case you didn't know, you gotta click the clap button above 😎😜😜 | |
| <br /> | |
| 👉🏻 Press down the button for some more fun! | |
| <br /> | |
| <a href="https://twitter.com/OhansEmmanuel" target="_blank">via @ohansemmanuel</a> | |
| <br/> | |
| <a href="https://codepen.io/ohansemmanuel/full/zEJpYy/" | |
| target="_blank"> | |
| See ReactJS implementation | |
| </a> | |
| </aside> |
The medium clap effect 👏 recreated with code. Yeah!
A Pen by Ohans Emmanuel on CodePen.
| const clap = document.getElementById('clap') | |
| const clapIcon = document.getElementById('clap--icon') | |
| const clapCount = document.getElementById('clap--count') | |
| const clapTotalCount = document.getElementById('clap--count-total') | |
| const initialNumberOfClaps = generateRandomNumber(500, 10000); | |
| const btnDimension = 80 | |
| const tlDuration = 300 | |
| let numberOfClaps = 0 | |
| let clapHold; | |
| const triangleBurst = new mojs.Burst({ | |
| parent: clap, | |
| radius: {50:95}, | |
| count: 5, | |
| angle: 30, | |
| children: { | |
| shape: 'polygon', | |
| radius: {6: 0}, | |
| scale: 1, | |
| stroke: 'rgba(211,84,0 ,0.5)', | |
| strokeWidth: 2, | |
| angle: 210, | |
| delay: 30, | |
| speed: 0.2, | |
| easing: mojs.easing.bezier(0.1, 1, 0.3 ,1), | |
| duration: tlDuration | |
| } | |
| }) | |
| const circleBurst = new mojs.Burst({ | |
| parent: clap, | |
| radius: {50:75}, | |
| angle: 25, | |
| duration: tlDuration, | |
| children: { | |
| shape: 'circle', | |
| fill: 'rgba(149,165,166 ,0.5)', | |
| delay: 30, | |
| speed: 0.2, | |
| radius: {3: 0}, | |
| easing: mojs.easing.bezier(0.1, 1, 0.3, 1), | |
| } | |
| }) | |
| const countAnimation = new mojs.Html({ | |
| el: '#clap--count', | |
| isShowStart: false, | |
| isShowEnd: true, | |
| y: {0: -30}, | |
| opacity: {0:1}, | |
| duration: tlDuration | |
| }).then({ | |
| opacity: {1:0}, | |
| y: -80, | |
| delay: tlDuration/2 | |
| }) | |
| const countTotalAnimation = new mojs.Html({ | |
| el: '#clap--count-total', | |
| isShowStart: false, | |
| isShowEnd: true, | |
| opacity: {0:1}, | |
| delay: 3*(tlDuration)/2, | |
| duration: tlDuration, | |
| y: {0: -3} | |
| }) | |
| const scaleButton = new mojs.Html({ | |
| el: '#clap', | |
| duration: tlDuration, | |
| scale: {1.3: 1}, | |
| easing: mojs.easing.out | |
| }) | |
| clap.style.transform = "scale(1, 1)" /*Bug1 fix*/ | |
| const animationTimeline = new mojs.Timeline() | |
| animationTimeline.add([ | |
| triangleBurst, | |
| circleBurst, | |
| countAnimation, | |
| countTotalAnimation, | |
| scaleButton | |
| ]) | |
| clap.addEventListener('click', function() { | |
| repeatClapping(); | |
| }) | |
| clap.addEventListener('mousedown', function() { | |
| clapHold = setInterval(function() { | |
| repeatClapping(); | |
| }, 400) | |
| }) | |
| clap.addEventListener('mouseup', function() { | |
| clearInterval(clapHold); | |
| }) | |
| function repeatClapping() { | |
| updateNumberOfClaps() | |
| animationTimeline.replay() | |
| clapIcon.classList.add('checked') | |
| } | |
| function updateNumberOfClaps() { | |
| numberOfClaps < 50 ? numberOfClaps++ : null | |
| clapCount.innerHTML = "+" + numberOfClaps | |
| clapTotalCount.innerHTML = initialNumberOfClaps + numberOfClaps | |
| } | |
| function generateRandomNumber(min, max) { | |
| return Math.floor(Math.random()*(max-min+1)+min); | |
| } | |
| /*====== TODO ========== | |
| 1. Bug fix. The button shouldn't | |
| scale up before being clicked (fixed) | |
| 2. Shadow should NOT fire hover | |
| animation in succession. | |
| Some sort of delay is delay. (Not that important) | |
| 3. Hover animation should be | |
| absent upon click (Not that important) | |
| 4. Handle onpress event on the button (Implemetaation is Buggy ATM) | |
| 5. Dynamically change burst angle | |
| everytime button is clicked | |
| =========================*/ |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/mo-js/0.288.1/mo.min.js"></script> |
| /*======================== | |
| SASS definitions | |
| =======================*/ | |
| $btn-dimension: 80px; | |
| $primary-color: rgba(189,195,199 ,1); | |
| $secondary-color: rgba(39,174,96 ,1); | |
| @mixin debug { | |
| outline: 1px solid red; | |
| } | |
| /*======================== | |
| FLEXBOX ALIGNMENT | |
| =======================*/ | |
| body { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| min-height: 100vh; | |
| } | |
| /*======================== | |
| BASIC styles | |
| =======================*/ | |
| * { | |
| box-sizing: border-box | |
| } | |
| /*======================== | |
| BUTTON styles | |
| =======================*/ | |
| .clap { | |
| position: relative; | |
| outline: 1px solid transparent; | |
| border-radius: 50%; | |
| border: 1px solid $primary-color; | |
| width: $btn-dimension; | |
| height: $btn-dimension; | |
| background: none; | |
| &:after { | |
| content: ""; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| display: block; | |
| border-radius: 50%; | |
| //border: 1px solid $primary-color; | |
| width: $btn-dimension - 1px; | |
| height: $btn-dimension - 1px; | |
| } | |
| &:hover { | |
| cursor: pointer; | |
| border: 1px solid $secondary-color; | |
| transition: border-color 0.3s ease-in; | |
| &:after { | |
| animation: shockwave 1s ease-in infinite; | |
| } | |
| } | |
| svg { | |
| width: 40px; | |
| fill: none; | |
| stroke: $secondary-color; | |
| stroke-width: 2px; | |
| &.checked { | |
| fill: $secondary-color; | |
| stroke: #fff; | |
| stroke-width: 1px; | |
| } | |
| } | |
| .clap--count { | |
| position: absolute; | |
| top: -$btn-dimension/1.6; | |
| left: $btn-dimension/4; | |
| font-size: 0.8rem; | |
| color: white; | |
| background: $secondary-color; | |
| border-radius: 50%; | |
| height: $btn-dimension/2; | |
| width: $btn-dimension/2; | |
| line-height: $btn-dimension/2; | |
| } | |
| .clap--count-total { | |
| position: absolute; | |
| font-size: 0.8rem; | |
| width: $btn-dimension; | |
| text-align: center; | |
| left: 0; | |
| top: -$btn-dimension/3.5; | |
| color: $primary-color; | |
| } | |
| } | |
| /*==================== | |
| Message | |
| ======================*/ | |
| #message { | |
| position: absolute; | |
| bottom: 20px; | |
| color: $secondary-color; | |
| line-height: 1.52rem; | |
| padding: 1rem; | |
| font-size: 0.9rem; | |
| a { | |
| color: $primary-color | |
| } | |
| } | |
| @keyframes shockwave { | |
| 0% { | |
| transform: scale(1); | |
| box-shadow: 0 0 2px $secondary-color; | |
| opacity: 1; | |
| } | |
| 100% { | |
| transform: scale(1); | |
| opacity: 0; | |
| box-shadow: 0 0 50px darken($secondary-color, 20%), inset 0 0 10px $secondary-color; | |
| } | |
| } |