vue封装gsap自定义动画指令

1、指令文件封装

javascript 复制代码
import { gsap } from 'gsap';

// 动画类型配置
const ANIMATION_TYPES = {
    // 缩放
	scale: {
		from: { scale: 0.5, opacity: 0 },
		to: { scale: 1, opacity: 1 },
		hide: { scale: 0.5, opacity: 0 },
	},
    // 透明度
	fade: {
		from: { opacity: 0 },
		to: { opacity: 1, ease: 'sine.out' },
		hide: { opacity: 0, ease: 'sine.in' },
	},
    // 向上滑出
	slideUp: {
		from: { y: 50, opacity: 0 },
		to: { y: 0, opacity: 1, ease: 'power2.out' },
		hide: { y: 50, opacity: 0, ease: 'power2.in' },
	},
    // 向下滑出
	slideDown: {
		from: { y: -50, opacity: 0 },
		to: { y: 0, opacity: 1, ease: 'power2.out' },
		hide: { y: -50, opacity: 0, ease: 'power2.in' },
	},
    // 向左滑出
	slideLeft: {
		from: { x: 50, opacity: 0 },
		to: { x: 0, opacity: 1, ease: 'power2.out' },
		hide: { x: 50, opacity: 0, ease: 'power2.in' },
	},
    // 向右滑出
	slideRight: {
		from: { x: -50, opacity: 0 },
		to: { x: 0, opacity: 1, ease: 'power2.out' },
		hide: { x: -50, opacity: 0, ease: 'power2.in' },
	},
    // 弹窗
	bounce: {
		from: { y: -100, opacity: 0 },
		to: {
			y: 0,
			opacity: 1,
			ease: 'bounce.out',
			duration: 1.5,
		},
		hide: {
			y: 100,
			opacity: 0,
			ease: 'power2.in',
			duration: 0.5,
		},
	},
    // 翻转折叠
	flip: {
		from: { rotationY: 90, opacity: 0 },
		to: { rotationY: 0, opacity: 1, ease: 'power2.out' },
		hide: { rotationY: -90, opacity: 0, ease: 'power2.in' },
	},
};

// 默认配置
const DEFAULT_CONFIG = {
	type: 'scale',
	duration: 0.3,
	delay: 0,
	origin: 'center',
	onComplete: null,
	onStart: null,
};

export const vGsapAnimation = {
	mounted(el, binding) {
		// 合并默认配置和绑定值
		const config = {
			...DEFAULT_CONFIG,
			...(typeof binding.value === 'object' ? binding.value : { value: binding.value }),
		};

		// 获取动画配置
		const animationConfig = ANIMATION_TYPES[config.type] || ANIMATION_TYPES.scale;

		// 设置变换原点
		el.style.transformOrigin = config.origin;
		el.style.willChange = 'transform, opacity';

		// 保存配置到元素
		el._gsapConfig = config;

		// 初始化动画时间轴
		el._gsapTimeline = gsap.timeline({
			paused: true,
			onComplete: config.onComplete,
			onStart: config.onStart,
		});

		// 创建显示动画
		el._gsapTimeline.fromTo(el, animationConfig.from, {
			...animationConfig.to,
			duration: config.duration,
			delay: config.delay,
		});

		// 初始状态
		if (config.value !== false) {
			el.style.visibility = 'visible';
			el._gsapTimeline.play();
		} else {
			el.style.visibility = 'hidden';
			gsap.set(el, animationConfig.from);
		}
	},

	updated(el, binding) {
		const oldConfig = el._gsapConfig;
		const newConfig = {
			...DEFAULT_CONFIG,
			...(typeof binding.value === 'object' ? binding.value : { value: binding.value }),
		};

		// 如果配置有变化
		if (JSON.stringify(oldConfig) !== JSON.stringify(newConfig)) {
			// 更新配置
			el._gsapConfig = newConfig;

			// 获取动画配置
			const animationConfig = ANIMATION_TYPES[newConfig.type] || ANIMATION_TYPES.scale;

			// 更新时间轴回调
			el._gsapTimeline.eventCallback('onComplete', newConfig.onComplete);
			el._gsapTimeline.eventCallback('onStart', newConfig.onStart);

			if (newConfig.value !== oldConfig?.value) {
				if (newConfig.value === false) {
					// 隐藏动画
					gsap.to(el, {
						...animationConfig.hide,
						duration: newConfig.duration,
						delay: newConfig.delay,
						onComplete: () => {
							el.style.visibility = 'hidden';
						},
					});
				} else {
					// 显示动画
					el.style.visibility = 'visible';
					el._gsapTimeline.restart();
				}
			}
		}
	},

	unmounted(el) {
		// 清理动画
		if (el._gsapTimeline) {
			el._gsapTimeline.kill();
		}
	},
};

2、main.ts注册

javascript 复制代码
// 引入文件
import { vGsapAnimation } from 'xxx'

// 注册指令
app.directive('gsap', vGsapAnimation)

3、使用

  • 基本使用
html 复制代码
<div v-gsap="isVisible">内容</div>
  • 指定动画类型
html 复制代码
<div v-gsap="{ type: 'fade', value: isVisible }">内容</div>
  • 完整配
html 复制代码
<div v-gsap="{
  type: 'bounce',
  value: isVisible,
  duration: 1,
  delay: 0.2,
  origin: 'top left',
  onComplete: handleComplete
}">内容</div>
相关推荐
sophie旭1 分钟前
一道面试题,开始性能优化之旅(5)-- 浏览器和性能
前端·面试·性能优化
lypzcgf9 分钟前
Coze源码分析-资源库-编辑知识库-前端源码-核心组件
前端·知识库·coze·coze源码分析·智能体平台·ai应用平台·agent平台
小墨宝12 分钟前
web前端学习 langchain
前端·学习·langchain
北城以北888817 分钟前
Vue--Vue基础(一)
前端·javascript·vue.js
IT_陈寒1 小时前
Python 3.12新特性实战:5个让你的代码提速30%的性能优化技巧
前端·人工智能·后端
sniper_fandc1 小时前
Vue Router路由
前端·javascript·vue.js
excel1 小时前
为什么 Vue 组件中的 data 必须是一个函数?(含 Vue2/3 对比)
前端
妄小闲2 小时前
成品网站模板源码 网站源码模板 html源码下载
前端·html
知识分享小能手10 小时前
微信小程序入门学习教程,从入门到精通,微信小程序常用API(上)——知识点详解 + 案例实战(4)
前端·javascript·学习·微信小程序·小程序·html5·微信开放平台
清灵xmf10 小时前
CSS field-sizing 让表单「活」起来
前端·css·field-sizing