Files
shoot-miniprograms/src/components/Matching.vue
2025-11-08 12:18:34 +08:00

176 lines
3.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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="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>