uniapp + vue 实现色弱测试小游戏
最终的效果:点击色块中不同的色块,跳到下一关
准备一些静态数据,放到js目录下,在vue文件中引入即可
// 在1到比1大的任意整数之间随机取一个整数 export const getRandomIntNum = (maxNum) =>{ return Math.floor(Math.random() * maxNum); } export const seruoDatas = [ { index: 0, blockCount: 4, commonColor: '#3399cc', specialColor: '#0da6f2', specialColor_position: getRandomIntNum(4), style: { width: '160px', height: '160px', border_radius: '10px', box_shadow: '3px 3px 6px #848484' } }, { index: 1, blockCount: 9, commonColor: '#bdcc33', specialColor: '#daf10e', specialColor_position: getRandomIntNum(9), style: { width: '110px', height: '110px', border_radius: '8px', box_shadow: '3px 3px 6px #848484' } }, { index: 2, blockCount: 16, commonColor: '#cc3369', specialColor: '#f00f5e', specialColor_position: getRandomIntNum(16), style: { width: '80px', height: '80px', border_radius: '8px', box_shadow: '3px 3px 6px #848484' } }, { index: 3, blockCount: 25, commonColor: '#6b33cc', specialColor: '#6211ed', specialColor_position: getRandomIntNum(25), style: { width: '65px', height: '65px', border_radius: '8px', box_shadow: '3px 3px 6px #848484' } }, { index: 4, blockCount: 36, commonColor: '#33cb54', specialColor: '#12ed41', specialColor_position: getRandomIntNum(36), style: { width: '55px', height: '55px', border_radius: '8px', box_shadow: '3px 3px 6px #848484' } }, { index: 5, blockCount: 49, commonColor: '#cc4233', specialColor: '#ec2913', specialColor_position: getRandomIntNum(49), style: { width: '48px', height: '48px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 6, blockCount: 64, commonColor: '#3359cc', specialColor: '#144aeb', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 7, blockCount: 64, commonColor: '#cc3378', specialColor: '#e91675', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 8, blockCount: 64, commonColor: '#c733cc', specialColor: '#e117e8', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 9, blockCount: 64, commonColor: '#33cc94', specialColor: '#18e79b', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 10, blockCount: 64, commonColor: '#33ccc7', specialColor: '#19e6df', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 11, blockCount: 64, commonColor: '#33cc8a', specialColor: '#1ae58d', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 12, blockCount: 64, commonColor: '#cc4233', specialColor: '#e42f1b', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 13, blockCount: 64, commonColor: '#7033cc', specialColor: '#6b1be4', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 14, blockCount: 64, commonColor: '#ccb533', specialColor: '#e3c51c', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 15, blockCount: 64, commonColor: '#6133cc', specialColor: '#581de2', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 16, blockCount: 64, commonColor: '#cc6b33', specialColor: '#e2651d', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 17, blockCount: 64, commonColor: '#cc337a', specialColor: '#e11e79', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 18, blockCount: 64, commonColor: '#5e33cc', specialColor: '#561fe0', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 19, blockCount: 64, commonColor: '#cca333', specialColor: '#e0ac1f', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 20, blockCount: 64, commonColor: '#33cc57', specialColor: '#20df4d', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 21, blockCount: 64, commonColor: '#cc3833', specialColor: '#de2721', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 22, blockCount: 64, commonColor: '#33bfcc', specialColor: '#21cede', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 23, blockCount: 64, commonColor: '#cc3345', specialColor: '#dd2238', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 24, blockCount: 64, commonColor: '#ccad33', specialColor: '#ddb722', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 25, blockCount: 64, commonColor: '#33c2cc', specialColor: '#23d0dc', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 26, blockCount: 64, commonColor: '#cc8f33', specialColor: '#db9224', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 27, blockCount: 64, commonColor: '#33a1cc', specialColor: '#33a7db', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 28, blockCount: 64, commonColor: '#cc33c2', specialColor: '#cc24d1', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 29, blockCount: 64, commonColor: '#3373cc', specialColor: '#3370cd', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, { index: 30, blockCount: 64, commonColor: '#7acccc', specialColor: '#7bccca', specialColor_position: getRandomIntNum(64), style: { width: '42px', height: '42px', border_radius: '5px', box_shadow: '2px 2px 4px #848484' } }, ] export const seruoResultText = [ { index: 0, level: 'LV0', text: '无目之眼' }, { index: 1, level: 'LV1', text: '凡胎之眼' }, { index: 2, level: 'LV2', text: '迟钝之眼' }, { index: 3, level: 'LV3', text: '惺忪之眼' }, { index: 4, level: 'LV4', text: '柔情之眼' }, { index: 5, level: 'LV5', text: '慈祥之眼' }, { index: 6, level: 'LV6', text: '专注之眼' }, { index: 7, level: 'LV7', text: '善良之眼' }, { index: 8, level: 'LV8', text: '坚定之眼' }, { index: 9, level: 'LV9', text: '敏锐之眼' }, { index: 10, level: 'LV10', text: '明眸之眼' }, { index: 11, level: 'LV11', text: '不羁之眼' }, { index: 12, level: 'LV12', text: '虎目之眼' }, { index: 13, level: 'LV13', text: '脉脉之眼' }, { index: 14, level: 'LV14', text: '炯炯之眼' }, { index: 15, level: 'LV15', text: '皓月之眼' }, { index: 16, level: 'LV16', text: '犀利之眼' }, { index: 17, level: 'LV17', text: '灼灼之眼' }, { index: 18, level: 'LV18', text: '深沉之眼' }, { index: 19, level: 'LV19', text: '睿智之眼' }, { index: 20, level: 'LV20', text: '深邃之眼' }, { index: 21, level: 'LV21', text: '秋瞳之眼' }, { index: 22, level: 'LV22', text: '先天之眼' }, { index: 23, level: 'LV23', text: '悟空之眼' }, { index: 24, level: 'LV24', text: '金刚之眼' }, { index: 25, level: 'LV25', text: '刑天之眼' }, { index: 26, level: 'LV26', text: '杨戬之眼' }, { index: 27, level: 'LV27', text: '恶魔之眼' }, { index: 28, level: 'LV28', text: '天使之眼' }, { index: 29, level: 'LV29', text: '光之眼' }, { index: 30, level: 'LV30', text: '审判之眼' }, ]
接下来两个vue文件,分别对应两个页面
<template> <view class="bg"> <view class="title"> 色弱小测试 </view> <view class="rules"> 找出所有色块里颜色不同的一个 </view> <view class="start_game"> <button id="btn_start" type="default" @click="startGame">开始</button> </view> </view> </template> <script> export default { data() { return { }; }, onLoad() { // 显示加载中,500毫秒之后消失 this.loading(); }, methods: { // 显示加载中,500毫秒之后消失 loading(){ uni.showLoading({ title: '加载中...', mask: true }) setTimeout(() => { uni.hideLoading(); }, 500) }, // 点击开始按钮开始游戏 startGame(){ uni.navigateTo({ url: '/pages/games/achromatismTestDetail' }) } } } </script> <style lang="less" scoped> @import url('../../static/css/basic.css'); .title { width: 100%; padding-top: 30px; text-align: center; color: #ff557f; font-weight: 600; font-size: 28px; } .rules { width: 100%; margin-top: 50px; text-align: center; color: #c282c2; font-size: 15px; } .start_game { margin-top: 150px; text-align: center; button { width: 150px; height: 65px; color: #f5f5f5; font-size: 25px; font-weight: 600; background-color: #f4517a; box-shadow: 3px 3px 6px #848484; } } </style>
<template> <view class="bg_red"> <view class="title"> 色弱小测试 </view> <view class="game_main"> <view class="time_score"> <view class="time"> <text>时间:</text> <text>{{countdown}}</text> </view> <view class="score"> <text>得分:</text> <text>{{score}}</text> </view> </view> <view class="color_block_main"> <view :style="{'background-color': (index == dataObject.specialColor_position ? dataObject.specialColor : dataObject.commonColor), 'width': dataObject.style.width, 'height': dataObject.style.height, 'border-radius': dataObject.style.border_radius, 'box-shadow': dataObject.style.box_shadow}" v-for="(item,index) in dataObject.blockCount" :key="index" @click="clickSpecial(index)"> </view> </view> </view> <!-- 遮罩层 --> <view class="countdown_end_mask" v-show="resultShow"> <view class="title_success"> 测试成功 </view> <view class="success_content"> <view class="success_content_top"> <text class="success_content_text">{{resultObject.text}}: </text> <text class="success_content_level">{{resultObject.level}}</text> </view> <view class="success_content_bottom"> <uni-icons type="home-filled" size="30" class="home" @click="toHomePage"></uni-icons> <button size="30" @click="reRestart" class="restart_btn">再来一次</button> <button class="redo" open-type="share" @click="toShare"> <uni-icons type="redo" size="30"></uni-icons> </button> </view> </view> </view> </view> </template> <script> import { seruoDatas, seruoResultText, getRandomIntNum } from '../../static/js/seruoData.js'; export default { data() { return { currentLevel: 0, // 当前关卡 countdown: 60, // 倒计时 score: 0, // 分数 timer: null, // 定时器 resultShow: false, // 倒计时结束后遮罩层显示 resultObject: { index: 0, level: 'LV0', text: '无目之眼' }, // 最终测试结果 dataObject: { index: 0, blockCount: 4, commonColor: '#3399cc', specialColor: '#0da6f2', specialColor_position: getRandomIntNum(4), style: { width: '160px', height: '160px', border_radius: '10px', box_shadow: '3px 3px 6px #848484' } }, // 等级0 分数0 的时候要展示的颜色块数量,特殊颜色块的颜色,以及特殊颜色块的位置 } }, onLoad() { // 显示加载中,500毫秒之后消失 this.loading(); // 将第一个数据对象取出来 this.getFirstDataObject(); // 加载分享菜单 this.loadingShareMenu(); }, methods: { // 显示加载中,500毫秒之后消失 loading() { uni.showLoading({ title: '加载中...', mask: true }) setTimeout(() => { uni.hideLoading(); // 倒计时 this.startCountdown(); }, 500) }, // 倒计时 startCountdown() { if (!this.timer) { this.timer = setInterval(() => { if (this.countdown > 0 && this.countdown <= 60) { this.countdown--; } else { clearInterval(this.timer); this.timer = null; // 显示遮罩层,看多少等级 this.getResult(); } }, 1000) } }, // 将第一个数据对象取出来 getFirstDataObject() { // 当前关卡:0 this.currentLevel = 0; this.dataObject = seruoDatas[0]; }, // 点击方块 clickSpecial(index) { // 如果点击到了特殊颜色的方块,就到下一关 if (index == this.dataObject.specialColor_position) { if (this.currentLevel == 30) { this.getResult(); } else { this.currentLevel++; this.score++; this.dataObject = seruoDatas[this.currentLevel] } } }, // 得到最终结果 getResult() { this.resultShow = true; this.resultObject = seruoResultText[this.currentLevel]; }, // 去首页 toHomePage() { uni.navigateTo({ url: '/pages/index/index' }) }, // 再来一次 reRestart() { // 页面重载 const pages = getCurrentPages() // 声明一个pages使用getCurrentPages方法 const curPage = pages[pages.length - 1] // 声明一个当前页面 curPage.onLoad(curPage.options) // 传入参数 curPage.onShow() // 执行刷新 curPage.onReady() this.resultShow = false; this.score = 0; this.currentLevel = 0; this.countdown = 60; this.getFirstDataObject(); }, // 加载分享菜单 loadingShareMenu() { wx.showShareMenu({ withShareTicket: true, //设置下方的Menus菜单,才能够让发送给朋友与分享到朋友圈两个按钮可以点击 menus: ["shareAppMessage", "shareTimeline"] }) }, // 去分享 toShare() { uni.share({ provider: "weixin", scene: "WXSceneSession", type: 1, summary: "色弱测试,看你能到第几关,快来跟我一起玩吧!", success: function(res) { console.log("success:" + JSON.stringify(res)); }, fail: function(err) { console.log("fail:" + JSON.stringify(err)); } }); } } } </script> <style lang="less" scoped> .bg_red { width: 100%; min-height: 100vh; background-color: #f06060; .title { width: 100%; font-size: 30px; font-weight: 700; padding-top: 50px; color: aliceblue; text-align: center; } .game_main { width: 92%; margin-top: 50px; margin-left: auto; margin-right: auto; .time_score { display: flex; justify-content: space-between; .time { font-size: 17px; color: aliceblue; } .score { font-size: 17px; color: aliceblue; } } .color_block_main { margin-top: 10px; width: 100%; height: 350px; border-radius: 10px; background-color: #fff; border: 6px solid #fff; position: relative; left: -7px; display: flex; justify-content: space-around; flex-wrap: wrap; padding-top: 5px; .per_color_block { width: 160px; height: 160px; border-radius: 10px; box-shadow: 3px 3px 6px #848484; } } } .countdown_end_mask { position: absolute; left: 27px; top: 180px; width: 86%; height: 360px; background-color: #f17f14; opacity: 0.9; z-index: 999999; border-radius: 10px; .title_success { width: 100%; text-align: center; font-size: 40px; font-weight: 800; color: aliceblue; } .success_content { margin-top: 10px; width: 100%; height: 300px; background-color: #fff5d4; display: flex; flex-direction: column; justify-content: space-around; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; .success_content_top { text-align: center; .success_content_text { font-size: 26px; color: #a15a19; font-weight: 600; margin-right: 10px; } .success_content_level { font-size: 26px; color: #a15a19; font-weight: 600; } } .success_content_bottom { display: flex; align-items: center; justify-content: space-evenly; .restart_btn { width: 140px; height: 50px; border-radius: 15px; background-color: #e9a62f; color: #ffffff; font-size: 20px; letter-spacing: 2px; font-weight: 600; position: relative; left: 30px; } .home { position: relative; left: 25px; } .redo { width: 50px; height: 50px; border-radius: 50%; background-color: #fff5d4; text-align: center; uni-icons { position: relative; top: -10px; } } } } } } </style>
通过vue动态绑定样式的方式,去渲染每一关的色块颜色以及大小。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具