添加匹配中效果
This commit is contained in:
190
src/components/Matching.vue
Normal file
190
src/components/Matching.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted, watch } from "vue";
|
||||
const props = defineProps({
|
||||
stopMatch: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
},
|
||||
onComplete: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
const playerNames = [
|
||||
"彭妮·希利",
|
||||
"埃琳娜·奥西波娃",
|
||||
"凯西·考夫霍尔德",
|
||||
"起鼓相当的对手",
|
||||
"马乌罗·内斯波利",
|
||||
"埃琳娜·奥西波娃",
|
||||
"凯西·考夫霍尔德",
|
||||
];
|
||||
|
||||
const totalTop = ref(0);
|
||||
const timer = ref(null);
|
||||
const textStyles = ref([]);
|
||||
|
||||
const getTextStyle = (top) => {
|
||||
const styles = [
|
||||
{
|
||||
color: "#fff9",
|
||||
fontSize: "20px",
|
||||
},
|
||||
{
|
||||
color: "#fff",
|
||||
fontSize: "24px",
|
||||
},
|
||||
{
|
||||
color: "#fed847",
|
||||
fontSize: "30px",
|
||||
},
|
||||
];
|
||||
const data = new Array(14).fill({
|
||||
color: "#fff6",
|
||||
fontSize: "16px",
|
||||
});
|
||||
const unitHeight = 100 / 7;
|
||||
let style = {};
|
||||
if (top >= 100 - unitHeight / 2) {
|
||||
for (let j = 0; j < 5; j++) {
|
||||
data[j + 1] = styles[j > 2 ? 4 - j : j];
|
||||
}
|
||||
} else {
|
||||
new Array(7).fill(1).some((_, i) => {
|
||||
if (
|
||||
top >= unitHeight * i - unitHeight / 2 &&
|
||||
top < unitHeight * (i + 1) - unitHeight / 2
|
||||
) {
|
||||
for (let j = 0; j < 5; j++) {
|
||||
data[7 + j + 1 - i] = styles[j > 2 ? 4 - j : j];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return data;
|
||||
};
|
||||
watch(
|
||||
() => props.onComplete,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal && !oldVal) {
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
timer.value = setInterval(() => {
|
||||
if (totalTop.value === 100) {
|
||||
clearInterval(timer.value);
|
||||
setTimeout(() => {
|
||||
newVal();
|
||||
}, 1000);
|
||||
} else {
|
||||
totalTop.value += 0.5;
|
||||
}
|
||||
textStyles.value = getTextStyle(totalTop.value);
|
||||
}, 10);
|
||||
}
|
||||
}
|
||||
);
|
||||
onMounted(() => {
|
||||
timer.value = setInterval(() => {
|
||||
if (totalTop.value === 100) {
|
||||
totalTop.value = 0;
|
||||
} else {
|
||||
totalTop.value += 0.5;
|
||||
}
|
||||
textStyles.value = getTextStyle(totalTop.value);
|
||||
}, 10);
|
||||
});
|
||||
onUnmounted(() => {
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="matching">
|
||||
<image
|
||||
src="../static/matching-bg.png"
|
||||
mode="widthFix"
|
||||
class="matching-bg"
|
||||
/>
|
||||
<view>
|
||||
<view
|
||||
class="player-names"
|
||||
:style="{
|
||||
top: `${totalTop - 100}%`,
|
||||
}"
|
||||
>
|
||||
<text
|
||||
v-for="(name, index) in playerNames"
|
||||
:key="index"
|
||||
:style="{
|
||||
lineHeight: `${98 / 7}vw`,
|
||||
...(textStyles[index] || {}),
|
||||
}"
|
||||
>
|
||||
{{ name }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="player-names" :style="{ top: `${totalTop}%` }">
|
||||
<text
|
||||
v-for="(name, index) in playerNames"
|
||||
:key="index"
|
||||
:style="{
|
||||
lineHeight: `${98 / 7}vw`,
|
||||
...(textStyles[index + 7] || {}),
|
||||
}"
|
||||
>
|
||||
{{ 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: 98vw;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
transform: translateY(3vw);
|
||||
}
|
||||
.matching-bg {
|
||||
position: absolute;
|
||||
width: 70vw;
|
||||
height: 102vw;
|
||||
top: 30vw;
|
||||
}
|
||||
.matching > button {
|
||||
width: 55%;
|
||||
margin-top: 20vw;
|
||||
padding: 18px;
|
||||
color: #000;
|
||||
background-color: #fed847;
|
||||
font-size: 18px;
|
||||
border-radius: 30px;
|
||||
}
|
||||
.player-names {
|
||||
width: 100%;
|
||||
height: 98vw;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transform: translateY(3vw);
|
||||
}
|
||||
.player-names > text {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
@@ -21,7 +21,7 @@ watch(
|
||||
() => props.seq,
|
||||
() => {
|
||||
if (props.seq > 0) {
|
||||
if(show.value) return;
|
||||
if (show.value) return;
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
count.value = props.countdown;
|
||||
show.value = true;
|
||||
@@ -38,6 +38,9 @@ watch(
|
||||
if (timer.value) clearInterval(timer.value);
|
||||
show.value = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user