加入购物车动画(贝塞尔曲线)

2021-12-10  本文已影响0人  怯言ouo

index.vue

<template>
        //五个小球循环使用,可连续点击
        <view class="cart-item-elc" :style="{item..left+'px',item..top+'px'}" v-show="item.isCartIcon" :key="index" v-for="(item,index) in carIconList "></view>
</template>

<script>
    import utils from "../../static/js/utils";
    var carIconData=uni.getStorageSync('carIconData')
    var carIconIndex=0
    export default {
        data(){
            return {
               carIconList : [
                  {isAnimate: true,isCartIcon: false, timer: null,left: 0, top: 0, bezierPos: null},
                  {isAnimate: true,isCartIcon: false, timer: null,left: 0, top: 0, bezierPos : null},
                  {isAnimate: true, isCartIcon: false, timer: null,left: 0, top: 0, bezierPos : null},
                  {isAnimate: true,isCartIcon: false, timer : null,left: 0, top: 0, bezierPos : null},
                  {isAnimate: true,isCartIcon: false, timer: null,left: 0,top: 0, bezierPos : null}
                ]
            }
        },
        onshow(){
           //isEmpty是一个判断非空的函数
            if (utils.isEmpty(cartlconData)){
                //count是购物车的class类名,计算购物车的坐标
                 uni.createSelectorQuery().select(".count").boundingClientRect(res =>{
                    cartIconData= [res.left, res.top]
                    uni.setStorageSync('cartIconData', cartIconData)
                }).exec()
            }
        },
        methods:{
            //加入增加数量并加入购物车
            incAmount(e,index,index2,gid){
               if (carIconindex == 5) {
                  carIconIndex = 1
              } else {
                  carIconIndex++
              }
              var index = carIconIndex - 1
              this.carIconList[index].left = e.detail.x; 
              this.carIconList[index].top = e.detail.y;
              this.carIconList[index].bezierPos = util.bezier([{
                x: this.carIconList[index].left, y: this.carIconList[index].top}, { x: this.carIconList[index].left - 100, y: 120 },{x: carticonData[o],y: cartIconData[1]}], 8);
              this.carIconList[index].isCartIcon = true; 
              this.startAnimation(index);
            },
            //开始动画
            startAnimation(){
               let bezier_points = this.carIconList[index].bezierPos['bezier_points']; let indexs = 0;
               this.cartIconAni = true
               this.carIconList[index].timer = setInterval(() => {
                    indexs++;
                    this.carIconList[index].left = bezier_points[indexs]["x"];             
                    this.carIconList[index].top = bezier_points[indexs]["y"];
                  //动画完成
                  if (indexs >= 7) {
                     clearInterval(this.carIconList[index].timer);                 
                     this.carIconList[index].isAnimate = true;
                     this.carIconList[index].isCartIcon = false;
                     this.cartIconAni = false
                  }
               }, 8)
            },
        }
    }
</script>

<style scoped>
    .cart-item-elc{width:20rpx;height:20rpx;background-color:#ff2400;position:absolute;left:0px;top:0px;border-radius: 100%;z-index:100;}
</style>


utils.js


function bezier(points, times){
    // 0、以3个控制点为例,点A,B,C,AB上设置点D,BC上设置点E,DE连线上设置点F,则最终的贝塞尔曲线是点F的坐标轨迹。
    // 1、计算相邻控制点间距。
    // 2、根据完成时间,计算每次执行时D在AB方向上移动的距离,E在BC方向上移动的距离。
    // 3、时间每递增100ms,则D,E在指定方向上发生位移, F在DE上的位移则可通过AD/AB = DF/DE得出。
    // 4、根据DE的正余弦值和DE的值计算出F的坐标。
    // 邻控制AB点间距
    var bezier_points = [];
    var points_D = [];
    var points_E = [];
    const DIST_AB = Math.sqrt(Math.pow(points[1]['x'] - points[0]['x'], 2) + Math.pow(points[1]['y'] - points[0]['y'], 2));
    // 邻控制BC点间距
    const DIST_BC = Math.sqrt(Math.pow(points[2]['x'] - points[1]['x'], 2) + Math.pow(points[2]['y'] - points[1]['y'], 2));
    // D每次在AB方向上移动的距离
    const EACH_MOVE_AD = -(DIST_AB / times);
    // E每次在BC方向上移动的距离
    const EACH_MOVE_BE = -(DIST_BC / times);
    // 点AB的正切
    const TAN_AB = (points[1]['y'] - points[0]['y']) / (points[1]['x'] - points[0]['x']);
    // 点BC的正切
    const TAN_BC = (points[2]['y'] - points[1]['y']) / (points[2]['x'] - points[1]['x']);
    // 点AB的弧度值
    const RADIUS_AB = Math.atan(TAN_AB);
    // 点BC的弧度值
    const RADIUS_BC = Math.atan(TAN_BC);
    // 每次执行
    for (var i = 1; i <= times; i++) {
        // AD的距离
        var dist_AD = EACH_MOVE_AD * i;
        // BE的距离
        var dist_BE = EACH_MOVE_BE * i;
        // D点的坐标
        var point_D = {};
        point_D['x'] = dist_AD * Math.cos(RADIUS_AB) + points[0]['x'];
        point_D['y'] = dist_AD * Math.sin(RADIUS_AB) + points[0]['y'];
        points_D.push(point_D);
        // E点的坐标
        var point_E = {};
        point_E['x'] = dist_BE * Math.cos(RADIUS_BC) + points[1]['x'];
        point_E['y'] = dist_BE * Math.sin(RADIUS_BC) + points[1]['y'];
        points_E.push(point_E);
        // 此时线段DE的正切值
        var tan_DE = (point_E['y'] - point_D['y']) / (point_E['x'] - point_D['x']);
        // tan_DE的弧度值
        var radius_DE = Math.atan(tan_DE);
        // 地市DE的间距
        var dist_DE = Math.sqrt(Math.pow((point_E['x'] - point_D['x']), 2) + Math.pow((point_E['y'] - point_D['y']), 2));
        // 此时DF的距离
        var dist_DF = (dist_AD / DIST_AB) * dist_DE;
        // 此时DF点的坐标
        var point_F = {};
        point_F['x'] = dist_DF * Math.cos(radius_DE) + point_D['x'];
        point_F['y'] = dist_DF * Math.sin(radius_DE) + point_D['y'];
        bezier_points.push(point_F);
    }
    return {
        'bezier_points': bezier_points
    };
}
export default {
    bezier
}
上一篇下一篇

猜你喜欢

热点阅读