关于 lightweight-3d-effects
Lightweight 3D Effects Skill 汇集 Zdog、Vanta.js 和 Vanilla-Tilt.js,用于网页中的装饰性 3D 图形、动画背景和倾斜交互。适合希望为页面和卡片增加视觉层次的设计师与开发者。
主要功能
- 01Zdog 伪 3D 矢量图形
- 02Canvas 或 SVG 渲染
- 03Vanta.js 动画背景与交互
- 04Vanilla-Tilt.js 倾斜与视差效果
- 05陀螺仪和眩光效果
适用场景
- 01为落地页主视觉添加动画背景
- 02制作可拖动旋转的装饰插图
- 03为卡片和图片添加倾斜交互
- 04组合背景效果与倾斜卡片
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ freshtechbro/ claudedesignskills --skill lightweight-3d-effects安装后在 Claude Code 中输入/lightweight-3d-effects确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/examples/README.mdassets/starter_lightweight/index.htmlmain.jsREADME.mdstyle.cssreferences/tilt_patterns.mdvantajs_effects.mdzdog_api.mdscripts/generate_zdog.pysetup_vanta.py详细介绍
轻量级 3D 效果技能
概述
此技能结合了三个功能强大的库,用于创建装饰性 3D 元素和微交互:
- Zdog:面向设计师友好的伪 3D 矢量插画引擎
- Vanta.js:由 Three.js/p5.js 驱动的动画 3D 背景
- Vanilla-Tilt.js:可响应鼠标/陀螺仪的流畅视差倾斜效果
何时使用此技能
- 无需沉重框架即可添加装饰性 3D 插画
- 为 Hero 区块创建动画背景
- 为卡片/图片实现细微的视差倾斜效果
- 构建具有视觉纵深感的轻量级落地页
- 添加增强用户体验且不影响性能的微交互
Zdog - 伪 3D 插画
核心概念
Zdog 是一个伪 3D 引擎,可使用 Canvas 或 SVG 在 3D 空间中渲染扁平、圆润的设计。
主要特性:
- 面向设计师的声明式 API
- 文件体积小(压缩后约 28kb)
- 支持 Canvas 或 SVG 渲染
- 内置拖动旋转
- 动画流畅
基本设置
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/zdog@1/dist/zdog.dist.min.js"></script>
<style>
.zdog-canvas {
display: block;
margin: 0 auto;
background: #FDB;
cursor: move;
}
</style>
</head>
<body>
<canvas class="zdog-canvas" width="240" height="240"></canvas>
<script>
let isSpinning = true;
let illo = new Zdog.Illustration({
element: '.zdog-canvas',
zoom: 4,
dragRotate: true,
onDragStart: function() {
isSpinning = false;
},
});
// Add shapes
new Zdog.Ellipse({
addTo: illo,
diameter: 20,
translate: { z: 10 },
stroke: 5,
color: '#636',
});
new Zdog.Rect({
addTo: illo,
width: 20,
height: 20,
translate: { z: -10 },
stroke: 3,
color: '#E62',
fill: true,
});
function animate() {
illo.rotate.y += isSpinning ? 0.03 : 0;
illo.updateRenderGraph();
requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>
Zdog 形状
基本形状:
// Circle
new Zdog.Ellipse({
addTo: illo,
diameter: 80,
stroke: 20,
color: '#636',
});
// Rectangle
new Zdog.Rect({
addTo: illo,
width: 80,
height: 60,
stroke: 10,
color: '#E62',
fill: true,
});
// Rounded Rectangle
new Zdog.RoundedRect({
addTo: illo,
width: 60,
height: 40,
cornerRadius: 10,
stroke: 4,
color: '#C25',
fill: true,
});
// Polygon
new Zdog.Polygon({
addTo: illo,
radius: 40,
sides: 5,
stroke: 8,
color: '#EA0',
fill: true,
});
// Line
new Zdog.Shape({
addTo: illo,
path: [
{ x: -40, y: 0 },
{ x: 40, y: 0 },
],
stroke: 6,
color: '#636',
});
// Bezier Curve
new Zdog.Shape({
addTo: illo,
path: [
{ x: -40, y: -20 },
{
bezier: [
{ x: -40, y: 20 },
{ x: 40, y: 20 },
{ x: 40, y: -20 },
],
},
],
stroke: 4,
color: '#C25',
closed: false,
});
Zdog 组
将形状组织成组,以构建复杂模型:
// Create a group
let head = new Zdog.Group({
addTo: illo,
translate: { y: -40 },
});
// Add shapes to group
new Zdog.Ellipse({
addTo: head,
diameter: 60,
stroke: 30,
color: '#FED',
});
// Eyes
new Zdog.Ellipse({
addTo: head,
diameter: 8,
stroke: 4,
color: '#333',
translate: { x: -10, z: 15 },
});
new Zdog.Ellipse({
addTo: head,
diameter: 8,
stroke: 4,
color: '#333',
translate: { x: 10, z: 15 },
});
// Mouth
new Zdog.Shape({
addTo: head,
path: [
{ x: -10, y: 0 },
{
bezier: [
{ x: -5, y: 5 },
{ x: 5, y: 5 },
{ x: 10, y: 0 },
],
},
],
stroke: 2,
color: '#333',
translate: { y: 5, z: 15 },
closed: false,
});
// Rotate entire group
head.rotate.y = Math.PI / 4;
Zdog 动画
// Continuous rotation
function animate() {
illo.rotate.y += 0.03;
illo.updateRenderGraph();
requestAnimationFrame(animate);
}
animate();
// Bounce animation
let t = 0;
function bounceAnimate() {
t += 0.05;
illo.translate.y = Math.sin(t) * 20;
illo.updateRenderGraph();
requestAnimationFrame(bounceAnimate);
}
bounceAnimate();
// Interactive rotation with easing
let targetRotateY = 0;
let currentRotateY = 0;
document.addEventListener('mousemove', (event) => {
targetRotateY = (event.clientX / window.innerWidth - 0.5) * Math.PI;
});
function smoothAnimate() {
// Ease towards target
currentRotateY += (targetRotateY - currentRotateY) * 0.1;
illo.rotate.y = currentRotateY;
illo.updateRenderGraph();
requestAnimationFrame(smoothAnimate);
}
smoothAnimate();
Vanta.js - 动画 3D 背景
核心概念
Vanta.js 只需极少设置即可提供动画 WebGL 背景,由 Three.js 或 p5.js 驱动。
主要特性:
- 14 种以上动画效果(Waves、Birds、Net、Clouds 等)
- 鼠标/触摸交互
- 可自定义颜色和设置
- 总计约 120KB(包括 Three.js)
- 在大多数设备上可达 60fps
基本设置
<!DOCTYPE html>
<html>
<head>
<style>
#vanta-bg {
width: 100%;
height: 100vh;
}
.content {
position: relative;
z-index: 1;
color: white;
text-align: center;
padding: 100px 20px;
}
</style>
</head>
<body>
<div id="vanta-bg">
<div class="content">
<h1>My Animated Background</h1>
<p>Content goes here</p>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vanta.waves.min.js"></script>
<script>
VANTA.WAVES({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x23153c,
shininess: 30.00,
waveHeight: 15.00,
waveSpeed: 0.75,
zoom: 0.65
});
</script>
</body>
</html>
可用效果
1. WAVES(Three.js)
VANTA.WAVES({
el: "#vanta-bg",
color: 0x23153c,
shininess: 30,
waveHeight: 15,
waveSpeed: 0.75,
zoom: 0.65
});
2. CLOUDS(Three.js)
VANTA.CLOUDS({
el: "#vanta-bg",
skyColor: 0x68b8d7,
cloudColor: 0xadc1de,
cloudShadowColor: 0x183550,
sunColor: 0xff9919,
sunGlareColor: 0xff6633,
sunlightColor: 0xff9933,
speed: 1.0
});
3. BIRDS(需要 p5.js)
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vanta.birds.min.js"></script>
<script>
VANTA.BIRDS({
el: "#vanta-bg",
backgroundColor: 0x23153c,
color1: 0xff0000,
color2: 0x0000ff,
birdSize: 1.5,
wingSpan: 20,
speedLimit: 5,
separation: 40,
alignment: 40,
cohesion: 40,
quantity: 3
});
</script>
4. NET(Three.js)
VANTA.NET({
el: "#vanta-bg",
color: 0x3fff00,
backgroundColor: 0x23153c,
points: 10,
maxDistance: 20,
spacing: 15,
showDots: true
});
5. CELLS(需要 p5.js)
VANTA.CELLS({
el: "#vanta-bg",
color1: 0x00ff00,
color2: 0xff0000,
size: 1.5,
speed: 1.0,
scale: 1.0
});
6. FOG(Three.js)
VANTA.FOG({
el: "#vanta-bg",
highlightColor: 0xff3f81,
midtoneColor: 0x1d004d,
lowlightColor: 0x2b1a5e,
baseColor: 0x000000,
blurFactor: 0.6,
speed: 1.0,
zoom: 1.0
});
**其他效果:**GLOBE、TRUNK、TOPOLOGY、DOTS、HALO、RINGS
配置选项
// Common options for all effects
{
el: "#element-id", // Required: target element
mouseControls: true, // Enable mouse interaction
touchControls: true, // Enable touch interaction
gyroControls: false, // Device orientation
minHeight: 200.00, // Minimum height
minWidth: 200.00, // Minimum width
scale: 1.00, // Size scale
scaleMobile: 1.00, // Mobile scale
// Colors (hex numbers, not strings)
color: 0x23153c,
backgroundColor: 0x000000,
// Performance
forceAnimate: false, // Force animation even when hidden
// Effect-specific options vary by effect
}
Vanta.js 方法
// Initialize and store reference
const vantaEffect = VANTA.WAVES({
el: "#vanta-bg",
// ... options
});
// Destroy when done (important for SPAs)
vantaEffect.destroy();
// Update options dynamically
vantaEffect.setOptions({
color: 0xff0000,
waveHeight: 20
});
// Resize (usually automatic)
vantaEffect.resize();
React 集成
import { useEffect, useRef, useState } from 'react';
import VANTA from 'vanta/dist/vanta.waves.min';
import * as THREE from 'three';
function VantaBackground() {
const vantaRef = useRef(null);
const [vantaEffect, setVantaEffect] = useState(null);
useEffect(() => {
if (!vantaEffect) {
setVantaEffect(VANTA.WAVES({
el: vantaRef.current,
THREE: THREE,
mouseControls: true,
touchControls: true,
color: 0x23153c,
shininess: 30,
waveHeight: 15,
waveSpeed: 0.75
}));
}
return () => {
if (vantaEffect) vantaEffect.destroy();
};
}, [vantaEffect]);
return (
<div ref={vantaRef} style={{ width: '100%', height: '100vh' }}>
<div className="content">
<h1>React + Vanta.js</h1>
</div>
</div>
);
}
Vanilla-Tilt.js - 视差倾斜效果
核心概念
Vanilla-Tilt.js 可添加响应鼠标移动和设备方向变化的流畅 3D 倾斜效果。
主要特性:
- 轻量级(压缩后约 8.5kb)
- 无依赖
- 支持陀螺仪
- 可选眩光效果
- 过渡流畅
基本设置
<!DOCTYPE html>
<html>
<head>
<style>
.tilt-card {
width: 300px;
height: 400px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 15px;
margin: 50px auto;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24px;
transform-style: preserve-3d;
}
.tilt-inner {
transform: translateZ(60px);
}
</style>
</head>
<body>
<div class="tilt-card" data-tilt>
<div class="tilt-inner">Hover Me!</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vanilla-tilt.min.js"></script>
</body>
</html>
配置选项
VanillaTilt.init(document.querySelector(".tilt-card"), {
// Rotation
max: 25, // Max tilt angle (degrees)
reverse: false, // Reverse tilt direction
startX: 0, // Initial tilt X (degrees)
startY: 0, // Initial tilt Y (degrees)
// Appearance
perspective: 1000, // Transform perspective (lower = more intense)
scale: 1.1, // Scale on hover (1 = no scale)
// Animation
speed: 400, // Transition speed (ms)
transition: true, // Enable smooth transitions
easing: "cubic-bezier(.03,.98,.52,.99)",
// Behavior
axis: null, // Restrict to "x" or "y" axis
reset: true, // Reset on mouse leave
"reset-to-start": true, // Reset to start position vs [0,0]
// Glare effect
glare: true, // Enable glare
"max-glare": 0.5, // Glare opacity (0-1)
"glare-prerender": false, // Pre-render glare elements
// Advanced
full-page-listening: false, // Listen to entire page
gyroscope: true, // Enable device orientation
gyroscopeMinAngleX: -45, // Min X angle
gyroscopeMaxAngleX: 45, // Max X angle
gyroscopeMinAngleY: -45, // Min Y angle
gyroscopeMaxAngleY: 45, // Max Y angle
gyroscopeSamples: 10 // Calibration samples
});
高级示例
带眩光效果的卡片:
<div class="tilt-card" data-tilt
data-tilt-glare
data-tilt-max-glare="0.5"
data-tilt-scale="1.1">
<div class="tilt-inner">
<h3>Premium Card</h3>
<p>With glare effect</p>
</div>
</div>
分层 3D 效果:
<style>
.tilt-card {
transform-style: preserve-3d;
}
.layer-1 {
transform: translateZ(20px);
}
.layer-2 {
transform: translateZ(40px);
}
.layer-3 {
transform: translateZ(60px);
}
</style>
<div class="tilt-card" data-tilt data-tilt-max="15">
<div class="layer-1">Background</div>
<div class="layer-2">Middle</div>
<div class="layer-3">Front</div>
</div>
以编程方式控制:
const element = document.querySelector(".tilt-card");
VanillaTilt.init(element, {
max: 25,
speed: 400,
glare: true,
"max-glare": 0.5
});
// Get tilt values
element.addEventListener("tiltChange", (e) => {
console.log("Tilt:", e.detail);
});
// Reset programmatically
element.vanillaTilt.reset();
// Destroy instance
element.vanillaTilt.destroy();
// Get current values
const values = element.vanillaTilt.getValues();
console.log(values); // { tiltX, tiltY, percentageX, percentageY, angle }
React 集成
import { useEffect, useRef } from 'react';
import VanillaTilt from 'vanilla-tilt';
function TiltCard({ children, options }) {
const tiltRef = useRef(null);
useEffect(() => {
const element = tiltRef.current;
VanillaTilt.init(element, {
max: 25,
speed: 400,
glare: true,
"max-glare": 0.5,
...options
});
return () => {
element.vanillaTilt.destroy();
};
}, [options]);
return (
<div ref={tiltRef} className="tilt-card">
{children}
</div>
);
}
// Usage
<TiltCard options={{ max: 30, scale: 1.1 }}>
<h3>My Card</h3>
</TiltCard>
常见模式
模式 1:使用 Vanta 和内容构建 Hero 区块
<section id="hero">
<div class="hero-content">
<h1>Welcome</h1>
<p>Animated background with content overlay</p>
<button>Get Started</button>
</div>
</section>
<style>
#hero {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
.hero-content {
position: relative;
z-index: 1;
color: white;
text-align: center;
padding-top: 20vh;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vanta.waves.min.js"></script>
<script>
VANTA.WAVES({
el: "#hero",
mouseControls: true,
touchControls: true,
color: 0x23153c,
waveHeight: 20,
waveSpeed: 1.0
});
</script>
模式 2:Zdog 图标网格
<div class="icon-grid">
<canvas class="icon" width="120" height="120"></canvas>
<canvas class="icon" width="120" height="120"></canvas>
<canvas class="icon" width="120" height="120"></canvas>
</div>
<script src="https://unpkg.com/zdog@1/dist/zdog.dist.min.js"></script>
<script>
document.querySelectorAll('.icon').forEach((canvas, index) => {
let illo = new Zdog.Illustration({
element: canvas,
zoom: 3,
dragRotate: true
});
// Create different icon for each canvas
const icons = [
createHeartIcon,
createStarIcon,
createCheckIcon
];
icons[index](illo);
function animate() {
illo.rotate.y += 0.02;
illo.updateRenderGraph();
requestAnimationFrame(animate);
}
animate();
});
function createHeartIcon(illo) {
new Zdog.Shape({
addTo: illo,
path: [
{ x: 0, y: -10 },
{
bezier: [
{ x: -20, y: -20 },
{ x: -20, y: 0 },
{ x: 0, y: 10 }
]
},
{
bezier: [
{ x: 20, y: 0 },
{ x: 20, y: -20 },
{ x: 0, y: -10 }
]
}
],
stroke: 6,
color: '#E62',
fill: true,
closed: false
});
}
</script>
模式 3:倾斜卡片画廊
<div class="card-gallery">
<div class="card" data-tilt data-tilt-glare data-tilt-max-glare="0.3">
<img src="product1.jpg" alt="Product 1">
<h3>Product 1</h3>
</div>
<div class="card" data-tilt data-tilt-glare data-tilt-max-glare="0.3">
<img src="product2.jpg" alt="Product 2">
<h3>Product 2</h3>
</div>
<div class="card" data-tilt data-tilt-glare data-tilt-max-glare="0.3">
<img src="product3.jpg" alt="Product 3">
<h3>Product 3</h3>
</div>
</div>
<style>
.card-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 30px;
padding: 50px;
}
.card {
background: white;
border-radius: 15px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
transform-style: preserve-3d;
}
.card img {
width: 100%;
border-radius: 10px;
transform: translateZ(40px);
}
.card h3 {
margin-top: 15px;
transform: translateZ(60px);
}
</style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vanilla-tilt.min.js"></script>
模式 4:组合效果——Vanta 背景 + 倾斜卡片
<div id="vanta-section">
<div class="container">
<h1>Our Services</h1>
<div class="services-grid">
<div class="service-card" data-tilt data-tilt-scale="1.05">
<div class="icon">🚀</div>
<h3>Fast</h3>
<p>Lightning quick performance</p>
</div>
<div class="service-card" data-tilt data-tilt-scale="1.05">
<div class="icon">🎨</div>
<h3>Beautiful</h3>
<p>Stunning visual design</p>
</div>
<div class="service-card" data-tilt data-tilt-scale="1.05">
<div class="icon">💪</div>
<h3>Powerful</h3>
<p>Feature-rich platform</p>
</div>
</div>
</div>
</div>
<script>
// Vanta background
VANTA.NET({
el: "#vanta-section",
color: 0x3fff00,
backgroundColor: 0x23153c,
points: 10,
maxDistance: 20
});
// Tilt cards
VanillaTilt.init(document.querySelectorAll(".service-card"), {
max: 15,
speed: 400,
glare: true,
"max-glare": 0.3
});
</script>
性能最佳实践
Zdog 优化
- 限制形状数量:形状总数保持在 100 个以内,以确保 60fps 流畅运行
- 使用组:将相关形状组织在一起,便于管理
- 优化动画循环:仅在需要时调用
updateRenderGraph() - Canvas 与 SVG:动画使用 Canvas 更快,静态插画使用 SVG 更合适
Vanta.js 优化
- 单个实例:每个页面仅使用 1-2 个 Vanta 效果
- 移动设备回退方案:在移动设备上禁用,或使用静态背景
- 卸载时销毁:在 SPA 中始终调用
.destroy() - 减少粒子数量:降低
points、quantity的值以提升性能
// Mobile detection and fallback
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (!isMobile) {
VANTA.WAVES({
el: "#hero",
// ... options
});
} else {
document.getElementById('hero').style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
}
Vanilla-Tilt 优化
- 限制实例数量:仅应用于可见元素
- 降低
gyroscopeSamples:降低其值以提升移动设备上的性能 - 在低端设备上禁用:检查设备性能
- 使用 CSS
will-change:提示浏览器即将进行变换
.tilt-card {
will-change: transform;
}
常见问题
问题 1:多个 Vanta 实例
问题:多个 Vanta 效果会导致性能问题
解决方案:仅使用一个效果,或按区块延迟加载效果
// Intersection Observer to load Vanta only when visible
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting && !entry.target.vantaEffect) {
entry.target.vantaEffect = VANTA.WAVES({
el: entry.target,
// ... options
});
}
});
});
observer.observe(document.getElementById('hero'));
陷阱 2:SPA 中的内存泄漏
问题:组件卸载时未销毁 Vanta/Tilt
解决方案:始终清理
// React useEffect cleanup
useEffect(() => {
const effect = VANTA.WAVES({ el: vantaRef.current });
return () => {
effect.destroy(); // Important!
};
}, []);
陷阱 3:Zdog 未渲染
问题:画布显示为空白
原因:
- 忘记调用
updateRenderGraph() - 画布尺寸为 0
- 图形位于视野之外
解决方案:
// Always call updateRenderGraph after shape changes
illo.updateRenderGraph();
// Ensure canvas has dimensions
<canvas width="240" height="240"></canvas>
// Check shape positions are visible
new Zdog.Ellipse({
addTo: illo,
diameter: 20,
translate: { z: 0 }, // Keep close to origin
});
陷阱 4:Tilt 在移动设备上无法使用
问题:Tilt 在移动设备上没有响应
解决方案:启用陀螺仪控制
VanillaTilt.init(element, {
gyroscope: true,
gyroscopeMinAngleX: -45,
gyroscopeMaxAngleX: 45
});
陷阱 5:颜色格式混淆(Vanta.js)
问题:颜色无法使用
原因:Vanta.js 使用十六进制数字,而不是字符串
// ❌ Wrong
color: "#23153c"
// ✅ Correct
color: 0x23153c
资源
Zdog:
Vanta.js:
Vanilla-Tilt.js:
相关技能
- threejs-webgl:用于制作超越装饰效果的更复杂 3D 图形
- gsap-scrolltrigger:用于在滚动时为这些效果添加动画
- motion-framer:用于制作 React 组件动画,与这些效果搭配使用
- react-three-fiber:当轻量级效果无法满足需求时,用于高级 3D