• 贝赛尔曲线 - Vue3实现加入购物车抛物线效果组件


    贝赛尔曲线 - Vue3实现加入购物车抛物线效果组件(可连续多个动画,动态回收DOM)

    前言

    在前几天的一次迭代中,我遇到了这么一个需求,模仿支付宝首页应用中心的编辑功能,支持编辑首页展示的应用,在支付宝应用首页编辑功能中,我注意到一种独特而细致的设计。无论是增加还是移除某个应用,都会引发一个精美的移动动画效果。这种贴心的设计在用户体验中起到了微妙而关键的作用,使得操作更加流畅,为整个过程增添了趣味性。不由地想起我们在使用各种购物外卖软件时,添加商品到购物车也有这么一个抛物线的动画效果。因此,决定手动造轮子,封装一个通用的抛物线组件。该组件已开源上传npm,可以直接安装使用,源码已上传Git,地址在文尾。

    贝赛尔曲线

    贝塞尔曲线(Bezier curve)是应用于二维图形应用程序的数学曲线,在矢量图形软件中,贝塞尔曲线被广泛用于精确画出曲线,它也是计算机图形学中相当重要的参数曲线。

    CSS中的贝塞尔曲线主要应用在动画和过渡中,可以使用cubic-bezier函数来创建自定义动画的速度曲线。使用transition-timing-function和animation-timing-function属性来定义贝塞尔曲线,这个函数接收四个参数,cubic-bezier(n,n,n,n),这四个点定义了一条贝塞尔曲线,其中n是一个0到1之间的数值。CSS提供了几个预定义的函数:ease, linear, ease-in, ease-out, ease-in-out。

    实现思路

    了解了Css中的贝赛尔曲线使用方法后,我们实现一个抛物线也就简单了,只用控制一个dom节点,在x轴和y轴上分别用不同的过度动画效果,改变dom节点left和top的位置,这样就能得到一个抛物线运动轨迹的动画效果了。在运动结束后我们将operaty设为0以达到动画结束隐藏节点。

    优化
    但是在实际使用时,如果我们不断地创造节点增加动画效果,那么就会有无数个dom节点冗余,大大降低了浏览器性能,因此,在动画结束还需要考虑回收dom,将不需要的dom节点移除,这样就大功告成,具体实现请看代码。

    主要实现代码

    1、定义一个基础dom结构,用slot以支持自定义不同的动画节点

    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、执行动画效果处理,将dom移动到起点,执行动画到末点,并在动画结束后销毁节点

    //开始执行动画
    const start = (point: any, time = 1, xcubic = 'linear', ycubic = 'ease-in') => {
        const nowTime = new Date().getTime();
        //新增一个动画节点
        ballList.value.push(nowTime);
        //dom渲染后增加动画效果
        nextTick(() => {
            const ele = ballRef.value[nowTime];
            ele.style.left = `${point.x1}px`;
            ele.style.top = `${point.y1}px`;
            ele.style.opacity = 1;
            setTimeout(() => {
                ele.style.left = `${point.x2}px`;
                ele.style.top = `${point.y2}px`;
                ele.style.transition = `left ${time}s ${xcubic}, top ${time}s ${ycubic}`;
            })
            setTimeout(() => {
                ele.style.opacity = 0;
                ele.style.left = `${point.x1}px`;
                ele.style.top = `${point.y1}px`;
                //动画结束回收dom
                removeDom(nowTime);
            }, time * 1000)
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    3、保留每个Dom引用,移除dom

    //将循环ref放入到数组中
    const setRefAction = (el: any, item: number) => {
        ballRef.value[item] = el;
    }
    
    //动画结束回收dom
    const removeDom = (nowTime: number) => {
        ballList.value = ballList.value.filter((item: number) => {
            return item != nowTime;
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    使用示例

    npm install @fcli/vue-cubic-bezier --save-dev 来安装
    
    在项目中使用
    import VueCubicBezier from '@fcli/vue-cubic-bezier';
    const app=createApp(App)
    app.use(VueCubicBezier);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    示例:

    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    参数说明

    使用时需要调用该组件的start方法,并传对应参数即可实现一个自定义抛物线,具体使用可以参考代码示例。

    属性属性名称类型可选值
    point起点和结束点距离左上角的距离,(x1,y1)起点坐标,(x2,y2)结束点坐标object{ x1: 250, y1: 50, x2: 100, y2: 400 }
    time动画效果过渡时间number1
    xcubic横向过渡贝赛尔动画参数numberlinear
    ycubic竖向过渡贝赛尔动画参数numberease-in

    slot
    可自定义动画的图标或者内容

    Git地址:https://gitee.com/fcli/vue-cubic-bezier.git

  • 相关阅读:
    Docker(1)
    LeetCode(力扣)216. 组合总和 IIIPython
    接口技术:总线部分练习题(PCI配置空间)
    基于Dijkstra和A*算法的机器人路径规划(Matlab代码实现)
    折腾一晚上的事情,明白了一个道理
    Java转义工具类StringEscapeUtils的学习笔记
    大一新生HTML期末作业 个人网页王嘉尔明星介绍网页设计与制作
    【科研新手指南3】chatgpt辅助论文优化表达
    #力扣:125. 验证回文串@FDDLC
    公司动态 | 月圆人团圆,联诚发与你相伴实现每一个圆满
  • 原文地址:https://blog.csdn.net/qq_34185872/article/details/133175109