Commit 585effb8 by CHEN\chenXi

水位控制挑战

parent 562b867e
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
"pages": [
{
"path": "pages/index/index",
"style": {
......@@ -24,6 +24,12 @@
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/miniGame-four/index",
"style": {
"navigationStyle": "custom"
}
}
],
"globalStyle": {
......
<template>
<view class="container">
<image class="bg" src="../../static/game-four/background.png" mode="aspectFill" />
<!-- 顶部标题 -->
<view class="top">
<image class="topTitle" src="../../static/game-four/title.png" mode="aspectFit" />
</view>
<!-- 主要内容区域 -->
<view class="content">
<view class="contentBor">
<!-- 根据进度动态切换水杯图片 -->
<image
class="shuibei"
:src="currentShuibeiImage"
mode="aspectFit"
/>
</view>
<view class="button">
<image class="buttonImg" src="../../static/game-four/startBut.png" mode="aspectFit"
@click="startProgress" />
<image class="buttonImg" src="../../static/game-four/stopBut.png" mode="aspectFit"
@click="stopProgress" />
</view>
</view>
<!-- 进度条 -->
<view class="progressLineContent">
<view class="progressLine">
<view class="lineTitle">精准度:{{ Math.floor(progress) }}%</view>
<view class="lineContent">
<!-- 进度条背景 -->
<view class="line">
<!-- 第一段:0-35% 绿色 -->
<view class="segment segment-1" :style="{ width: segment1Width }"></view>
<!-- 第二段:35-80% 橙色 -->
<view class="segment segment-2" :style="{ width: segment2Width }"></view>
<!-- 第三段:80-100% 红色 -->
<view class="segment segment-3" :style="{ width: segment3Width }"></view>
</view>
<image class="shuidi" src="../../static/game-four/shuidi.png" mode="aspectFit" />
</view>
</view>
</view>
<!-- 规则和提示 -->
<view class="rule-tips">
<!-- 游戏规则 -->
<view class="rules">
<view class="itemBg">
<view class="ruleTop">
<image class="ruleIcon" src="../../static/game-four/ruleIcon.png" />
<view class="ruleTitle">游戏规则</view>
</view>
<view class="ruleContent">
<view v-for="(rule, index) in rules" :key="`rule-${index}`" class="ruleText">
<view class="circel"></view>
{{ rule }}
</view>
</view>
</view>
</view>
<!-- 小提示 -->
<view class="tips">
<view class="itemBg">
<view class="tipsTop">
<image class="tipsIcon" src="../../static/game-four/tipsIcon.png" />
<view class="tipsTitle">小提示</view>
</view>
<view class="tipsContent">
<view v-for="(tip, index) in tips" :key="`tip-${index}`" class="tipsText">
<view class="circel"></view>
{{ tip }}
</view>
</view>
</view>
</view>
</view>
<!-- 全屏完成弹窗 -->
<view class="popup-overlay" v-if="showPopup" @click="closePopup">
<view class="popup-content">
<image
class="popup-image"
src="https://userone-oss-cdn.angelgroup.com.cn/static/2026-01-23/d204d71cf2a54b18a6404e6132618cd6完成弹窗.webp"
mode="aspectFit"
@click.stop="handleImageClick"
/>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, onUnmounted, watch } from 'vue'
// 进度条相关状态
const progress = ref(0) // 当前进度百分比(0-100)
const isRunning = ref(false) // 是否正在运行
const timer = ref(null) // 定时器
const speed = 0.5 // 每100ms增加的进度百分比
const showPopup = ref(false) // 是否显示弹窗
const timeoutId = ref(null) // 定时器ID
// 当前显示的水杯图片
const currentShuibeiImage = ref('../../static/game-four/35water.png')
// 图片路径常量 - 去掉%符号
const SHUIBEI_IMAGES = {
PERCENT_35: '../../static/game-four/35water.png',
PERCENT_80: '../../static/game-four/80water.png',
PERCENT_99: '../../static/game-four/99water.png',
PERCENT_100: '../../static/game-four/100water.png'
}
// 规则数据抽离
const rules = [
'控制水位达到目标区域',
'点击加水按钮增加水量',
'在合适的时机点击停止',
'达到目标水位400ml时即为成功!'
]
// 提示数据抽离
const tips = [
'集中注意力观察刻度',
'提前预判水位到达时间',
'手指放在停止按钮上准备',
'点击返回再进入可以重新开始'
]
// 监听进度变化,更新水杯图片
watch(progress, (newValue) => {
updateShuibeiImage(newValue)
// 当进度达到100%时,延迟3秒显示弹窗
if (newValue >= 100) {
// 清除之前的定时器
if (timeoutId.value) {
clearTimeout(timeoutId.value)
}
// 设置3秒后显示弹窗
timeoutId.value = setTimeout(() => {
showPopup.value = true
}, 3000) // 3000毫秒 = 3秒
}
})
// 根据进度更新水杯图片
const updateShuibeiImage = (progressValue) => {
if (progressValue >= 100) {
currentShuibeiImage.value = SHUIBEI_IMAGES.PERCENT_100
} else if (progressValue >= 80) {
currentShuibeiImage.value = SHUIBEI_IMAGES.PERCENT_99
} else if (progressValue >= 35) {
currentShuibeiImage.value = SHUIBEI_IMAGES.PERCENT_80
} else {
// 1-35%都使用35%水位的图片
currentShuibeiImage.value = SHUIBEI_IMAGES.PERCENT_35
}
}
// 计算各段的宽度
const segment1Width = computed(() => {
// 第一段:0-35%
if (progress.value <= 35) {
return `${progress.value}%`
} else {
return '35%'
}
})
const segment2Width = computed(() => {
// 第二段:35-80%
if (progress.value <= 35) {
return '0%'
} else if (progress.value <= 80) {
return `${progress.value - 35}%`
} else {
return '45%' // 80% - 35% = 45%
}
})
const segment3Width = computed(() => {
// 第三段:80-100%
if (progress.value <= 80) {
return '0%'
} else {
return `${progress.value - 80}%`
}
})
// 开始进度
const startProgress = () => {
if (isRunning.value || progress.value >= 100) return
isRunning.value = true
// 清除之前的定时器
if (timer.value) {
clearInterval(timer.value)
}
// 设置新的定时器
timer.value = setInterval(() => {
// 进度增加
let newProgress = progress.value + speed
// 确保进度不超过100%
if (newProgress >= 100) {
newProgress = 100
}
// 更新进度值,四舍五入保留2位小数避免精度问题
progress.value = Math.round(newProgress * 100) / 100
// 当进度达到100%时停止
if (progress.value >= 100) {
stopProgress()
}
}, 100) // 每100ms更新一次
}
// 停止进度
const stopProgress = () => {
isRunning.value = false
if (timer.value) {
clearInterval(timer.value)
timer.value = null
}
}
// 重置进度
const resetProgress = () => {
stopProgress()
progress.value = 0
// 重置图片为初始状态(35%水位图片)
currentShuibeiImage.value = SHUIBEI_IMAGES.PERCENT_35
// 关闭弹窗
closePopup()
}
// 关闭弹窗
const closePopup = () => {
showPopup.value = false
// 清除定时器
if (timeoutId.value) {
clearTimeout(timeoutId.value)
timeoutId.value = null
}
}
// 点击弹窗图片的处理(防止冒泡)
const handleImageClick = () => {
closePopup()
}
// 组件卸载时清除定时器
onUnmounted(() => {
if (timer.value) {
clearInterval(timer.value)
timer.value = null
}
if (timeoutId.value) {
clearTimeout(timeoutId.value)
timeoutId.value = null
}
})
</script>
<style scoped lang="scss">
.container {
width: 100%;
min-height: 100%;
position: relative;
.bg {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
}
.top {
width: 100%;
padding-top: 220rpx;
display: flex;
justify-content: center;
align-items: center;
.topTitle {
width: 288rpx;
height: 108rpx;
text-align: center;
}
}
.content {
width: 670rpx;
height: 712rpx;
border-radius: 24rpx;
border: 4rpx solid #2D4B5D;
background: linear-gradient(180deg, #FFF 0%, #D9EBF7 100%);
margin: 12rpx auto;
.contentBor {
display: flex;
justify-content: center;
align-items: center;
height: 600rpx; // 确保容器有固定高度
.shuibei {
width: 714rpx;
height: 600rpx;
object-fit: contain;
transition: opacity 0.3s ease; // 添加过渡效果
}
}
.button {
display: flex;
align-items: center;
justify-content: space-around;
// margin-top: -110rpx;
.buttonImg {
width: 218rpx;
height: 100rpx;
// 添加点击效果
&:active {
opacity: 0.8;
transform: scale(0.95);
}
}
}
}
.progressLineContent {
width: 694rpx;
height: 120rpx;
border-radius: 24rpx;
border: 4rpx solid #2D4B5D;
background: #FFF;
margin: 12rpx auto;
.progressLine {
width: 678rpx;
height: 108rpx;
border-radius: 12rpx;
border: 4rpx solid #FFF;
background: #A1DCFA;
margin: 5rpx auto;
.lineTitle {
padding: 8rpx 24rpx;
color: #ffffff;
-webkit-text-stroke-width: 2rpx;
font-size: 28rpx;
font-weight: 600;
}
.lineContent {
padding: 4rpx 24rpx;
display: flex;
align-items: center;
.line {
width: 526rpx;
height: 28rpx;
border-radius: 62rpx;
border: 2rpx solid #FFF;
background: #5B729A;
box-shadow: 0 8rpx 0 0 #00000040 inset;
position: relative;
overflow: hidden;
// 进度条分段
.segment {
position: absolute;
top: 0;
height: 100%;
min-width: 0;
transition: width 0.1s linear;
border-radius: 0; // 所有段过渡处都设置为平的
// 第一段:绿色(0-35%)
&.segment-1 {
background: #00CC99;
left: 0;
border-radius: 62rpx 0 0 62rpx; // 仅左侧有圆角
}
// 第二段:橙色(35-80%
&.segment-2 {
background: #FFAA00;
left: 35%;
border-radius: 0; // 平直过渡
}
// 第三段:红色(80-100%
&.segment-3 {
background: #E63B34;
left: 80%;
border-radius: 0 62rpx 62rpx 0; // 仅右侧有圆角
}
}
}
.shuidi {
margin-top: -50rpx;
margin-left: 15rpx;
width: 95.39rpx;
height: 105.66rpx;
transform: rotate(3.768deg);
}
}
}
}
.rule-tips {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx;
.rules,
.tips {
width: 336rpx;
height: 336rpx;
border-radius: 24rpx;
border: 4rpx solid #2D4B5D;
background: #D9EBF7;
.itemBg {
width: 320rpx;
height: 320rpx;
border-radius: 12rpx;
background: #FFF;
margin: 8rpx;
.ruleTop,
.tipsTop {
padding: 10rpx 30rpx;
display: flex;
align-items: center;
.ruleTitle,
.tipsTitle {
margin-left: 20rpx;
color: #25334d;
font-size: 32rpx;
font-weight: 600;
}
}
.ruleContent,
.tipsContent {
padding: 0rpx 22rpx;
.ruleText,
.tipsText {
display: flex;
color: #25334d;
font-size: 26rpx;
font-weight: 500;
margin-bottom: 12rpx;
}
.circel {
margin-right: 5rpx;
}
}
}
}
.tips .tipsTop {
justify-content: center;
}
}
/* 全屏弹窗样式 */
.popup-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
.popup-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 20rpx;
.popup-image {
width: 100%;
height: 100%;
object-fit: contain;
// 添加点击效果
&:active {
opacity: 0.9;
}
}
}
}
/* 为所有图片添加公共样式 */
image {
display: block;
}
.ruleIcon,
.tipsIcon {
width: 54rpx !important;
height: 54rpx !important;
}
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment