uniapp + vue 实现色弱测试小游戏

最终的效果:点击色块中不同的色块,跳到下一关

image
image

准备一些静态数据,放到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动态绑定样式的方式,去渲染每一关的色块颜色以及大小。

posted @ 2023-01-05 11:28  合起来的彳亍  阅读(358)  评论(0编辑  收藏  举报