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

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

相关推荐
海底火旺20 分钟前
JavaScript中的Object方法完全指南:从基础到高级应用
前端·javascript·面试
海底火旺21 分钟前
JavaScript中的Symbol:解锁对象属性的新维度
前端·javascript·面试
天天扭码21 分钟前
一文吃透 ES6新特性——解构语法
前端·javascript·面试
JustHappy24 分钟前
啥是Hooks?为啥要用Hooks?Hooks该怎么用?像是Vue中的什么?React Hooks的使用姿势(上)
前端·vue.js·react.js
培根芝士1 小时前
electron-updater实现自动更新
javascript·electron
海天胜景1 小时前
vue3 el-table 右击
javascript·vue.js·elementui
Mercury-circle1 小时前
JavaScript基础知识合集笔记1——数据类型
开发语言·javascript·笔记
樊小肆2 小时前
Vue3 在线 PDF 编辑 2.0 缩放拖拽、渲染优化功能解析
前端·vue.js·开源
一天睡25小时2 小时前
视频HLS分片与关键帧优化深度解析
前端·javascript
Java~~2 小时前
山东大学软件学院项目实训-基于大模型的模拟面试系统-网页图片显示问题
javascript·vue.js