简介
Anime.js 是一个轻量级的 JavaScript 动画库,它提供了简单而强大的 API 来创建各种复杂的动画效果。以下是 Anime.js 的主要使用方法和特性:
安装
npm install animejs
基本用法
<script setup>
import { ref, onMounted } from "vue";
import anime from "animejs";const rotations = ref(0);
const logoRef = ref(null);const handleClick = () => {rotations.value += 1;anime({targets: logoRef.value,rotate: rotations.value * 360,easing: "easeOutQuart",duration: 2000,});
};onMounted(() => {anime({targets: logoRef.value,scale: [{ value: 1.25, easing: "easeInOutCubic", duration: 200 },{ value: 1, easing: "spring(1, 80, 10, 0)" },],loop: true,direction: "alternate",loopDelay: 250,});
});
</script><template><div class="mt-10"><img ref="logoRef" src="@/assets/react.svg" class="logo" alt="React logo" /><buttonclass="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors mt-4"@click="handleClick">旋转</button></div>
</template>
定时器(timer)
<script setup>
import { ref, onMounted, onUnmounted } from "vue";const time = ref(0);
const count = ref(0);
let interval = null;onMounted(() => {let currentIteration = 0;interval = setInterval(() => {time.value = Date.now();currentIteration += 1;count.value = currentIteration;}, 1000 / 30);
});onUnmounted(() => {clearInterval(interval);
});
</script><template><div class="m-10 container mx-auto max-w-2xl"><div class="flex flex-row justify-center items-center gap-8"><divclass="relative w-64 h-24 rounded-lg overflow-hidden shadow-lg bg-[#6d402a] flex flex-col items-center justify-center"><span class="text-lg text-white mb-2">current time</span><spanclass="text-6xl font-mono font-bold tracking-widest text-[#ffa94d] lcd">{{ time }}</span></div><divclass="relative w-64 h-24 rounded-lg overflow-hidden shadow-lg bg-[#6d402a] flex flex-col items-center justify-center"><span class="text-lg text-white mb-2">callback fired</span><spanclass="text-6xl font-mono font-bold tracking-widest text-[#ffa94d] lcd">{{ count }}</span></div></div></div>
</template>
时间线(timeline)
<script setup>
import { onMounted } from "vue";
import anime from "animejs";onMounted(() => {const tl = anime.timeline({ duration: 750 });tl.add({ targets: ".square", translateX: "15rem" }).add({ targets: ".circle", translateX: "15rem" }).add({ targets: ".triangle", translateX: "15rem", rotate: "1turn" });
});
</script><template><div class="flex gap-4 mt-10"><div class="square w-16 h-16 bg-red-400 rounded"></div><div class="circle w-16 h-16 bg-green-400 rounded-full"></div><divclass="triangle"style="width: 0; height: 0; border-left: 32px solid transparent; border-right: 32px solid transparent; border-bottom: 64px solid #60a5fa;"></div></div>
</template>
动画(animate)
<script setup>
import { ref } from "vue";
import anime from "animejs";const boxRef = ref(null);const handleAnimate = () => {anime({targets: boxRef.value,opacity: [0, 1],scale: [0.5, 1.2, 1],rotate: [0, 360],duration: 1200,easing: "easeInOutCubic",});
};
</script><template><div class="mt-10 flex flex-col items-center"><div ref="boxRef" class="w-24 h-24 bg-purple-400 rounded mb-4"></div><button@click="handleAnimate"class="px-4 py-2 bg-purple-600 text-white rounded">动画</button></div>
</template>
拖动(drag)
<script setup>
import { ref, onMounted } from "vue";
import interact from "interactjs";const containerRef = ref(null);
const squareRef = ref(null);onMounted(() => {interact(squareRef.value).draggable({inertia: true,modifiers: [interact.modifiers.restrictRect({restriction: containerRef.value,endOnly: true,}),],listeners: {move(event) {const target = event.target;const x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx;const y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;target.style.transform = `translate(${x}px, ${y}px)`;target.setAttribute("data-x", x);target.setAttribute("data-y", y);},},});
});
</script><template><divref="containerRef"class="mt-10 w-[400px] h-[200px] bg-gray-100 relative flex items-center justify-center"><divref="squareRef"class="square w-16 h-16 bg-yellow-400 rounded absolute top-0 left-0 cursor-move"></div></div>
</template>
滚动(scroll)
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import anime from "animejs";const lastProgress = ref(0);
let ticking = false;const onScroll = () => {if (!ticking) {window.requestAnimationFrame(() => {const scrollY = window.scrollY;const docHeight = document.body.scrollHeight - window.innerHeight;const progress = Math.min(scrollY / docHeight, 1);if (Math.abs(progress - lastProgress.value) > 0.001) {lastProgress.value = progress;// 1. 粉色盒子:分段动画if (progress < 0.33) {anime({targets: ".scroll-box",translateY: progress * 600,scale: 1 + progress * 1.5,opacity: 1,rotate: 0,background: "#f472b6",duration: 400,easing: "easeOutCubic",});} else if (progress < 0.66) {anime({targets: ".scroll-box",translateY: 200 + (progress - 0.33) * 600,scale: 1.5,opacity: 1 - (progress - 0.33) * 1.5,rotate: (progress - 0.33) * 720,background: "#fbbf24",duration: 400,easing: "easeInOutCubic",});} else {anime({targets: ".scroll-box",translateY: 400 + (progress - 0.66) * 600,scale: 1.5 - (progress - 0.66) * 1.5,opacity: 0.5 - (progress - 0.66) * 1.5,rotate: 360,background: "#34d399",duration: 400,easing: "easeInCubic",});}// 2. 蓝色盒子:左右来回移动+弹性anime({targets: ".scroll-box2",translateX: Math.sin(progress * Math.PI * 2) * 300,scale: 1 + Math.abs(Math.cos(progress * Math.PI)),rotate: progress * 360,background: "#60a5fa",duration: 500,easing: "easeOutElastic(1, .5)",});// 3. 进度条anime({targets: ".scroll-progress",scaleX: progress,duration: 200,easing: "linear",});// 4. 文字渐显anime({targets: ".scroll-text",opacity: progress,translateY: 100 - progress * 100,duration: 400,easing: "easeOutCubic",});}ticking = false;});ticking = true;}
};onMounted(() => {window.addEventListener("scroll", onScroll);
});onUnmounted(() => {window.removeEventListener("scroll", onScroll);
});
</script><template><div class="h-[2500px] relative"><!-- 滚动进度条 --><div class="fixed top-0 left-0 w-full h-2 bg-gray-200 z-50"><divclass="scroll-progress origin-left h-full bg-pink-400 scale-x-0"></div></div><!-- 动画盒子1 --><divclass="scroll-box w-32 h-32 bg-pink-400 fixed top-20 left-20 rounded-lg shadow-lg"></div><!-- 动画盒子2 --><divclass="scroll-box2 w-32 h-32 bg-blue-400 fixed top-60 left-60 rounded-lg shadow-lg"></div><!-- 渐显文字 --><divclass="scroll-text fixed top-[300px] left-1/2 -translate-x-1/2 w-[600px] text-3xl text-gray-700 opacity-0"><p>分段动画、弹性、渐变、旋转、缩放、透明度,全部联动!</p><p class="mt-10 text-xl">继续滚动,体验更丰富的滚动动画效果。</p></div><!-- 内容填充 --><divclass="absolute top-[700px] left-1/2 -translate-x-1/2 w-[600px] text-xl text-gray-700"><p>你可以继续添加更多动画元素,或根据滚动区间分段控制动画效果。</p></div></div>
</template>
SVG 动画效果
<script setup>
import { ref, onMounted } from "vue";
import anime from "animejs";const pathRef = ref(null);onMounted(() => {if (pathRef.value) {const length = pathRef.value.getTotalLength();pathRef.value.style.strokeDasharray = length;pathRef.value.style.strokeDashoffset = length;anime({targets: pathRef.value,strokeDashoffset: [length, 0],duration: 2000,easing: "easeOutCubic",});}
});
</script><template><div class="flex flex-col items-center mt-10"><svg width="320" height="120" viewBox="0 0 320 120"><pathref="pathRef"d="M20,60 Q160,10 300,60 T300,110"stroke="#f472b6"stroke-width="6"fill="none"/></svg><p class="mt-4 text-lg text-gray-700">SVG 路径描边动画</p></div>
</template>
Vue3 Anime.js超级炫酷的网页动画库详解 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿技术分享