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

175 lines
3.5 KiB
Vue
Raw Normal View History

2025-06-25 21:54:18 +08:00
<script setup>
2025-08-25 13:47:32 +08:00
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
2025-06-25 21:54:18 +08:00
const props = defineProps({
stopMatch: {
type: Function,
default: () => {},
},
onComplete: {
type: Function,
default: null,
},
});
const playerNames = [
2025-10-28 16:44:15 +08:00
"乐正青山",
"宇文玉兰",
"岑思宇",
"邬梓瑜",
"范子衿",
2025-07-22 00:01:29 +08:00
"旗鼓相当的对手",
2025-10-28 16:44:15 +08:00
"乐子睿",
"时春晓",
"柏孤鸿",
"东宫锦瑟",
"段干流云",
2025-06-25 21:54:18 +08:00
];
2025-10-28 16:44:15 +08:00
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;
2025-06-25 21:54:18 +08:00
2025-10-28 16:44:15 +08:00
const currentTop = ref(-totalHeight + rowHeight * 0);
2025-06-25 21:54:18 +08:00
const timer = ref(null);
2025-10-28 16:44:15 +08:00
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 {
2025-06-25 21:54:18 +08:00
color: "#fff6",
2025-10-28 16:44:15 +08:00
fontSize: "14px",
};
2025-06-25 21:54:18 +08:00
};
watch(
() => props.onComplete,
(newVal, oldVal) => {
if (newVal && !oldVal) {
2025-10-28 16:44:15 +08:00
if (timer.value) {
clearInterval(timer.value);
timer.value = null;
}
2025-06-25 21:54:18 +08:00
timer.value = setInterval(() => {
2025-10-28 16:44:15 +08:00
const count = Math.round(
(
(totalHeight + (currentTop.value + rowHeight / 3)) /
rowHeight
).toFixed(1)
);
if (count === 10) {
2025-06-25 21:54:18 +08:00
clearInterval(timer.value);
2025-10-28 16:44:15 +08:00
timer.value = null;
2025-06-25 21:54:18 +08:00
setTimeout(() => {
newVal();
2025-07-16 14:42:00 +08:00
}, 1500);
2025-06-25 21:54:18 +08:00
} else {
2025-10-28 16:44:15 +08:00
currentTop.value += 2;
2025-06-25 21:54:18 +08:00
}
2025-10-28 16:44:15 +08:00
}, 40);
2025-06-25 21:54:18 +08:00
}
}
);
onMounted(() => {
timer.value = setInterval(() => {
2025-10-28 16:44:15 +08:00
if (currentTop.value >= -4) {
currentTop.value = -totalHeight;
2025-06-25 21:54:18 +08:00
} else {
2025-10-28 16:44:15 +08:00
currentTop.value += 2;
2025-06-25 21:54:18 +08:00
}
2025-06-26 13:41:40 +08:00
}, 40);
2025-06-25 21:54:18 +08:00
});
2025-08-25 13:47:32 +08:00
onBeforeUnmount(() => {
2025-06-25 21:54:18 +08:00
if (timer.value) clearInterval(timer.value);
2025-10-28 16:44:15 +08:00
timer.value = null;
2025-06-25 21:54:18 +08:00
});
</script>
<template>
<view class="matching">
<image
src="../static/matching-bg.png"
mode="widthFix"
class="matching-bg"
/>
<view>
2025-10-28 16:44:15 +08:00
<view class="player-names" :style="{ top: `${currentTop}%` }">
2025-06-25 21:54:18 +08:00
<text
2025-10-28 16:44:15 +08:00
v-for="(name, index) in [...playerNames, ...playerNames]"
2025-06-25 21:54:18 +08:00
:key="index"
:style="{
2025-10-28 16:44:15 +08:00
lineHeight: `${rowHeight}vw`,
...getTextStyle(currentTop, index),
2025-06-25 21:54:18 +08:00
}"
>
{{ 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;
2025-06-26 01:27:23 +08:00
height: 95vw;
2025-06-25 21:54:18 +08:00
overflow: hidden;
2025-06-26 13:41:40 +08:00
position: absolute;
2025-10-28 16:44:15 +08:00
top: 30vw;
2025-06-25 21:54:18 +08:00
}
.matching-bg {
position: absolute;
width: 70vw;
height: 102vw;
2025-06-26 01:27:23 +08:00
top: 27vw;
2025-06-25 21:54:18 +08:00
}
.matching > button {
width: 55%;
padding: 18px;
color: #000;
background-color: #fed847;
font-size: 18px;
border-radius: 30px;
2025-06-26 13:41:40 +08:00
position: absolute;
top: 142vw;
2025-06-25 21:54:18 +08:00
}
.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>