Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 2x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 38x 2x 2x 2x 38x 21x 21x 6x 6x 15x 15x 21x 21x 35x 35x 806x 806x 806x 746x 746x 746x 25x 746x 806x 806x 116x 116x 81x 35x 38x 38x 38x 38x 38x 3x 3x | import { AnimationOptions, Driver, DriverControls, KeyframeOptions, } from "./types" import { detectAnimationFromOptions } from "./utils/detect-animation-from-options" import sync, { cancelSync, FrameData } from "framesync" import { interpolate } from "../utils/interpolate" import { loopElapsed, reverseElapsed, hasRepeatDelayElapsed, } from "./utils/elapsed" const framesync: Driver = (update) => { const passTimestamp = ({ delta }: FrameData) => update(delta) return { start: () => sync.update(passTimestamp, true, true), stop: () => cancelSync.update(passTimestamp), } } export function animate<V = number>({ from, autoplay = true, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, onPlay, onStop, onComplete, onRepeat, onUpdate, ...options }: AnimationOptions<V>) { let { to } = options let driverControls: DriverControls let repeatCount = 0 let computedDuration = (options as KeyframeOptions<V>).duration let latest: V let isComplete = false let isForwardPlayback = true let interpolateFromNumber: (t: number) => V const animator = detectAnimationFromOptions(options) if ((animator as any).needsInterpolation?.(from, to)) { interpolateFromNumber = interpolate([0, 100], [from, to], { clamp: false, }) as (t: number) => V from = 0 as any to = 100 as any } const animation = animator({ ...options, from, to } as any) function repeat() { repeatCount++ if (repeatType === "reverse") { isForwardPlayback = repeatCount % 2 === 0 elapsed = reverseElapsed( elapsed, computedDuration, repeatDelay, isForwardPlayback ) } else { elapsed = loopElapsed(elapsed, computedDuration, repeatDelay) if (repeatType === "mirror") animation.flipTarget() } isComplete = false onRepeat && onRepeat() } function complete() { driverControls.stop() onComplete && onComplete() } function update(delta: number) { if (!isForwardPlayback) delta = -delta elapsed += delta if (!isComplete) { const state = animation.next(Math.max(0, elapsed)) latest = state.value as any if (interpolateFromNumber) latest = interpolateFromNumber(latest as any) isComplete = isForwardPlayback ? state.done : elapsed <= 0 } onUpdate?.(latest) if (isComplete) { if (repeatCount === 0) computedDuration ??= elapsed if (repeatCount < repeatMax) { hasRepeatDelayElapsed( elapsed, computedDuration, repeatDelay, isForwardPlayback ) && repeat() } else { complete() } } } function play() { onPlay?.() driverControls = driver(update) driverControls.start() } autoplay && play() return { stop: () => { onStop?.() driverControls.stop() }, } } |