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

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

相关推荐
Thetimezipsby6 分钟前
基于Taro4打造的一款最新版微信小程序、H5的多端开发简单模板
前端·javascript·微信小程序·typescript·html5·taro
BUG创建者24 分钟前
uni 拍照上传拍视频上传以及相册
前端·javascript·音视频
就是帅我不改31 分钟前
敏感词过滤黑科技!SpringBoot+Vue3+TS强强联手,打造无懈可击的内容安全防线
前端·vue.js·后端
菲兹园长1 小时前
CSS(展示效果)
前端·javascript·css
香香甜甜的辣椒炒肉1 小时前
vue(7)-单页应用程序&路由
前端·javascript·vue.js
dreams_dream2 小时前
vue中axios与fetch比较
前端·javascript·vue.js
梦鱼2 小时前
Vue 项目图标一把梭:Iconify 自用小记(含 TS/JS 双版本组件)
前端·javascript·vue.js
给月亮点灯|3 小时前
Vue基础知识-脚手架开发-初始化目录解析
前端·javascript·vue.js
周小码3 小时前
CesiumJS详解:打造专业级Web 3D地球仪与地图的JavaScript库
前端·javascript·3d
哆啦A梦15883 小时前
Element-Plus
前端·vue.js·ts