animejs
animejs是一个强大的动画库,你肯定之前有所耳闻了;
animejs是一个
纯js库
,她应该怎么在vue3+ts+hook中使用呢?
一、安装
安装animejs和它的类型声明包(否则引入会报错),如果你用的是js那就无需安装,同时下个章节的类型也请忽略;
npm install animejs --save
npm install @types/animejs -D
二、创建类型声明
虽然引入用了@types/animejs 类型声明包,但是个人觉得还是差了点意思,于是自己手动敲一下,CssField是css的类型,另一个就是animejs常用的配置项目;
export type CssField =
| 'translateX'
| 'translateY'
| 'translateZ'
| 'rotate'
| 'rotateX'
| 'rotateY'
| 'rotateZ'
| 'scale'
| 'scaleX'
| 'scaleY'
| 'scaleZ'
| 'skew'
| 'skewX'
| 'skewY'
| 'perspective'
| 'matrix'
| 'matrix3d'
| 'opacity';
export type AnimeParams = {
targets: Ref<HTMLElement | null>;
duration?: number;
delay?: number;
endDelay?: number;
elasticity?: number;
round?: number;
loop?: number;
autoplay?: boolean;
direction?: string;
easing?: anime.EasingOptions;
} & {
[key in CssField]?: any;
};
三、创建hook
类似这种配置多变的hook,我一般会配置一个通用的(满足特殊需求)
,一些常用的(快速使用)
;
useTranslateX(常用的水平移动
)
import anime from 'animejs/lib/anime.es.js';
import { Ref } from 'vue';
const EASING = 'easeInOutQuad';
export function useTranslateX(el: Ref<HTMLElement | null>, from = 0, to = 0, delay = 0, duration = 200, opotion?: AnimeParams) {
onMounted(() => {
anime({
targets: el.value,
translateX: [from, to],
scale: [1.2, 1],
opacity: [0, 1],
duration,
delay,
easing: EASING,
...opotion,
});
});
}
useTranslateY(常用的垂直移动
)
export function useTranslateY(el: Ref<HTMLElement | null>, from = 0, to = 0, delay = 0, duration = 200, opotion?: AnimeParams) {
onMounted(() => {
anime({
targets: el.value,
translateY: [from, to],
scale: [1.2, 1],
opacity: [0, 1],
duration,
delay,
easing: EASING,
...opotion,
});
});
}
useAnime(通用
)
此处有人可能有疑问了,明明opotion有个targets,为什么后面还要重新再赋值一遍?
假如是通过const top = ref<HTMLElement | null>(null)获取的元素;
因为在vue中通过ref获取到的元素类型是Ref<HTMLElement | null>,为了保证其响应式
,传入hook的必须是top,不能是top.value;
如果传入hook的是top.value(失去响应式
),onMounted之前定义的top变量是null,将无法加载动画;
export function useAnime(opotion: AnimeParams) {
onMounted(() => {
anime({
...opotion,
targets: opotion.targets.value,
});
});
}
四、使用
<template>
<div center text-center col-span-6 flex flex-col items-center justify-center text-black h-screen>
<div ref="top" font-500 text-xl> 咨询,测评,价格 </div>
<div ref="middle" text-8xl font-500 text-blue-500 b-blue-500 mt-2> INFORMATION </div>
<div ref="bottom" text-sm font-500 mt-2 text-gray-400> 提供最新汽车报价,汽车图片,汽车价格大全,汽车新闻、行情、评测、导购等内容 </div>
</div>
</template>
<script setup lang="ts">
import { useTranslateX, useTranslateY, useAnime } from '/@/hooks/useAnime';
const top = ref<HTMLElement | null>(null);
const middle = ref<HTMLElement | null>(null);
const bottom = ref<HTMLElement | null>(null);
// useTranslateX(middle, -600, 0, 0, 600);
useTranslateY(top, -60, 0, 600, 200);
useAnime({
targets: middle,
translateX: [-600, 0],
duration: 600,
easing: 'easeInOutQuad',
opacity: [0, 1],
});
useTranslateY(bottom, 60, 0, 600, 200);
</script>