更新记录

1.0.6(2025-01-09) 下载此版本

优化组件

1.0.5(2025-01-09) 下载此版本

修复vue项目中使用兼容问题

1.0.4(2024-07-29) 下载此版本

修复一些文案错误

查看更多

平台兼容性

uni-app

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ √ √ - - - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ - - - - - - √ - - - -

hbxw-nine-square-grid-lottery组件

介绍

自定义宫格抽奖组件,支持完全自定义UI

组件提供默认九宫格UI,但考虑到形形色色的抽奖UI需求,抽奖UI支持完全自定义

考虑到网络请求需要一定的时间,所以组件留出了最小转圈数等待你设置抽奖奖品,在最小圈数的时候如果已经拿到抽奖奖品,会走最后一圈的奖品定位,如果没有拿到奖品则会继续走下去,直到转到最大圈数报抽奖失败。

使用示例

推荐先直接复制示例代码到工程中看效果了解下使用方法再投入项目使用。


<template>
    <view class="container">
    <text class="title">标准使用</text>
        <hbxw-nine-square-grid-lottery 
      :list="list"
      :luckPrice="luckPrice"
      :luckyCount="luckyCount"
      @luckEnd="luckEnd" 
      @luckStart="luckStartFn" 
    />

    <text class="title">自定义UI0</text>
        <hbxw-nine-square-grid-lottery 
      :list="list0" 
      :isStart="startLuck" 
      :luckPrice="luckPrice0"
      :luckyCount="luckyCount"
      @luckEnd="luckEnd"
    >
      <template #default="{activePriceIndex}">
        <view class="luck-container">
          <view class="luck-item" v-for="(item, index) in list0" :key="item.id" :class="{active: index === activePriceIndex}">
            <view class="luck-img-wrap">
              <image class="luck-item-img" mode="widthFix" :src="item.img" :alt="item.name" />
            </view>
            <text class="luck-item-title">{{item.name}}</text>
          </view>
          <button @click="startLuckFn" :disabled="startLuck">点击抽奖,当前可抽奖次数{{luckyCount}}</button>
        </view>
      </template>
    </hbxw-nine-square-grid-lottery>

    <text class="title">自定义UI1</text>
    <hbxw-nine-square-grid-lottery 
      :list="list" 
      :isStart="startLuck1" 
      :luckPrice="luckPrice1"
      :luckyCount="luckyCount"
      @luckEnd="luckEnd"
    >
      <template #default="{ prizeList, activeId }">
        <view class="luck-container">
          <template v-for="(item, index) in prizeList" :key="item.id">
            <view class="tresure-chest" v-if="item.id === -1" @click="startLuckFn1">
              <view class="tresure-chest-con">
                <text class="tresure-chest-title">{{item.name}}</text>
                <text class="tresure-chest-content">剩余次数: {{luckyCount}}</text>
              </view>
            </view>
            <view v-else class="luck-item" :class="{active: item.id === activeId}">
              <view class="luck-img-wrap">
                <image class="luck-item-img" mode="widthFix" :src="item.img" :alt="item.name" />
              </view>
              <text class="luck-item-title">{{item.name}}</text>
            </view>
          </template>
        </view>
      </template>
    </hbxw-nine-square-grid-lottery>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                list: [
          {
            img: 'https://placehold.jp/999999/ffffff/300x500.png?text=奖品图1',
            name: '我是长奖品测一测省略1',
            priceId: 1,
            id: 1
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图2',
            name: '奖品2',
            priceId: 2,
            id: 2
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图3',
            name: '奖品3',
            priceId: 3,
            id: 3
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图4',
            name: '奖品4',
            priceId: 4,
            id: 4
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图5',
            name: '奖品5',
            priceId: 5,
            id: 5
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图6',
            name: '奖品6',
            priceId: 6,
            id: 6
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图7',
            name: '奖品7',
            priceId: 7,
            id: 7
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图8',
            name: '奖品8',
            priceId: 8,
            id: 8
          }
        ],
        list0: [
          {
            img: 'https://placehold.jp/999999/ffffff/300x500.png?text=奖品图1',
            name: '我是长奖品测一测省略1',
            priceId: 1,
            id: 1
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图2',
            name: '奖品2',
            priceId: 2,
            id: 2
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图3',
            name: '奖品3',
            priceId: 3,
            id: 3
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图4',
            name: '奖品4',
            priceId: 4,
            id: 4
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图5',
            name: '奖品5',
            priceId: 5,
            id: 5
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图6',
            name: '奖品6',
            priceId: 6,
            id: 6
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图7',
            name: '奖品7',
            priceId: 7,
            id: 7
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图8',
            name: '奖品8',
            priceId: 8,
            id: 8
          }, {
            img: 'https://placehold.jp/999999/ffffff/300x300.png?text=奖品图9',
            name: '奖品9',
            priceId: 9,
            id: 9
          }
        ],
        luckyCount: 3,
        startLuck: false,
        luckPrice: null,
        luckPrice0: null,
        startLuck1: false,
        luckPrice1: null
            }
        },
        methods: {
      luckStartFn() {
        console.log('---- luckStartFn  ----:抽奖开始');
        setTimeout(() => {
          this.luckPrice = this.list[3];
        }, 1000)
      },

      startLuckFn() {
        this.startLuck = true;
        setTimeout(() => {
          this.luckPrice0 = this.list[4];
        })
      },
      startLuckFn1() {
        this.startLuck1 = true;
        setTimeout(() => {
          this.luckPrice1 = this.list[4];
        })
      },
      luckEnd(e) {
        console.log('---- luckend  ----:', e);
        // 表示抽奖成功了
        if (e.status === 'ok') {
          this.luckyCount -= 1;
        }
        if (e.result) {
          uni.showToast({
            icon: 'none',
            title: `当前中奖奖品:${e.result.name}`
          })
        } else {
          if (e.luckyCount <= 0) {
            uni.showToast({
              icon: 'none',
              title: '暂无抽奖次数'
            })
          }
        }
        // 抽完奖要置位,以用于下次触发抽奖
        setTimeout(() => {
          this.startLuck = false;
          this.startLuck1 = false;
          e.reset && e.reset();
        }, 1000);
      }
        }
    }
</script>

<style lang="scss" scoped>
.container{
  overflow: hidden;
  min-height: 100vh;
  background-color: green;
}
.title{
  font-size: 32rpx;
  margin: 20rpx 10rpx;
  color: white;
}

// 自定义样式
.luck-container{
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  flex-wrap: wrap;
  padding: 20rpx;
}
.luck-item {
    width: 226rpx;
    height: 226rpx;
    flex: none;
    padding: 10rpx 15rpx;
    margin-bottom: 10rpx;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    background-color: #F6F8FA;
    border-radius: 20rpx;
    border: 2px solid transparent;
    &.active{
      background-color: #D3E9FF;
      border: 2px solid #2964E6;
    }
    .luck-item-title{
      width: 100%;
      text-align: center;
      font-size: 24rpx;
      line-height: 36rpx;
      overflow: hidden;
      flex: none;
      text-overflow: ellipsis;
      white-space: nowrap;
      color: #A08866;
    }
    .luck-img-wrap{
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      flex: 1;
      overflow: hidden;
    }
    .luck-item-img{
      width: 100%;
    }
}

.tresure-chest {
    width: 226rpx;
    height: 226rpx;
    border-radius: 20rpx;
    overflow: hidden;
    cursor: pointer;
    position: relative;
    background-color: #2964E6;
    background-image: linear-gradient(-61deg, #2964E6, #4C93FF);
    .tresure-chest-con{
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      position: relative;
      z-index: 2;
      font-size: 45rpx;
      font-weight: bold;
      color: #fff;
    }
    .tresure-chest-content{
      font-size: 30rpx;
      color: #FFFFFF;
    }
    .tresure-chest-title{
      font-size: 42rpx;
      font-weight: bold;
      margin-bottom: 20rpx;
      color: #FFFFFF;
    }
}
</style>

API

Props

属性名 类型 默认值 必填 说明
list Array null 是 当前要抽奖数据
speed Number 100 否 切换一格的时间间隔
speedLast Number 300 否 最后一圈切换一格的时间间隔,一般会speed的慢,制作紧张感
circleMin Number 2 否 至少转多少圈,到了这个圈数后面的每一圈都会检查是否设置了中奖奖品数据
circleMax Number 5 否 最多转多少圈,转到这个圈数如果发现还没有检查到中奖奖品数据,即判定为抽奖失败
isStart Boolean false 否 用于自定义UI的情触发抽奖转盘,如果用默认UI,该参数不需要用
luckPrice Object null 是 当前中奖数据
luckyCount Number 0 是 当前可抽奖次数
btnText String 点击抽奖 否 当前抽奖按钮上文案
luckStyle Object 抽奖容器样式 否 抽奖容器样式,最小成本实现自定义UI
itemStyle Object 抽奖项样式 否 抽奖项样式,最小成本实现自定义UI
itemActiveStyle Object 抽奖项高亮样式 否 抽奖项高亮样式,最小成本实现自定义UI
itemTextStyle Object 抽奖项文本样式 否 抽奖项文本样式,最小成本实现自定义UI
itemTextActiveStyle Object 抽奖项文本亮亮样式 否 抽奖项文本亮亮样式,最小成本实现自定义UI
btnStyle Object 抽奖按钮样式 否 抽奖按钮样式,最小成本实现自定义UI
btnDisableStyle Object 抽奖按钮禁用样式 否 禁用状态下抽奖按钮样式,最小成本实现自定义UI
btnTitleStyle Object 抽奖按钮主文本样式 否 抽奖按钮主文本样式,最小成本实现自定义UI
btnDisableTitleStyle Object 抽奖禁用下按钮主文本样式 否 抽奖禁用下按钮主文本样式,最小成本实现自定义UI
btnSubTitleStyle Object 抽奖按钮次主文本样式 否 抽奖按钮次主文本样式,最小成本实现自定义UI
btnDisableSubTitleStyle Object 抽奖禁用下按钮次要文本样式 否 抽奖禁用下按钮次要文本样式,最小成本实现自定义UI
isDisabled Boolean 抽奖禁用 否 禁用抽奖,主动设置为true或者当前抽奖次数为0都会进入抽奖禁用状态

Event

事件名 说明 返回值
luckStart 抽奖开始触发的事件,主要是给使用默认UI用的,用于外面触发抽奖接口获取抽奖奖品 无
luckEnd 抽奖结束触发的事件 抽奖结果对象{ result: 抽奖结果, luckyCount: 当前抽奖余下的次数, status: 抽奖状态 ok成功/error失败, reset: 抽奖重置方法爆露,用于外面重置抽奖 }

注:包体积显示994kb,是因为有二张示例图片,真正会打包到项目中的体积是只有10k左右

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT协议