SVG动画案例库
浏览精选的SVG动画案例
移开即停止播放
'use client';
import React, { useState, useEffect, useRef, useMemo } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 600;
const CENTER_X = VIEW_WIDTH / 2;
const CENTER_Y = VIEW_HEIGHT / 2;
const RAY_LENGTH = 350;
// Refractive Indices
const N1 = 1.00; // Air
const N2 = 1.33; // Water
export const LightRefractionView = () => {
const [incidentAngleDeg, setIncidentAngleDeg] = useState(45);
const timeRef = useRef(0);
const requestRef = useRef<number>();
// Animation Loop
con
Light refraction at the water surface
移开即停止播放
'use client';
import React, { useState, useEffect, useRef } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 400;
const WAVE_SPEED = 2; // 波纹扩散速度
const EMISSION_RATE = 15; // 发射频率 (每多少帧发射一次)
const MAX_SOURCE_SPEED = 1.2; // 源点移动最大速度 (需小于 WAVE_SPEED 以避免音爆/混乱)
export const DopplerEffectView = () => {
const [waves, setWaves] = useState([]);
const [sourceX, setSourceX] = useState(200);
const [velocity, setVelocity] = useState(0);
const [phase, setPhase] = useState('static'); // s
Doppler effect of a moving wave source
移开即停止播放
'use client';
import React, { useState, useEffect, useRef } from 'react';
const VIEW_WIDTH = 1000;
const VIEW_HEIGHT = 600;
const ARRAY_SIZE = 15;
// Helper to generate sorted unique random numbers
const generateSortedArray = (size) => {
const set = new Set();
while (set.size < size) {
set.add(Math.floor(Math.random() * 90) + 10);
}
return Array.from(set).sort((a, b) => a - b); // Numeric sort
};
export const BinarySearchView = () => {
// State
const [array, setArray] = useSt
Binary search in computing
移开即停止播放
'use client';
import React, { useState, useEffect, useRef } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 600;
const GROUND_Y = 500;
const APPLE_START_X = 480;
const APPLE_START_Y = 220;
const GRAVITY = 0.6;
const BOUNCE_FACTOR = 0.5;
export const AppleFallAnimation = () => {
// 动画状态
const [appleY, setAppleY] = useState(APPLE_START_Y);
const [rotation, setRotation] = useState(0);
const [status, setStatus] = useState<'hanging' | 'falling' | 'resting'>('hanging');
// 物理
An apple falling from a tree
移开即停止播放
'use client';
import React, { useState, useEffect, useRef, useMemo } from 'react';
const VIEW_WIDTH = 1000;
const VIEW_HEIGHT = 600;
export const MoonOrbitView = () => {
// 动画状态:角度 (0 ~ 2PI)
const [angle, setAngle] = useState(0);
const requestRef = useRef<number>();
// 轨道参数
const centerX = VIEW_WIDTH / 2;
const centerY = VIEW_HEIGHT / 2;
const orbitRadiusX = 350; // 椭圆长轴
const orbitRadiusY = 120; // 椭圆短轴 (模拟3D视角倾斜)
const earthRadius = 80;
const moonRadius = 20;
const
Moon orbiting Earth
移开即停止播放
'use client';
import React, { useState, useEffect, useRef, useMemo } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 450;
const ANIMATION_DURATION = 8000; // 8 seconds per loop
export default function NewsIntroAnimation() {
const [time, setTime] = useState(0);
const requestRef = useRef(null);
const startTimeRef = useRef(null);
// Animation Loop
const animate = (timestamp) => {
if (!startTimeRef.current) startTimeRef.current = timestamp;
const elapsed = timestamp -
News-style intro: ANIMORA spins then becomes Animation Studio
移开即停止播放
'use client';
import React, { useState, useEffect, useRef } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 400;
export default function LittleBoyDriving() {
const [frame, setFrame] = useState(0);
// 动画循环
useEffect(() => {
let animationFrameId;
const loop = () => {
setFrame((f) => f + 1);
animationFrameId = requestAnimationFrame(loop);
};
loop();
return () => cancelAnimationFrame(animationFrameId);
}, []);
// 动画参数计算
const roadSpeed = 8;
Little boy driving a car
移开即停止播放
'use client';
import React, { useState, useEffect, useRef, useMemo } from 'react';
const VIEW_WIDTH = 1000;
const VIEW_HEIGHT = 600;
const CENTER_Y = VIEW_HEIGHT / 2;
const CIRCLE_X = 150;
const WAVE_START_X = 300;
const RADIUS = 80;
export const SineWaveView = () => {
// 动画相位状态
const [phase, setPhase] = useState(0);
const requestRef = useRef<number>();
const previousTimeRef = useRef<number>();
// 动画循环
const animate = (time: number) => {
if (previousTimeRef.current !== undefi
Sine wave extending forward on axes
广告
Ads移开即停止播放
'use client';
import React, { useState, useEffect, useRef } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 600;
const BALL_RADIUS = 30;
const STRING_LENGTH = 250;
const PIVOT_Y = 100;
const CENTER_X = VIEW_WIDTH / 2;
const MAX_ANGLE = Math.PI / 4; // 45 degrees swing
export const NewtonsCradle = () => {
const [time, setTime] = useState(Math.PI); // Start with left ball ready to swing down
const requestRef = useRef<number>();
// Physics loop
const animate = () => {
//
Newton's cradle with 5 metal balls
移开即停止播放
'use client';
import React, { useState, useEffect, useRef, useMemo } from 'react';
// 视图配置
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 500;
const CENTER_X = VIEW_WIDTH / 2;
const CENTER_Y = VIEW_HEIGHT / 2;
// 轨道参数
const A = 300; // 半长轴
const E = 0.6; // 离心率 (0.6 使得速度差异明显)
const B = A * Math.sqrt(1 - E * E); // 半短轴
const C = A * E; // 焦距 (中心到焦点的距离)
// 动画参数
const ANIMATION_SPEED = 0.015; // 平均角速度因子
const SWEEP_INTERVAL = 1.5; // 扫过区域的时间间隔 (弧度制下的平均近点角跨度)
export const KeplerSecondLawView = ()
Planetary elliptical orbit showing equal swept areas (Kepler's second law)
移开即停止播放
'use client';
import React, { useMemo, useEffect, useState } from 'react';
const VIEW_WIDTH = 800;
const VIEW_HEIGHT = 600;
const CENTER_X = VIEW_WIDTH / 2;
const CENTER_Y = VIEW_HEIGHT / 2;
export const BlackHoleAnimation = () => {
// 生成背景星空
const stars = useMemo(() => {
return Array.from({ length: 150 }).map((_, i) => ({
id: i,
x: Math.random() * VIEW_WIDTH,
y: Math.random() * VIEW_HEIGHT,
r: Math.random() * 1.5 + 0.5,
opacity: Math.random() * 0.7 + 0.3