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

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

相关推荐
何何____1 小时前
Vue 生命周期详解
前端·javascript
默_笙2 小时前
💫 闭包是个背包:拆解小米前端面试题里的三道"闭包陷阱"
前端·javascript·面试
老男孩游戏时光4 小时前
Vue3 Composition API 最佳实践,别再乱写 setup 了
vue.js
+VX:Fegn08954 小时前
计算机毕业设计|基于java+ vue共享单车信息系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
尾善爱看海5 小时前
《JavaScript 数组操作全攻略:12 类 API + 30 个实战场景 + 20 个避坑指南》
前端·javascript·面试
Bs_MoneyMagnet5 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
计算机毕设定制辅导-无忧学长5 小时前
《基于SpringBoot的未成年人健康知识科普平台的设计与实现》
java·开发语言·vue.js·spring boot·未成年人健康知识科普平台
OpsEye5 小时前
为什么你的 Agent 莫名烧钱?聊聊循环调用的兜底方案
javascript·ai编程
linux_cfan6 小时前
16 · `custom-media-element`:属性拦截与转发
前端·javascript·音视频
右耳朵猫AI6 小时前
Web前端周刊2026W38 | React 19.3 发布、StyleX 深潜、jsdom 30.1 提速
前端·javascript·react.js·typescript·node.js