Files
shoot-miniprograms/src/components/Matching.vue
T

176 lines
3.5 KiB
Vue

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
const props = defineProps({
stopMatch: {
type: Function,
default: () => {},
},
onComplete: {
type: Function,
default: null,
},
});
const playerNames = [
"乐正青山",
"宇文玉兰",
"岑思宇",
"邬梓瑜",
"范子衿",
"旗鼓相当的对手",
"乐子睿",
"时春晓",
"柏孤鸿",
"东宫锦瑟",
"段干流云",
];
const textStyles = [
{
color: "#fff9",
fontSize: "18px",
},
{
color: "#fff",
fontSize: "22px",
},
{
color: "#fed847",
fontSize: "30px",
},
];
const rowHeight = 100 / 7;
const totalHeight = (playerNames.length / 7) * 100 + 7;
const currentTop = ref(-totalHeight + rowHeight * 0);
const timer = ref(null);
const getTextStyle = (top, index) => {
const count = Math.floor(
((totalHeight + (top + rowHeight / 3)) / rowHeight).toFixed(1)
);
if (index === 12 - count) return textStyles[0];
else if (index === 13 - count) return textStyles[1];
else if (index === 14 - count) return textStyles[2];
else if (index === 15 - count) return textStyles[1];
else if (index === 16 - count) return textStyles[0];
return {
color: "#fff6",
fontSize: "14px",
};
};
watch(
() => props.onComplete,
(newVal) => {
if (timer.value) {
clearInterval(timer.value);
timer.value = null;
}
timer.value = setInterval(() => {
const count = Math.round(
(
(totalHeight + (currentTop.value + rowHeight / 3)) /
rowHeight
).toFixed(1)
);
if (count === 10) {
clearInterval(timer.value);
timer.value = null;
setTimeout(newVal, 1500);
return;
}
// 这里不重置,如果运行超13秒,就不会循环了
if (currentTop.value >= -4) {
currentTop.value = -totalHeight;
} else {
currentTop.value += 2;
}
}, 40);
}
);
onMounted(() => {
timer.value = setInterval(() => {
if (currentTop.value >= -4) {
currentTop.value = -totalHeight;
} else {
currentTop.value += 2;
}
}, 40);
});
onBeforeUnmount(() => {
if (timer.value) clearInterval(timer.value);
timer.value = null;
});
</script>
<template>
<view class="matching">
<image
src="../static/matching-bg.png"
mode="widthFix"
class="matching-bg"
/>
<view>
<view class="player-names" :style="{ top: `${currentTop}%` }">
<text
v-for="(name, index) in [...playerNames, ...playerNames]"
:key="index"
:style="{
lineHeight: `${rowHeight}vw`,
...getTextStyle(currentTop, index),
}"
>
{{ name }}
</text>
</view>
</view>
<button hover-class="none" @click="$clickSound(stopMatch)">取消匹配</button>
</view>
</template>
<style scoped>
.matching {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: relative;
}
.matching > view {
width: 70vw;
height: 95vw;
overflow: hidden;
position: absolute;
top: 30vw;
}
.matching-bg {
position: absolute;
width: 70vw;
height: 102vw;
top: 27vw;
}
.matching > button {
width: 55%;
padding: 18px;
color: #000;
background-color: #fed847;
font-size: 18px;
border-radius: 30px;
position: absolute;
top: 142vw;
}
.player-names {
width: 100%;
display: flex;
flex-direction: column;
position: absolute;
top: 0;
}
.player-names > text {
width: 100%;
text-align: center;
transition: all 0.3s ease;
}
</style>