Contents
SVG loading spinner
import "./styles.css" import { animate, stagger } from "motion" const numSegments = document.querySelectorAll(".segment").length /** * Stagger offset (in seconds) * Decrease this to speed the animation up or increase * to slow it down. */ const offset = 0.09 setTimeout(() => { animate( ".segment", { opacity: [0, 1, 0] }, { offset: [0, 0.1, 1], duration: numSegments * offset, delay: stagger(offset), repeat: Infinity, } ) }, 1000)
SVG path drawing timeline
import "./styles.css" import { timeline } from "motion" /** * Remember to set the pathLength="1" SVG attribute on * the elements you want to draw. This makes it easy * to use the same animation logic for elements of a * different path length. */ const draw = (progress) => ({ // This property makes the line "draw" in when animated strokeDashoffset: 1 - progress, // Each line will be hidden until it starts drawing // to fix a bug in Safari where the line can be // partially visible even when progress is at 0 visibility: "visible", }) timeline([ ["circle", draw(1), { duration: 0.8, delay: 1 }], ["path", draw(1), { duration: 0.6, at: "-0.2" }], ])
Scroll-triggered animation
Animating HTML text
Morph SVG path
import { animate } from "motion"; import { interpolate } from "flubber"; import { paths } from "./paths"; const path = document.querySelector("path"); let currentPath = paths.star; path.setAttribute("fill", currentPath.color); path.setAttribute("d", currentPath.d); const transition = { duration: 0.5 }; function togglePath() { currentPath = currentPath === paths.star ? paths.heart : paths.star; const mixPaths = interpolate(path.getAttribute("d"), currentPath.d, { maxSegmentLength: 0.1 }); animate(path, { fill: currentPath.color }, transition); animate((progress) => path.setAttribute("d", mixPaths(progress)), transition); } setTimeout(togglePath, 1000); path.addEventListener("click", togglePath);
P5
Mixing Motion One custom animations with the P5 library.
import P5 from "p5"; import { animate, spring } from "motion"; import { mix, progress, wrap } from "@motionone/utils"; new P5(function (p5) { let x = 0; let y = 0; let radius = 50; let weight = 3; let currentAnimation; const startAnimation = (targetX, targetY) => { const originX = x; const originY = y; currentAnimation && currentAnimation.stop(); currentAnimation = animate( (progress) => { x = mix(originX, targetX, progress); y = mix(originY, targetY, progress); }, { easing: spring({ stiffness: 300, damping: 10, restDistance: 0.001 }) } ); }; p5.setup = () => { const { width, height, elt: element } = p5.createCanvas( Math.max(document.documentElement.clientWidth, window.innerWidth || 0), Math.max(document.documentElement.clientHeight, window.innerHeight || 0) ); x = width / 2; y = height / 2; element.addEventListener("click", (event) => { startAnimation(event.pageX, event.pageY); }); }; p5.draw = () => { p5.noFill(); p5.strokeWeight(weight); p5.stroke(`hsl(${getHue(performance.now())}, 100%, 50%)`); p5.circle(x, y, radius); }; }); const duration = 4000; function getHue(t) { const looped = wrap(0, duration, t); const p = progress(0, duration, looped); return Math.round(mix(0, 360, p)); }
Scroll
Page progress bar
Element-based progress bar
Parallax and scroll-snapping
Fade on enter/exit
Video scrubbing
3D camera
Custom easing function
Have you seen Motion DevTools?
It's an incredible new developer tool for Chrome that let you inspect, edit and export Motion One and CSS animations. Animate like the good-ol' days of Flash!