在wepy搭建的小程序中实现贝塞尔曲线

381 阅读2分钟

小程序项目要求实现一个贝塞尔曲线的效果,网上搜了一下,是有算法代码的,然鹅都是原生的小程序,然后鼓弄了一番,终于可以在wepy搭建的小程序上跑起来了。话不多说,直接上

  1. 在app.wpy中定义screenSize函数,用户获取屏幕宽高
    screenSize () {
        var that = this
        wx.getSystemInfo({
          success: function (res) {
            var ww = res.windowWidth
            var hh = res.windowHeight
            that.globalData.ww = ww
            that.globalData.hh = hh
          }
        })
    }

    // 在onLaunch钩子里调用
    onLaunch() {
        this.screenSize()
        this.testAsync()
      }
  1. 在app.wpy中定义贝塞尔函数
    bezier (points, part) {
        let sx = points[0]['x']
        let sy = points[0]['y']
        let cx = points[1]['x']
        let cy = points[1]['y']
        let ex = points[2]['x']
        let ey = points[2]['y']
        var bezierPoints = []
        // 起始点到控制点的x和y每次的增量
        var changeX1 = (cx - sx) / part
        var changeY1 = (cy - sy) / part
        // 控制点到结束点的x和y每次的增量
        var changeX2 = (ex - cx) / part
        var changeY2 = (ey - cy) / part
        // 循环计算
        for (var i = 0; i <= part; i++) {
          // 计算两个动点的坐标
          var qx1 = sx + changeX1 * i
          var qy1 = sy + changeY1 * i
          var qx2 = cx + changeX2 * i
          var qy2 = cy + changeY2 * i
          // 计算得到此时的一个贝塞尔曲线上的点
          var lastX = qx1 + (qx2 - qx1) * i / part
          var lastY = qy1 + (qy2 - qy1) * i / part
          // 保存点坐标
          var point = {}
          point['x'] = lastX
          point['y'] = lastY
          bezierPoints.push(point)
        }
        // console.log(bezierPoints)
        return {
          'bezierPoints': bezierPoints
        }
    }
  1. data对象中的数据
data = {
    hide_good_box: true,  // 隐藏运动的元素
    bus_x: 370,           // 移动球的x坐标
    bus_y: 300,           // 移动球的y坐标
    finger: {},           // 手指点点击位置
    busPos: {},           // 购物车位置
    timer: null,          // 定时器  
    linePos: null         // 移动球运动轨迹
  }
  1. onLoad时定义购物车的位置
async onLoad () {
    // 购物车坐标
    this.busPos = {}
    this.busPos['x'] = this.$parent.globalData.ww - 90
    this.busPos['y'] = this.$parent.globalData.hh - 60
}
  1. 在template中定义小球元素
    <!-- 抛物线小球 -->
    <view class="good_box" hidden="{{hide_good_box}}" style="left: {{bus_x}}px; top: {{bus_y}}px;">
    </view>
  1. 一般通过点击事件调用
    // 点触屏幕
    touchOnGoods(e) {
        // 如果good_box正在运动
        if (!this.hide_good_box) return
        this.finger = {}
        var topPoint = {}
        this.finger['x'] = e.touches['0'].clientX
        this.finger['y'] = e.touches['0'].clientY
        this.$apply()
        if (this.finger['y'] < this.busPos['y']) {
          topPoint['y'] = this.finger['y'] - 150
        } else {
          topPoint['y'] = this.busPos['y'] - 150
        }
        topPoint['x'] = Math.abs(this.finger['x'] - this.busPos['x']) / 2
        if (this.finger['x'] > this.busPos['x']) {
          topPoint['x'] = (this.finger['x'] - this.busPos['x']) / 2 + this.busPos['x']
        } else {
          topPoint['x'] = (this.busPos['x'] - this.finger['x']) / 2 + this.finger['x']
        }
        this.linePos = this.$parent.bezier([this.finger, topPoint, this.busPos], 20)
        this.startAnimation()
    }
    
      // 加入购物车动画开始
      startAnimation(e) {
        var index = 0
        var that = this
        var bezierPoints = that.linePos['bezierPoints']
        var len = bezierPoints.length - 1
    
        that.hide_good_box = false
        that.bus_x = that.finger['x']
        that.bus_y = that.finger['y']
        that.$apply()
    
        this.timer = setInterval(function () {
          index++
    
          that.bus_x = bezierPoints[index]['x']
          that.bus_y = bezierPoints[index]['y']
          that.$apply()
    
          if (index >= len) {
            clearInterval(that.timer)
            that.hide_good_box = true
            that.$apply()
          }
        }, 20)
    }
  1. 最后效果
    结果