Newton's Cradle

HTML
<div class="container"> <div class="holder"> <div class="holderBars"></div> <div class="cradles"> <div class="cradle cradle-first"> <div class="line"></div> <div class="circle"> <svg viewBox="0 0 10 15" class="svg-3"> <!--<path d="M8,1 Q2,2 1,8"/>--> <path d="M4,3 Q1,5 1,10"/> </svg> </div> </div> <div class="cradle cradle-middle"> <div class="line"></div> <div class="circle"> <svg viewBox="0 0 10 15" class="svg-3"> <!--<path d="M8,1 Q2,2 1,8"/>--> <path d="M4,3 Q1,5 1,10"/> </svg> </div> </div> <div class="cradle cradle-middle"> <div class="line"></div> <div class="circle"> <svg viewBox="0 0 10 15" class="svg-3"> <!--<path d="M8,1 Q2,2 1,8"/>--> <path d="M4,3 Q1,5 1,10"/> </svg> </div> </div> <div class="cradle cradle-middle"> <div class="line"></div> <div class="circle"> <svg viewBox="0 0 10 15" class="svg-3"> <!--<path d="M8,1 Q2,2 1,8"/>--> <path d="M4,3 Q1,5 1,10"/> </svg> </div> </div> <div class="cradle cradle-last"> <div class="line"></div> <div class="circle"> <svg viewBox="0 0 10 15" class="svg-3"> <!--<path d="M8,1 Q2,2 1,8"/>--> <path d="M4,3 Q1,5 1,10"/> </svg> </div> </div> </div> <div class="holder__bottomBar pos-left"></div> <div class="holder__bottomBar pos-right"></div> </div> </div>
SCSS
$bgColor: #ec7158; $borderColor: #F6CC8A; $lineColor: #3E3E5C; $circleColor: #74b89c; * { margin: 0; padding: 0; } html { font-size: 62.5%; //DEFAULT FONT SIZE IS 16PX SO WE WILL MAKE IT 10 => (10/16 * 100) SO WE CAN EASILY USE REM WITHOUT CALCULATION } body { overflow: hidden; } .container { height: 100vh; width: 100vw; display: flex; justify-content: center; align-items: center; background-color: $bgColor; } .holder { position: relative; height: 38rem; border-radius: .5rem; &__bottomBar { position: absolute; bottom: 0; height: 1rem; width: 15%; background-color: $borderColor; border-radius: .5rem; } } .holderBars { position: absolute; left: 0; right: 0; top: -.5rem; bottom: 0; border: 1rem solid $borderColor; border-bottom: none; border-radius: .5rem; z-index: 1; } .pos-left { left: 0rem; } .pos-right { right: 0rem; } .cradles { display: flex; justify-content: space-between; height: 100%; padding: 0 4.5rem; } .cradle { display: flex; flex-direction: column; align-items: center; height: 80%; transform-origin: top center; } .line { flex: 1; width: .6rem; background-color: $lineColor; } .circle { position: relative; width: 8rem; height: 8rem; border-radius: 50%; background-color: $circleColor; border: .6rem solid $lineColor; } svg { position: absolute; width: 4rem; left: .4rem; top: .4rem; path { fill: none; stroke: rgba(#fff, .9); stroke-width: .15rem; stroke-linecap: round; stroke-linejoin: round; transition: 0.2s; } }
ES6
//Inspired by https://dribbble.com/shots/3405520-001-Newton-s-Cradle TweenMax.fromTo('.fire', .03, {x: -.5, y: -.4}, {x: .5, y: .4, repeat: -1, yoyo: true}) var tl = new TimelineMax({repeat: -1}); tl .fromTo('.cradle-last', .5, {transform: 'rotate(-45deg)'}, {transform: 'rotate(0)', ease: Power1.easeIn}) .to('.cradle-last', .2, {transform: 'rotate(2deg)'}) .to('.cradle-middle', .2, {rotation: '2deg'}, '-=.2') .to('.cradle-middle', .2, {rotation: 0}) .to('.cradle-last', .2, {transform: 'rotate(0)'}, '-=.2') .to('.cradle-first', .5, {rotation: '45deg', ease: Power1.easeOut}, '-=.4') .to('.cradle-first', .5, {rotation: '0', ease: Power1.easeIn}) .to('.cradle-first', .2, {rotation: '-2deg'}) .to('.cradle-middle', .2, {rotation: '-2deg'}, '-=.2') .to('.cradle-middle', .2, {rotation: 0}) .to('.cradle-first', .2, {rotation: '0'}, '-=.2') .to('.cradle-last', .5, {transform: 'rotate(-45deg)'}, '-=.4') tl.timeScale(2.5); //SLOW MOTION document.querySelector('.holder').addEventListener('mouseenter', () => tl.timeScale(.2)) document.querySelector('.holder').addEventListener('mouseleave', () => tl.timeScale(2.5)) //SCALE DEPENDS ON WINDOW SIZE function scaleCradle() { const holderWidth = 850, windowWidth = window.innerWidth, scale = windowWidth / holderWidth > 1 ? 1 : windowWidth / holderWidth; document.querySelector('.holder').style.transform = `scale(${scale})`; } scaleCradle() window.addEventListener('resize', scaleCradle);
Expand for more options Login