美文网首页微信小程序开发
微信小程序营销之大转盘(二)

微信小程序营销之大转盘(二)

作者: IT实战联盟咖啡 | 来源:发表于2018-06-22 13:59 被阅读0次

    前言

    大转盘营销活动大家应该都不陌生那如何用小程序实现呢?
    第一个版本的大转盘都是用图片做的,奖品等信息都是不无法修改的,说白了就是没啥实际用途,作者我就直接用canvas撸了一个全手工绘制的大转盘分享给大家。此处应有掌声 : )

    效果图

    因为gif动态效果图实在是太大了,就截取了两张图片给大家看

    项目结构

    运行流程

    • 获取所有奖品列表
    • 绘制指针和转盘
    • 绑定指针区域点击事件
    • 点击指针开始转动
    • 请求后端获取抽中的奖品
    • 调用大转盘停止方法把奖品传进去
    • 大转盘停止转动
    • 展示奖品和信息

    关键代码

    绘制大转盘和绑定指针点击事件

     // 启用事件
        point.inputEvent = true;
        point.onInputDown = run;
    // 更新动画
        var update = function () {
          // 清空
          context.clearRect(0, 0, w, h);
          // 画转盘
          wheel.draw(context);
          // 画指针
          point.draw(context);
    
          // 更新数据
          animation.draw(context);
          // 更新数据
          animation.update();
    
          // 获取手指点击
          var touch = that.data.touch;
          if (point.inputEvent && touch.isPressed && point.onInputDown) {
            // 如果点击到了指针
            if (point.contains(touch)) {
              // 调用点击回调方法
              point.onInputDown();
            }
          }
    
          // 绘图   
          context.draw()
    
        };
        setInterval(update, 1000 / fps, 1000 / fps);
    

    点击指针之后的回调处理
    使用setTimeout 模拟后端返回结果
    使用stopTo 方法来让大转盘停止到某一个奖品

     // 开始转
        function run() {
          // 避免重复调用
          if (animation.isRun) return;
          // 当动画完成时
          animation.onComplete = function (prize) {
            wx.showToast({
              image: prize.img,
              title: prize.text,
              duration: 3000,
              mask: true,
            })
          };
    
          // 开始转
          animation.run();
    
          // 模拟后台返回数据
          setTimeout(function () {
            // 随机一个奖品
            var prizeIndex = utils.getRandom(slicePrizes.length - 1);
            // 计算奖品角度
            animation.stopTo(prizeIndex);
          }, 3000);
        }
    

    转动处理的构造方法

    function Animation(circle, screen) {
      this.circle = circle;
      this.screen = screen;
      // 角速度
      this.speed = 0;
      // 最大速度
      this.maxSpeed = 10;
      // 摩擦力
      this.friction = 0.98;
      // 加速度
      this.acceleration = 0.5;
      // 是否开始运行
      this.isRun = false;
      // 圈数
      this.rounds = 5;
      // 角度
      this.degrees = 0;
      // 当前角度
      this.angle = -90;
      // 开始减速
      this.speedDown = false;
      // 开始加速
      this.speedUp = true;
      // 顺时针还是逆时针
      this.anticlockwise = false;
      // 完成
      this.onComplete = null;
      // debug
      this.isDebug = false;
    }
    

    转动效果,先加速》匀速一段时间》调用stopTo方法后》减速》停止

    
    Animation.prototype.update = function () {
      if (this.isRun) {
        // 到达奖品区
        var isJoin = this.prize && this.angle > this.minAngle && this.angle < this.maxAngle;
        // 是否要减速
        if (isJoin) {
          this.speedDown = true;
        }
    
        // 是否要停止加速
        if (this.speed >= this.maxSpeed) {
          this.speedUp = false;
        }
    
        // 加速
        if (this.speedUp) {
          this.speed += this.acceleration;
        }
    
        // 减速
        if (this.speedDown) {
          if (this.speed <= 2 && isJoin) {
            this.isRun = false;
            this.speed = 0;
            if (this.onComplete) this.onComplete(this.prize);
          } else if (this.speed <= 1) {
            this.speed = 1;
          } else {
            this.speed *= this.friction;
          }
        }
    
        this.angle += this.speed;
        // 转动角度
        if (Math.abs(this.angle) > 360) {
          this.angle -= 360;
        }
        // 旋转方向
        if (this.anticlockwise) {
          this.circle.rotation += (Math.PI / 180) * this.speed;
        } else {
          this.circle.rotation -= (Math.PI / 180) * this.speed;
        }
      }
    };
    

    大转盘的绘制

    
    Circle.prototype.draw = function (context) {
      // 保存
      context.save();
      // 移动到圆心
      context.translate(this.x, this.y);
      // 旋转
      context.rotate(this.rotation);
      // 缩放
      // context.scale(this.scaleX, this.scaleY);
    
      if (this.img) {
        var imgX = -this.width / 2;
        var imgY = -this.height / 2;
        context.drawImage(this.img, imgX, imgY);
      }
      var colors = this.colors;
      var size = this.size;
      var angle = this.angle;
    
      var r = this.radius;
    
      // 画扇形
      for (var i = 0; i < size; i++) {
        context.beginPath()
        context.moveTo(0, 0)
        context.arc(0, 0, r, 0, angle * Math.PI / 180)
        context.setFillStyle(colors[i % colors.length])
        context.fill()
        context.rotate(angle * Math.PI / 180);
      }
    
      // 画图案
      // 计算圆上任意一点
      var offset = this.radius / 2;
      var offsetA = angle / 2;
      var offsetX = Math.cos(offsetA * Math.PI / 180) * offset;
      var offsetY = Math.sin(offsetA * Math.PI / 180) * offset;
      for (var i = 0; i < size; i++) {
        var prize = this.slicePrizes[i]
        context.save();
    
        context.translate(offsetX, offsetY);
    
        context.rotate((180 - ((180 - angle) / 2)) * Math.PI / 180);
        context.drawImage(prize.img, -10, -30, this.prizeWidth, this.prizeHeight);
    
        // 写文字
        context.setFontSize(this.prizeFontSize)
        context.setFillStyle(this.prizeFontStyle)
        context.textAlign = "center";
        context.fillText(prize.text, 0, (offset - 25) * -1)
    
        // 话圆点参考
        // context.beginPath()
        // context.arc(0, 0, 2, 0, 2 * Math.PI)
        // context.setFillStyle('red')
        // context.fill()
    
        context.restore()
        context.rotate(angle * Math.PI / 180);
      }
    
      // 还原
      context.restore();
    };
    

    指针和跑马灯的绘制

    
    Circle.prototype.draw = function (context) {
      // 保存
      context.save();
      // 移动到圆心
      context.translate(this.x, this.y);
      // 旋转
      context.rotate(this.rotation);
      // 缩放
      // context.scale(this.scaleX, this.scaleY);
    
      if (this.img) {
        var imgX = -this.width / 2;
        var imgY = -this.height / 2;
        context.drawImage(this.img, imgX, imgY);
      }
    
      // 指针
      context.beginPath()
      context.setFillStyle('#ffffff')
      context.moveTo(0, (this.radius + 50) * -1);
      context.lineTo(-10, 0);
      context.lineTo(10, 0);
      context.fill()
    
      // 圆盘
      context.beginPath()
      context.setFillStyle('#ffffff')
      context.arc(0, 0, this.radius, 0, 2 * Math.PI)
      context.fill()
    
      // 文字
      context.setFontSize(30)
      context.setFillStyle('#ff2244')
      context.setTextAlign("center");
      context.fillText('抽奖', 0, 10)
    
      var r = this.wheel.radius;
      // 跑马灯外框  F6D000  FFA200
      context.beginPath()
      context.setLineWidth(15);
      context.setStrokeStyle("#FFA200")
      context.arc(0, 0, r + 20, 0, 2 * Math.PI)
      context.stroke()
    
      // 跑马灯内框 F6D000
      context.beginPath()
      context.setLineWidth(10);
      context.setStrokeStyle("#F6D000")
      context.arc(0, 0, r + 8, 0, 2 * Math.PI)
      context.stroke()
    
      // 跑马灯灯  
      for (var i = 0; i < 32; i++) {
        context.beginPath()
        context.setFillStyle(i % 2 == 0 ? "#ffffff" : "#FF403A")
        context.arc(r + 20, 0, 4, 0, 2 * Math.PI)
        context.fill()
        context.rotate((360 / 32) * Math.PI / 180);
      }
      // 还原
      context.restore();
    };
    

    完整代码

    GitHub 地址: https://github.com/qiaohhgz/bigwheel-miniapp

    关注我们

    IT实战联盟是集产品、UI设计、前后端、架构、大数据和AI人工智能等为一体的实战交流服务平台!联盟嘉宾都为各互联网公司项目的核心成员,联盟主旨是“让实战更简单”,欢迎来撩~~~

    我们的网站: http://100boot.cn

    相关文章

      网友评论

        本文标题:微信小程序营销之大转盘(二)

        本文链接:https://www.haomeiwen.com/subject/qlrasftx.html