Skip to content

Instantly share code, notes, and snippets.

@IpsumLorem16
Created April 18, 2021 12:56
Show Gist options
  • Save IpsumLorem16/5cfe899f3e2a57ba894599589f7afbc2 to your computer and use it in GitHub Desktop.
Save IpsumLorem16/5cfe899f3e2a57ba894599589f7afbc2 to your computer and use it in GitHub Desktop.
Animated SVG heart button
<button data-liked="false">
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="42" viewBox="0 0 42 42" fill="none">
<g id="heart_lines" opacity="0">
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
<g class="line-wrapper">
<rect class="heart-line" x="19" y="0" width="3.30527" height="11.3992" rx="1.65264" fill="#C80000"/>
</g>
</g>
<path id="heart_button" d="M20.877 6.69703C20.046 6.04303 19.13 5.50502 18.15 5.09602C16.734 4.50602 15.215 4.20098 13.68 4.19898C12.146 4.19698 10.626 4.49799 9.20802 5.08399C7.79002 5.67099 6.50103 6.53101 5.41603 7.61701C4.33103 8.70201 3.47102 9.99101 2.88502 11.409C2.29802 12.827 1.99801 14.348 2.00001 15.882C2.00201 17.417 2.30701 18.936 2.89701 20.353C3.48601 21.769 4.35002 23.055 5.43702 24.137C5.43702 24.138 5.43803 24.138 5.43803 24.139L19.811 38.515L20.871 39.576L21.932 38.515L36.307 24.136L36.31 24.133C38.488 21.943 39.709 18.979 39.705 15.89C39.701 12.801 38.473 9.83898 36.289 7.65498C34.105 5.46998 31.144 4.24101 28.055 4.23701C25.442 4.23401 22.918 5.10803 20.877 6.69703Z" stroke="#B9B9B9" stroke-width="3"/>
</svg>
</button>
/*heart lines animation*/
function heartLines() {
let lineWraps, tl;
//loop though line wrappers and rotate evenly around 360deg
lineWraps = document.querySelectorAll(".line-wrapper");
for (i = 0; i < lineWraps.length; i++) {
let degrees = i * (360 / lineWraps.length);
gsap.set(lineWraps[i], {
rotation: degrees,
transformOrigin: "center bottom"
});
}
//create timeline
tl = gsap
.timeline()
.set("#heart_lines", {
opacity: 1,
transformOrigin: "center bottom",
y: 10,
scale: 1.2,
})
.to(".heart-line", {
transformOrigin: "bottom center",
duration: 1,
y: -25,
height: 3
})
.to("#heart_lines", {
opacity: 0,
duration: 0.3,
position: "-=0.3"
});
return tl;
}
/* heart shape animation */
function heartShape({on}) {
let tl = gsap
.timeline({
defaults: {
transformOrigin: "center center"
}
})
.to("#heart_button", {
duration: 0.2,
scale: 0.8
})
.to("#heart_button", {
duration: 0.2,
fill: on ? "red": "none",
stroke: on ? "red": "rgb(185, 185, 185)",
position: "-=0.15"
})
.to("#heart_button", {
duration: 1.2,
scale: 1,
ease: on ? "elastic.out(1.1, 0.2)" : "Power1.easeOut"
});
return tl;
}
let heartOn = gsap.timeline()
.add(heartShape({on:true}))
.add(heartLines(), "<0.4")
.timeScale(2)
.pause();
let heartOff = gsap.timeline()
.add(heartShape({on:false}))
.timeScale(3)
.pause();
const button = document.querySelector("button");
function toggleHeartBtn() {
if (button.getAttribute("data-liked") === "false") {
heartOff.pause();
heartOn.play(0);
gsap.set(".heart-line",{opacity:1});
button.setAttribute("data-liked", "true");
} else {
heartOn.pause();
gsap.set(".heart-line",{opacity:0});
heartOff.play(0);
button.setAttribute("data-liked", "false");
}
}
button.addEventListener("click", () => {
toggleHeartBtn();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.0.2/gsap.min.js"></script>
htlm,body {
padding:0;
margin:0;
height:100vh;
}
body {
display:flex;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
button {
outline:none;
padding:2px;
border: 0;
background:none;
display:inline-block;
cursor:pointer;
-webkit-user-select: none;
-webkit-tap-highlight-color: transparent;
}
svg {
display:block;
margin:0 auto;
max-height:100%;
max-width:100%;
overflow:visible;
pointer-events:none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment