这是一个微信小程序九宫格抽奖页面的完整代码,包括 WXML、WXSS、JS 和 JSON。

效果

九宫格抽奖

功能说明:

  1. 静态页面布局: 3x3 九宫格,中间是“立即抽奖”按钮,周围是奖品金额。
  2. 抽奖动画: 点击“立即抽奖”后,九宫格会动态跑马灯式高亮显示,最终停留在中奖项。
  3. 中奖提示: 抽奖结束后弹出中奖结果。

1. lottery.json (页面配置)

{"navigationBarTitleText": "九宫格抽奖","usingComponents": {}
}

2. lottery.wxml (页面结构)

<view class="container"><view class="lottery-grid"><block wx:for="{{gridItems}}" wx:key="id"><viewclass="lottery-item {{item.isButton ? 'lottery-btn' : ''}} {{item.active ? 'active' : ''}}"data-index="{{item.id}}"bindtap="{{item.isButton ? 'startLottery' : ''}}"><text>{{item.text}}</text></view></block></view>
</view>

3. lottery.wxss (页面样式)

/* container */
.container {display: flex;justify-content: center;align-items: center;min-height: 100vh; /* 撑满整个屏幕高度 */background-color: #f8f8f8;padding: 20rpx;box-sizing: border-box;
}/* 九宫格容器 */
.lottery-grid {display: grid;grid-template-columns: repeat(3, 1fr); /* 3列,每列等宽 */gap: 15rpx; /* 格子之间的间距 */width: 700rpx; /* 九宫格总宽度 */background-color: #fff;border-radius: 20rpx;padding: 15rpx;box-shadow: 0 5rpx 20rpx rgba(0, 0, 0, 0.1);
}/* 抽奖格子公共样式 */
.lottery-item {width: 100%; /* 充满父容器的宽度 */height: 200rpx; /* 高度 */display: flex;justify-content: center;align-items: center;background-color: #fdfdfd;border: 4rpx solid #ffd700; /* 金色边框 */border-radius: 15rpx;font-size: 36rpx;font-weight: bold;color: #333;transition: all 0.1s ease; /* 动画过渡效果 */box-sizing: border-box; /* 边框和内边距不撑大元素 */
}/* 中间抽奖按钮样式 */
.lottery-btn {background-color: #ffda47; /* 醒目的黄色 */color: #d84e27; /* 红色字体 */font-size: 40rpx;border-color: #f77026; /* 橙色边框 */box-shadow: 0 4rpx 8rpx rgba(255, 165, 0, 0.4);cursor: pointer;
}/* 激活(高亮)状态样式 */
.lottery-item.active {background-color: #ff4d4f; /* 红色高亮 */color: #fff;border-color: #ff0000;transform: scale(1.03); /* 稍微放大 */box-shadow: 0 0 20rpx rgba(255, 77, 79, 0.8);
}/* 按钮禁用状态(抽奖进行中) */
.lottery-btn[disabled] {opacity: 0.7;cursor: not-allowed;background-color: #ccc;border-color: #aaa;
}

4. lottery.js (页面逻辑)

Page({data: {// 九宫格数据// id: 格子索引 (0-8)// text: 显示的文本// isButton: 是否是抽奖按钮 (中间格子)// active: 是否是当前高亮格子gridItems: [],// 抽奖相关状态currentIndex: -1,     // 当前高亮的格子索引isDrawing: false,     // 是否正在抽奖timer: null,          // 抽奖定时器speed: 200,           // 初始转动速度 (ms)minSpeed: 50,         // 最快转动速度 (ms)drawCount: 0,         // 已经转动的次数totalRounds: 3,       // 至少转动多少圈 (影响动画时长)finalPrizeIndex: -1,  // 最终中奖的格子索引accelerateSteps: 10,  // 加速阶段的步数decelerateSteps: 10,  // 减速阶段的步数// 抽奖路径 (按顺时针方向,跳过中间按钮4)// 0 1 2// 7 X 3  (X是中间按钮4)// 6 5 4lotteryPath: [0, 1, 2, 5, 8, 7, 6, 3],},onLoad: function () {this.initGridItems();},/*** 初始化九宫格数据*/initGridItems: function () {const initialGridData = [{ id: 0, text: '5元' },{ id: 1, text: '8元' },{ id: 2, text: '10元' },{ id: 3, text: '90元' }, // 注意这个位置,对应抽奖路径{ id: 4, text: '立即抽奖', isButton: true }, // 中间按钮{ id: 5, text: '20元' }, // 注意这个位置,对应抽奖路径{ id: 6, text: '50元' },{ id: 7, text: '40元' },{ id: 8, text: '30元' }];const gridItems = initialGridData.map(item => ({...item,active: false,isButton: item.isButton || false // 确保 isButton 属性存在}));this.setData({gridItems: gridItems});},/*** 获取下一个高亮的格子索引*/getNextLotteryIndex: function (currentPathIndex) {const { lotteryPath } = this.data;return (currentPathIndex + 1) % lotteryPath.length;},/*** 开始抽奖*/startLottery: function () {if (this.data.isDrawing) {wx.showToast({title: '正在抽奖中...',icon: 'none'});return;}this.setData({isDrawing: true,drawCount: 0,speed: 200, // 恢复初始速度});// 清除上次的定时器,避免重复if (this.data.timer) {clearTimeout(this.data.timer);}// 模拟抽奖结果,这里排除中间按钮(index 4)const prizePoolIndexes = this.data.lotteryPath; // 只有周围的8个格子能中奖const randomIndexInPool = Math.floor(Math.random() * prizePoolIndexes.length);const finalPrizeIndex = prizePoolIndexes[randomIndexInPool];console.log("最终中奖格子索引 (在 lotteryPath 中的位置):", randomIndexInPool);console.log("最终中奖格子在 gridItems 中的实际ID:", finalPrizeIndex);this.setData({finalPrizeIndex: finalPrizeIndex,currentIndex: this.data.lotteryPath[0] // 初始从第一个格子开始}, () => {// 确保 finalPrizeIndex 设置后再启动动画this.runLottery();});},/*** 运行抽奖动画*/runLottery: function () {let { gridItems, currentIndex, drawCount, speed, minSpeed,finalPrizeIndex, lotteryPath, totalRounds, accelerateSteps, decelerateSteps } = this.data;// 清除上一个高亮if (currentIndex !== -1) {let oldGridItems = gridItems;const oldIndexInPath = lotteryPath.indexOf(currentIndex);oldGridItems[lotteryPath[oldIndexInPath]].active = false;this.setData({ gridItems: oldGridItems });}// 计算下一个高亮索引const currentPathIndex = lotteryPath.indexOf(currentIndex);const nextPathIndex = this.getNextLotteryIndex(currentPathIndex);const nextActualIndex = lotteryPath[nextPathIndex];// 更新高亮gridItems[nextActualIndex].active = true;this.setData({gridItems: gridItems,currentIndex: nextActualIndex,drawCount: drawCount + 1});// 计算总的转动步数,确保至少转totalRounds圈 + 停到中奖位置// 假设 finalPrizeIndex 是在 lotteryPath 中的实际索引const prizePathIndex = lotteryPath.indexOf(finalPrizeIndex);const minRunSteps = lotteryPath.length * totalRounds + prizePathIndex + 1; // 至少转的步数// 速度控制let newSpeed = speed;if (drawCount < accelerateSteps) { // 加速阶段newSpeed = Math.max(minSpeed, speed - (speed - minSpeed) / accelerateSteps * drawCount);} else if (drawCount >= minRunSteps - decelerateSteps && drawCount < minRunSteps) { // 减速阶段newSpeed = Math.min(200, speed + (200 - minSpeed) / decelerateSteps);} else if (drawCount >= minRunSteps) { // 减速到最终结果,确保最终速度不会太快newSpeed = Math.min(newSpeed + 30, 400); // 逐渐变慢}// 检查是否停止const isStop = drawCount >= minRunSteps && currentIndex === finalPrizeIndex;if (isStop) {clearTimeout(this.data.timer);this.setData({isDrawing: false,timer: null});wx.showModal({title: '恭喜!',content: '您抽中了' + gridItems[finalPrizeIndex].text + '!',showCancel: false,confirmText: '确定'});} else {this.setData({ speed: newSpeed });this.data.timer = setTimeout(() => this.runLottery(), newSpeed);}},onUnload: function() {// 页面卸载时清除定时器,避免内存泄漏if (this.data.timer) {clearTimeout(this.data.timer);this.setData({ timer: null });}}
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96700.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96700.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/96700.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java类冲突

一、为什么会发生类冲突&#xff1f; 在 Java 的类加载机制中&#xff0c;类的唯一性是由“类加载器类的全限定名”共同决定的。当你的项目依赖了多个 jar 包&#xff0c;这些 jar 包里有同名的类&#xff08;包名和类名完全一样&#xff09;&#xff0c;但实现却不同。类加载器…

GIT客户端配置支持中文

环境&#xff1a;windows10、Git-2.42.0.2-64-bit.exe1. 问题描述客户端安装后&#xff0c;默认是不支持中文显示的&#xff0c;中文名的文件显示乱码&#xff0c;提交时打的标签内容也不支持中文显示。2. 解决新建Git全局配置文件&#xff0c;文件名为.gitconfig&#xff0c;内…

Teable vs NocoDB 开源、在线协同 多维表格大PK

文章目录 Teable 简介 特性 docker-compose部署 功能截图 NocoDB 简介 docker-compose部署 功能截图 总结 Teable 简介 Teable 是一款企业级高性能多维表格解决方案,通过无代码方式快速构建业务管理系统,支持私有部署和精细权限管理。 官方文档 特性 🚀 卓越性能 轻松处…

SQL专家云能做哪些事儿?

背景数据库是信息化的基石&#xff0c;支撑着整个业务系统&#xff0c;发挥着非常重要的作用&#xff0c;被喻为“IT的心脏”。因此&#xff0c;让数据库安全、稳定、高效地运行已经成为IT管理者必须要面对的问题。但是很多组织没有专业的DBA&#xff0c;数据库运维面临着极大的…

Python 高效实现 Word 转 PDF:告别 Office 依赖

在工作中&#xff0c;经常会遇到需要把 Word 文档转换成 PDF 的情况。比如生成报表、分发文档、或者做归档保存&#xff0c;PDF 格式在排版和跨平台显示上更稳定。传统的做法往往依赖 Microsoft Office 或 LibreOffice 等软件来完成转换&#xff0c;但在自动化环境&#xff08;…

SQL优化简单思路

1. 背景 在实际生产中&#xff0c;因为SQL较慢、SQL关联不合理、不了解索引的性质、不熟悉mysql执行计划分析&#xff0c;可能会出现一些生产事故&#xff0c;本文会简单说明SQL通常的优化分析思路。 基本的优化原则&#xff1a; 先优化SQL再优化mysql server最后优化硬件 2. 优…

软考 系统架构设计师系列知识点之杂项集萃(144)

接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(143) 第268题 甲、乙、丙、丁4人加工A、B、C、D四种工件所需工时如下表所示。指派每人加工一种工件,四人加工四种工件其总工时最短的最优方案中,工件B应由()加工。 A B C D 甲

P1168 中位数

题目描述给定一个长度为 N 的非负整数序列 A&#xff0c;对于前奇数项求中位数。输入格式第一行一个正整数 N。第二行 N 个正整数 A1…N​。输出格式共 ⌊2N1​⌋ 行&#xff0c;第 i 行为 A1…2i−1​ 的中位数。输入输出样例输入 #1复制7 1 3 5 7 9 11 6输出 #11 3 5 6输入 #…

【CE】图形化CE游戏教程通关手册

【CE】图形化CE游戏教程通关手册 文章目录【CE】图形化CE游戏教程通关手册导读需求1️⃣ 第一关提示操作总结2️⃣ 第二关&#xff08;代码共享&#xff09;提示操作验证3️⃣ 第三关提示提示总结导读 需求 除了Tutorial-x86_64.exe教程外&#xff0c;CE还提供了图形化教程gtu…

leetcode 2785. 将字符串中的元音字母排序 中等

给你一个下标从 0 开始的字符串 s &#xff0c;将 s 中的元素重新 排列 得到新的字符串 t &#xff0c;它满足&#xff1a;所有辅音字母都在原来的位置上。更正式的&#xff0c;如果满足 0 < i < s.length 的下标 i 处的 s[i] 是个辅音字母&#xff0c;那么 t[i] s[i] 。…

支付子系统架构及常见问题

支付流程对于支付系统来说&#xff0c;它最重要的其实是安全&#xff0c;所以整个支付流程采用秘钥加签的方式进行操作&#xff0c;一共四对秘钥&#xff0c;以支付宝在线支付为例子&#xff0c;首先通过RSA2算法生成商户公钥以及商户私钥&#xff0c;同时支付宝平台会提供支付…

内存传输速率MT/s

1 0 0 0 0 0 0 0 0 010 9 8 7 6 5 4 3 2 1十 亿 千 百 十 万 千 百 十 个亿 万 万 万传输速率 …

.env文件的作用和使用方法

目录 什么是 .env 文件&#xff1f; 为什么要使用 .env 文件&#xff1f;&#xff08;好处&#xff09; 如何使用 .env 文件&#xff1f; 通用步骤&#xff1a; 具体技术栈中的实现&#xff1a; 最佳实践和注意事项 总结 什么是 .env 文件&#xff1f; .env 文件&#x…

深度拆解 Python 装饰器参数传递:从装饰器生效到参数转交的每一步

在 Python 装饰器的学习中&#xff0c;“被装饰函数的参数如何传递到装饰器内层函数”是一个高频疑问点。很多开发者能写出装饰器的基本结构&#xff0c;却对参数传递的底层逻辑一知半解。本文将以一段具体代码为例&#xff0c;把参数传递过程拆成“装饰器生效→调用触发→参数…

【Vue2 ✨】Vue2 入门之旅 · 进阶篇(七):Vue Router 原理解析

在前几篇文章中&#xff0c;我们介绍了 Vue 的性能优化机制、组件缓存等内容。本篇将深入解析 Vue Router 的原理&#xff0c;了解 Vue 如何管理路由并进行导航。 目录 Vue Router 的基本概念路由模式&#xff1a;hash 和 history路由匹配原理导航守卫Vue Router 的路由过渡动…

Linux磁盘级文件/文件系统理解

Linux磁盘级文件/文件系统理解 1. 磁盘的物理结构 磁盘的核心是一个利用磁性介质和机械运动进行数据读写的、非易失性的存储设备。 1.1 盘片 盘片是传统机械硬盘中最核心的部件&#xff0c;它是数据存储的物理载体。盘片是一个坚硬的、表面极度光滑的圆形碟片&#xff0c;被安装…

【星海出品】rabbitMQ - 叁 应用篇

rabbitMQ 的基础知识这里就不阐述了,可以参看我早年写的文章 -> rabbitMQ 入门 https://blog.csdn.net/weixin_41997073/article/details/118724779 Celery 官网:http://www.celeryproject.org/ Celery 官方文档英文版:http://docs.celeryproject.org/en/latest/index.h…

C# 每个chartArea显示最小值、平均值、最大值

private void AddStatisticsAnnotations(ChartArea chartArea, int channelIndex) {RemoveExistingAnnotations(channelIndex);// 获取ChartArea的相对坐标&#xff08;百分比&#xff09;float chartAreaX chartArea.Position.X; // X坐标&#xff08;百分比&#xff09;floa…

打破“不可能三角”:WALL-OSS开源,具身智能迎来“安卓时刻”?

目录 引言&#xff1a;当“大脑”学会思考&#xff0c;机器人才能走出实验室 一、具身智能的“不可能三角”&#xff1a;机器人“大脑”的核心困境 二、WALL-OSS的四把重锤&#xff1a;如何系统性地破解难题&#xff1f; 2.1 第一锤&#xff1a;更聪明的“大脑”架构 —— …

SigNoz分布式追踪新体验:cpolar实现远程微服务监控

前言 SigNoz是一款开源的应用性能监控工具&#xff0c;专为微服务架构设计&#xff0c;集成了指标、追踪和日志分析功能。它能够全面监控分布式系统的性能&#xff0c;帮助开发团队快速定位问题根源。SigNoz支持OpenTelemetry协议&#xff0c;可以无缝集成各种编程语言和框架&…