小程序版九宫格抽奖

上代码:
axml

<view class="fruit-slots ">
  <view class="title">今日还剩{{isDrawVO.remainingCount||0}}次抽奖机会</view>
  <view class="lt-item-list">
    <block a:for="{{prizeBox}}">
      <view key="{{index}}" class="lt-item {{index === activeIndex ? 'lt-active' : ''}}">
        <image src="{{item.icon}}" mode="widthFix" style="width:100%;height:100%;" />
      </view>
      <!-- <view key="btn" a:if="{{index==3}}" class="lt-item lt-button {{disabled ? 'disabled' : (isRolling ? 'pause' : '')}}" 
        onTap="startClick" /> -->
      <view key="btn" a:if="{{index==3}}" class="lt-item {{disabled ? 'disabled' : (isRolling ? 'pause' : '')}}"
      style="background:url('{{drawBtnImg}}') no-repeat center / cover"
        onTap="startClick" />
    </block>
  </view>
</view>

acss

.lt-item-list {
  margin: 20rpx auto;
  background: url("https://xiaojinhe-cdn.iyoudui.com/activity/lottert-bg.png")
    no-repeat center / 100%;
  width: 702rpx;
  height: 576rpx;
  padding: 20rpx;
  padding-top: 80rpx;
  border-radius: 20rpx;
  box-sizing: border-box;
  /* border: 1rpx solid red; */
}
.fruit-slots {
  /* border: 1rpx solid green; */
  position: relative;
}
.title {
  position: absolute;
  top: 17rpx;
  left: 50%;
  transform: translateX(-50%);
  font-weight: 700;
  font-size: 28rpx;
  line-height: 42rpx;
  color: #fff;
}

.lt-item {
  margin: 16rpx 0 0 16rpx;
  width: 210rpx;
  height: 145rpx;
  padding: 0;
  float: left;
  display: inline-block;
  background-repeat: no-repeat;
  background-position: left top;
  box-sizing: border-box;
  border-radius: 20rpx;
  background-color: #eff1dd;
  overflow: hidden;
}
/* .lt-item:nth-child(1) {
  background-color: #c3ebfa;
}
.lt-item:nth-child(2) {
  background-color: #eff1dd;
}
.lt-item:nth-child(3) {
  background-color: #f1d6dc;
}
.lt-item:nth-child(4) {
  background-color: #f1d6dc;
} */
.lt-item:nth-child(5) {
  background-color: #2683fc;
  border: none;
}
/* .lt-item:nth-child(6) {
  background-color: #c3ebfa;
}
.lt-item:nth-child(7) {
  background-color: #eff1dd;
}
.lt-item:nth-child(8) {
  background-color: #c3ebfa;
}
.lt-item:nth-child(9) {
  background-color: #f1d6dc;
} */
.lt-item:nth-child(1),
.lt-item:nth-child(4),
.lt-item:nth-child(7) {
  margin-left: 0 !important;
}
.lt-item:nth-child(1),
.lt-item:nth-child(2),
.lt-item:nth-child(3) {
  margin-top: 0 !important;
}
.lt-active {
  background-repeat: no-repeat;
  background-position: left top;
  box-sizing: border-box;
  /* filter: contrast(50%); */
  filter: brightness(50%);
}
.lt-button {
  background-repeat: no-repeat;
  background-size: contain;
  background-image: url(https://zos.alipayobjects.com/rmsportal/CNzFiofsxZsEPuzbORIA.png);
}
.lt-button.disabled {
  background-image: url(https://zos.alipayobjects.com/rmsportal/JbBzEiibIXRGxXPRzJIg.png);
}
.lt-button.pause {
  background-image: url(https://zos.alipayobjects.com/rmsportal/eGLmgGZHTDBjtzwhxNkJ.png);
}

js

Component({
  data: {
    activeOrder: [0, 1, 2, 4, 7, 6, 5, 3], // 九宫格除按钮外的8个格子自左上角顺时针的下标顺序
    activeIndex: NaN,
    itemWidth: 0,
    isRolling: false,
  },
  props: {
    width: 700, // 组件宽度,单位 rpx
    margin: 20, // 奖项之间的外边距,单位 rpx
    prizeBox: [], // 奖项列表,个数限定为8
    prizeName: "", // 获奖项名称
    rollTimes: 3, // 转动圈数
    mode: "pre", // 抽奖模式:pre(默认) | realtime
    currentIndex: 0, // 转动开始的下标
    speed: 100, // 转动速度, 单位 ms
    isDrawVO: {},
    drawBtnImg: "",
    disabled: false, // 按钮是否可点击
    onStart: function onStart() {}, // 开始的回调
    onFinish: function onFinish() {}, // 结束的回调
    onClickDraw: () => {},
  },
  didMount: function didMount() {
    this.prizeLength = 8;
    // 必须要取整,否则部分机型下有适配问题
    this.setData({
      itemWidth: parseInt((this.props.width - 4 * this.props.margin) / 3),
    });
  },
  didUpdate: function didUpdate(prevProps) {
    var _props = this.props,
      mode = _props.mode,
      prizeName = _props.prizeName;

    if (mode === "realtime" && prizeName && prevProps.prizeName !== prizeName) {
      var prizeIndex = this.findPrizeIndex(prizeName);
      if (prizeIndex === -1) {
        console.error(
          "请传入正确的获奖项name,其值必须存在于 prizeBox name 字段中"
        );
        return;
      }
      // 总转动步数 = 默认圈数 x 奖品个数 + 结束位置索引 + 当前位置到一圈结束还剩下的步数
      var activeIndex = this.currentStep % this.prizeLength;
      this.totalSteps =
        1 * this.prizeLength +
        this.currentStep +
        (this.prizeLength - activeIndex) +
        prizeIndex;
    }
  },

  methods: {
    next: function next(activeIndex) {
      var _this = this;

      activeIndex = activeIndex % this.prizeLength;
      this.setData({ activeIndex: this.data.activeOrder[activeIndex] });
      if (this.currentStep === this.totalSteps) {
        this.done(activeIndex);
        return;
      }
      this.currentStep += 1;
      setTimeout(function () {
        _this.next(++activeIndex);
      }, this.speedCtl());
    },

    /**
      模拟速度变化,分为四档
      当走过格子数 < 总步数 - 2圈格子数时,速度为speed
      以此线性递增
    */
    speedCtl: function speedCtl() {
      var steps = this.totalSteps;
      var size = this.prizeLength;
      var currentStep = this.currentStep;
      if (currentStep < steps - size * 2) {
        return this.props.speed;
      } else if (
        steps - size * 2 <= currentStep &&
        currentStep <= steps - size
      ) {
        return this.props.speed * 2;
      } else if (steps - currentStep > 3) {
        return this.props.speed * 3;
      } else {
        return this.props.speed * 4;
      }
    },

    /**
      通过名称获取奖品项在顺时针格子中对应的下标
      未找到返回-1
    */
    findPrizeIndex: function findPrizeIndex(name) {
      var prizeBox = this.props.prizeBox;
      var order = this.data.activeOrder;
      for (var i = 0; i < this.prizeLength; i++) {
        if (prizeBox[order[i]].name == name) {
          return i;
        }
      }
      return -1;
    },
    startClick() {
      if (this.props.disabled || this.data.isRolling) return;
      this.props.onClickDraw();
    },
    start: function start(position) {
      var _props2 = this.props,
        disabled = _props2.disabled,
        prizeBox = _props2.prizeBox,
        currentIndex = _props2.currentIndex,
        prizeName = _props2.prizeName,
        mode = _props2.mode;

      if (disabled || this.data.isRolling) return;
      this.currentStep = 0;
      if (prizeBox.length !== 8) {
        console.error("奖品项列表 prizeBox 长度不为8");
      }
      var activeIndex = +currentIndex || 0;
      if (mode === "realtime") {
        this.totalSteps = Infinity;
      } else {
        // 奖品项下标
        var prizeIndex = this.findPrizeIndex(prizeName);
        if (prizeIndex === -1) {
          console.error(
            "请传入正确的获奖项name,其值必须存在于 prizeBox name 字段中"
          );
        }
        // 总转动步数 = 默认圈数 x 奖品个数 + 结束位置索引 + 当前位置到一圈结束还剩下的步数
        this.totalSteps =
          this.props.rollTimes * this.prizeLength +
          prizeIndex +
          (this.prizeLength - activeIndex);
      }
      this.setData({ isRolling: true });
      this.next(activeIndex);
      this.props.onStart(position);
    },
    done: function done(activeIndex) {
      var _this2 = this;

      // setTimeout防止抽奖结束后父组件设置disabled=true的过程中用户马上再次点击抽奖 此时 disabled 和 isRolling
      // 状态还没来得及更新,start 函数可能被执行
      setTimeout(function () {
        _this2.setData({ isRolling: false });
      }, 50);
      this.props.onFinish(activeIndex, this.props.prizeName);
      // 中奖后清除遮罩
      setTimeout(() => {
        this.setData({ activeIndex: NaN });
      }, 1000);
    },
  },
});

html使用

<fruit-slots
    ref="fruitRef"
    mode="realtime"
    prizeBox="{{prizeBox}}"
    prizeName="{{prizeName}}"
    disabled="{{disabled}}"
    isDrawVO="{{isDrawVO}}"
    drawBtnImg="{{drawBtnImg}}"
    rollTimes="3"
    onClickDraw="onClickDraw"
    onStart="onStart"
    onFinish="onFinish"
    speed="50"
  />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C+ 安口木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值