实现"选中表格项将元素加入集合"的动画效果

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/ 这个网站可以直接把调试贝塞尔曲线

相关推荐
jay神15 分钟前
【计算机毕业设计】基于Flask+Vue的电影数据可视化与智能推荐系统
前端·vue.js·python·信息可视化·flask·毕业设计·课程设计
海兰7 小时前
【应用】基于 Next.js 16 + Python mplfinance的金融K线图与技术指标可视化平台(三)
javascript·python·金融
小磊哥er9 小时前
深入解构Claude Code - 第 7 篇 · 连接外面的世界
javascript·ai编程
小磊哥er9 小时前
深入解构Claude Code - 第 6 篇 · 终端里的图形界面
javascript·ai编程
海兰9 小时前
【应用】基于 Next.js 16 + Python mplfinance的金融K线图与技术指标可视化平台(一)
javascript·python·金融
可乐鸡翅yeah_10 小时前
hls.js 内存泄漏实战排查,直播 M3U8 长时间播放异常定位方案
开发语言·javascript·python·django·ecmascript·m3u8·m3u8在线
可乐鸡翅yeah_11 小时前
第三方接口对接 M3U8 流媒体排坑实战,解决外部服务商流兼容难题
前端·javascript·python·django·html·m3u8·m3u8在线
默_笙11 小时前
🏠 「LLM Notes」:我用 Next.js + Redis 给自己造了个笔记博客
前端·javascript
ruanCat13 小时前
Prettier 明明执行成功,Markdown 为什么还是没变?一次插件误诊复盘
前端·javascript·node.js
软件开发技术深度爱好者13 小时前
在线学习实践 TypeScript 的官方Playground(演练场)使用介绍
javascript·学习·typescript