微信小程序加入购物车动画

*人狠话不多,直接代码搞起*

点击github下载小demo,可以直接运行看效果,了解二次贝塞尔曲线的可以自己玩。

小程序加入购物车动画效果:点击商品,出现一个小的商品图,呈现曲线(贝塞尔曲线/抛物线)飞向购物车的图标里。

1


app.js

	  onLaunch: function (){
		 this.screenSize()
	  },
	  screenSize: function () {
	    var that = this;
	    wx.getSystemInfo({
	      success: function (res) {
	        //可视窗口宽度
	        var ww = res.windowWidth;
	        //可视窗口高度
	        var hh = res.windowHeight;
	        that.globalData.ww = ww;
	        that.globalData.hh = hh;
	      }
	    })
	  },
	
	  bezier: function (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
	    };
	  },

index.wxml

	  <!-- 购物车图标 和 角标数字-->
	  <view class="bus">
		    <image src="../../images/shopCart.png"></image>
		    <view class="count" hidden="{{hideCount}}">{{count}}</view>
	  </view>
	  <!-- 加购物车时飞的图片 -->
	  <view class="good_box" hidden="{{hide_good_box}}"  style="left: {{bus_x}}px; top: {{bus_y}}px;">
	    	<image src="{{feiBox}}"></image>
	  </view>

index.wxss

	.bus {
	    position: fixed;
	    left: 85%;
	    top: 85%;
	    background: #fff;
	    border-radius: 50%;
	}
	
	.bus image {
	    width: 62px;
	    height: 62px;
	    position: absolute;
	    left: 50%;
	    top: 50%;
	    margin: -4px;
	}
	
	.count {
	    display: block;
	    width: 20px;
	    height: 20px;
	    line-height: 20px;
	    text-align: center;
	    font-size: 12px;
	    background: #ff4611;
	    border-radius: 10px;
	    color: #fff;
	    position: absolute;
	    left: 34px;
	    top: 0;
	}
	
	.scale {
	    background: rgba(120, 188, 255, 0.3);
	    border: 1px solid rgba(0, 116, 255, 0.4);
	}
	
	.scale image {
	    transform: scale(1.2);
	}
	
	.good_box {
	    width: 40px;
	    height: 40px;
	    position: fixed;
	    border-radius: 50%;
	    overflow: hidden;
	    left: 50%;
	    top: 50%;
	    z-index: +99;
	    border: 1px solid #fff;
	    background: rgba(120, 188, 255, 0.2);
	}
	
	.good_box image {
	    display: block;
	    width: 100%;
	    height: 100%;
	}


index.js

	data:{
	 	hideCount: true, //角标初始是隐藏的
        count: 0, //角标数
        hide_good_box: true,
        feiBox: ""
	},
	onLoad: function() {
        //可视窗口x,y坐标
        this.busPos = {};
        this.busPos['x'] = app.globalData.ww * .85;
        this.busPos['y'] = app.globalData.hh * .85;
    },

    //点击商品触发的事件
    touchOnGoods: function(e) {
        //把点击每一项的对应的商品图保存下来,就是飞向购物车的图片
        this.setData({
            feiBox: this.data.imgUrls[e.currentTarget.dataset.idx]
        })
        // 如果good_box正在运动
        if (!this.data.hide_good_box) return;
        //当前点击位置的x,y坐标
        this.finger = {};
        var topPoint = {};
        this.finger['x'] = e.touches["0"].clientX;
        this.finger['y'] = e.touches["0"].clientY - 20;
        if (this.finger['y'] < this.busPos['y']) {
            topPoint['y'] = this.finger['y'] - 150;
        } else {
            topPoint['y'] = this.busPos['y'] - 150;
        }

        if (this.finger['x'] < this.busPos['x']) {
            topPoint['x'] = Math.abs(this.finger['x'] - this.busPos['x']) / 2 + this.finger['x'];
        } else {
            topPoint['x'] = this.busPos['x'];
            this.finger['x'] = this.busPos['x']
        }


        this.linePos = app.bezier([this.finger, topPoint, this.busPos], 30);
        this.startAnimation();

    },
    //开始动画
    startAnimation: function() {
        var index = 0,
            that = this,
            bezier_points = that.linePos['bezier_points'];
        this.setData({
            hide_good_box: false,
            bus_x: that.finger['x'],
            bus_y: that.finger['y']
        })
        this.timer = setInterval(function() {
            index++;
            that.setData({
                bus_x: bezier_points[index]['x'],
                bus_y: bezier_points[index]['y']
            })
            if (index >= 28) {
                clearInterval(that.timer);
                that.setData({
                    hide_good_box: true,
                    hideCount: false,
                    count: that.data.count += 1
                })
            }
        }, 33);
    }
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐