Hi there π
In this post, I'll show you how i created a draw effect for my blog logo.
Here what you will get ( you can do it basically with any svg, is really simple)
How it works
Basically we are writing our SVG using motiov.svg
element.
_30import { motion } from "framer-motion";
_30function MotionLogo(){
_30 const [progress, setProgress] = useState(0);
_30 viewBox="0 0 331.25 326.77"
_30 xmlns="http://www.w3.org/2000/svg"
_30 fill={"currentColor"}
_30 stroke={"currentColor"}
_30 fillOpacity: progress,
_30 transition={{ ease: "easeInOut" }}
_30 strokeDasharray="0 1"
_30 d="M0 257.25V69.51h27.89v187.74H0Zm113.5 0-48.03-87.8-1.81-5.17-2.58 5.04-19.24 25.18c-1.64-4.56-2.35-9.77-2.13-15.62.21-5.85 1.29-11.75 3.23-17.69 1.94-5.94 4.71-11.36 8.33-16.27l55.39-75.41h31.25l-58.23 75.67 66.88 112.08H113.5ZM233.15 257.25c-4.91 0-9.99-.3-15.24-.9-5.25-.6-11.67-1.81-19.24-3.62 1.63-3.01 3.59-5.89 5.88-8.65 2.28-2.75 4.99-4.93 8.13-6.52 3.14-1.59 6.73-2.13 10.78-1.61 1.55.17 2.97.3 4.26.39 1.29.09 2.8.13 4.52.13 6.02 0 11.51-1.51 16.46-4.52 4.95-3.01 8.91-7.1 11.88-12.27s4.46-11.06 4.46-17.69c0-8.09-2.17-14.8-6.52-20.14s-10.2-9.34-17.56-12.01c-7.36-2.67-15.56-4-24.6-4h-28.02v88.45h-27.63V68.99c7.14-1.38 13.77-2.47 19.88-3.29 6.11-.82 12.05-1.44 17.82-1.87 5.77-.43 11.75-.65 17.95-.65 14.8 0 27.18 2.22 37.12 6.65 9.94 4.43 17.39 10.46 22.34 18.08 4.95 7.62 7.42 16.29 7.42 26.02 0 6.2-1.72 12.83-5.17 19.88-3.44 7.06-8.35 12.61-14.72 16.66l-7.49 3.62 7.23 1.81c6.37 2.84 11.9 6.54 16.59 11.1 4.69 4.56 8.31 9.75 10.85 15.56 2.54 5.81 3.81 12.07 3.81 18.79s-1.4 13.26-4.2 19.88c-2.8 6.63-6.82 12.65-12.07 18.08-5.25 5.42-11.67 9.77-19.24 13.04-7.58 3.27-16.14 4.91-25.7 4.91Zm-44.8-111.04h28.02c7.83 0 14.61-1.42 20.34-4.26 5.72-2.84 10.14-6.69 13.24-11.56 3.1-4.86 4.65-10.35 4.65-16.46 0-5.34-1.42-10.27-4.26-14.78-2.84-4.52-7.08-8.13-12.72-10.85-5.64-2.71-12.72-4.07-21.24-4.07-4.65 0-9.32.13-14.01.39-4.69.26-9.36.65-14.01 1.16v60.43Z"
The animation is pretty easy, we are just changing two properties: fillOpacity and pathLength
Note that the value of fillOpacity and pathLength must be between 0
and 1
.
PLayground: play with the fill opacity and path length
You may have noticed that in my case the logo path is fully written
with a Path length of 0.43.
If you try with other SVG the value may be different.
π€―
The real path length is not between 0 and 1, but in my case is 2123 units.
We don't need to know the realPathLength of our path because motion-framer handle this for us.
For a more detailed explanation of the code, check out the Framer Motion docs.
Conclusion
This is a basic example of how to animate SVG with Framer Motion, but you can do much more with it.
I just wanted to share how i did it for my logo, and maybe inspire you to try it out.
I hope you enjoyed this post, and if you have any questions or suggestions, feel free to contact me on twitter.
π€―
For reference here's the code of the SVG displayed as example at the top of this post
import { motion } from "framer-motion";
import { useEffect, useState } from "react";
export default function AnimateSvgLogoSlider() {
const [progress, setProgress] = useState(100);
const [isRunning, setIsRunning] = useState(false);
const togglePlay = () => {
setIsRunning(!isRunning);
const animationDuration = 3000;
const interval = setInterval(() => {
setProgress((progress) => progress + 1);
}, animationDuration / 100);
return () => clearInterval(interval);
<div className="flex flex-row justify-center items-center">
<Logo progress={progress / 100} />
<div className=" w-full flex flex-row gap-3 items-center">
onChange={(e) => setProgress(parseInt(e.target.value))}
className="range range-error"
className={clsx("btn btn-square", {
xmlns="http://www.w3.org/2000/svg"
d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.348a1.125 1.125 0 010 1.971l-11.54 6.347a1.125 1.125 0 01-1.667-.985V5.653z"
function Logo(props: LogoProps) {
const { progress = 0.1 } = props;
viewBox="0 0 331.25 326.77"
xmlns="http://www.w3.org/2000/svg"
animate={{ fillOpacity: progress, pathLength: progress }}
transition={{ ease: "easeInOut" }}
d="M0 257.25V69.51h27.89v187.74H0Zm113.5 0-48.03-87.8-1.81-5.17-2.58 5.04-19.24 25.18c-1.64-4.56-2.35-9.77-2.13-15.62.21-5.85 1.29-11.75 3.23-17.69 1.94-5.94 4.71-11.36 8.33-16.27l55.39-75.41h31.25l-58.23 75.67 66.88 112.08H113.5ZM233.15 257.25c-4.91 0-9.99-.3-15.24-.9-5.25-.6-11.67-1.81-19.24-3.62 1.63-3.01 3.59-5.89 5.88-8.65 2.28-2.75 4.99-4.93 8.13-6.52 3.14-1.59 6.73-2.13 10.78-1.61 1.55.17 2.97.3 4.26.39 1.29.09 2.8.13 4.52.13 6.02 0 11.51-1.51 16.46-4.52 4.95-3.01 8.91-7.1 11.88-12.27s4.46-11.06 4.46-17.69c0-8.09-2.17-14.8-6.52-20.14s-10.2-9.34-17.56-12.01c-7.36-2.67-15.56-4-24.6-4h-28.02v88.45h-27.63V68.99c7.14-1.38 13.77-2.47 19.88-3.29 6.11-.82 12.05-1.44 17.82-1.87 5.77-.43 11.75-.65 17.95-.65 14.8 0 27.18 2.22 37.12 6.65 9.94 4.43 17.39 10.46 22.34 18.08 4.95 7.62 7.42 16.29 7.42 26.02 0 6.2-1.72 12.83-5.17 19.88-3.44 7.06-8.35 12.61-14.72 16.66l-7.49 3.62 7.23 1.81c6.37 2.84 11.9 6.54 16.59 11.1 4.69 4.56 8.31 9.75 10.85 15.56 2.54 5.81 3.81 12.07 3.81 18.79s-1.4 13.26-4.2 19.88c-2.8 6.63-6.82 12.65-12.07 18.08-5.25 5.42-11.67 9.77-19.24 13.04-7.58 3.27-16.14 4.91-25.7 4.91Zm-44.8-111.04h28.02c7.83 0 14.61-1.42 20.34-4.26 5.72-2.84 10.14-6.69 13.24-11.56 3.1-4.86 4.65-10.35 4.65-16.46 0-5.34-1.42-10.27-4.26-14.78-2.84-4.52-7.08-8.13-12.72-10.85-5.64-2.71-12.72-4.07-21.24-4.07-4.65 0-9.32.13-14.01.39-4.69.26-9.36.65-14.01 1.16v60.43Z"