176 lines
3.5 KiB
Vue
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="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>
|