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动态绑定样式的方式,去渲染每一关的色块颜色以及大小。