vue3 element-plus gsap
获取动画起止点
element plus中 这样写会构造一个选择器列
js
<el-table-column type="selection"/>
选中事件为@select 参数1是当前选中的所有行 参数2是变化的行(选中或没选中) 并不能得到用户点击的位置信息
因此这里需要一点小寄巧 在另一个表格列加入一个用于定位的元素
xml
<el-table-column>
<template v-slot="{ row }">
<span class="hidden" :id="row.id"></span>
<!-- 其他列的正常内容 -->
</template>
</el-table-column>
然后可以通过被点击行的id 取得用户点击的那个checkbox
js
document.querySelector(
`.el-table__row:has(>.el-table__cell>.cell>#${id})>td:first-child .el-checkbox`,
)
需要注意的是querySelector需要一个合法的css选择器
一些id会导致css选择器非法 例如useId生成的id :S1:
动画终点dom通过ref获得即可
创建动画
首先需要一个临时创建dom的函数
在这篇文章的基础上 为contanier增加z-index 确保动画能覆盖在所有dom上面
js
import { createVNode, render } from 'vue'
/** 命令式临时渲染一个组件 */
export const tempRender = (comp, ...args) => {
const container = document.createElement('div')
container.style.position = 'fixed'
container.style.zIndex = '9999'
document.body.append(container)
const dialogNode = createVNode(comp, { ...args })
render(dialogNode, container)
function destory () {
render(null, container)
container.remove()
}
return destory
}
然后就可以用gsap创建动画
先在main.js注册插件
js
import gsap from 'gsap'
import MotionPathPlugin from 'gsap/MotionPathPlugin'
gsap.registerPlugin(MotionPathPlugin)
然后实际创建动画
js
async function startAnime (id) {
const startDom = //
const endDom = //
const { top: startTop, left: startLeft } = getCenterPosition(startDom)
const { top: endTop, left: endLeft } = getCenterPosition(endDom)
const animePointId = `__animePoint${Date.now()}`
const duration = 0.8 // 秒
const bezier = 'cubic-bezier(0.30, 1.00, 0.80, 1.20)'
const path = getPath(startTop, startLeft, endTop, endLeft, bezier)
const [d, bg] = ['1rem', '#6f65cc']
const destory = tempRender('div', {
id: animePointId,
class: 'fixed rounded-full',
style: `top:${startTop}px;left:${startLeft}px;width:${d};height:${d};background-color:${bg};`,
})
const animePoint = document.querySelector(`#${animePointId}`)
await gsap.to(animePoint, { motionPath: path, duration, ease: 'power1.in' })
destory()
await gsap.to(endDom, { scale: 1.2, duration: 0.15 })
await gsap.to(endDom, { scale: 1, duration: 0.1 })
}
/**
* 获取一个dom的左上角相对html的位置
* @param {HTMLElement} dom
*/
function getCenterPosition (dom) {
const { top, left } = dom.getBoundingClientRect()
const { scrollX, scrollY } = window
return {
top: top + scrollX,
left: left + scrollY,
}
}
/**
* 根据起止点缩放贝塞尔曲线
*/
function getPath (startTop, startLeft, endTop, endLeft, bezier) {
const x = endLeft - startLeft
const y = endTop - startTop
const [x1, y1, x2, y2] = bezier
.match(/cubic-bezier\((.*)\)/)[1]
.split(/\s?,\s?/)
.map(Number)
return `M0,0 C${x1 * x},${y1 * y} ${x2 * x},${y2 * y} ${x},${y}`
}
实际效果就是淘宝、美团加入购物车的那个动画 小球抛出 然后按钮闪一下
理论上需要构造抛物线 但是实现需要x平移 y按上抛变化 比较麻烦
所以用贝塞尔曲线模拟一下就行了 反正差不多
cubic-bezier.tupulin.com/ 这个网站可以直接把调试贝塞尔曲线