mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-07 00:17:17 +08:00
refactor the implement of flying card - with pure dom operation
This commit is contained in:
@@ -1,58 +1,86 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="container"
|
class="flying-company-logo-list-container"
|
||||||
:style="{
|
:style="{
|
||||||
gridTemplateColumns: `repeat(${colCount}, 1fr)`,
|
gridTemplateColumns: `repeat(${colCount}, 1fr)`,
|
||||||
gridTemplateRows: `repeat(${rowCount}, 1fr)`
|
gridTemplateRows: `repeat(${rowCount}, 1fr)`
|
||||||
}"
|
}"
|
||||||
>
|
ref="imageElContainer"
|
||||||
<img
|
/>
|
||||||
v-for="n in rowCount * colCount"
|
|
||||||
:key="n"
|
|
||||||
class="dot"
|
|
||||||
:src="currentIndexToSrcMap[n - 1]"
|
|
||||||
@animationiteration="
|
|
||||||
(ev) => {
|
|
||||||
handleAnimationiteration(ev, n - 1)
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
import { logoQueueInjectKey } from './types'
|
|
||||||
|
|
||||||
const logoQueue = ref<string[]>([])
|
|
||||||
|
|
||||||
const rowCount = 4
|
const rowCount = 4
|
||||||
const colCount = 6
|
const colCount = 6
|
||||||
const currentIndexToSrcMap: string[] = ref([])
|
const logoQueue: HTMLImageElement[] = []
|
||||||
|
const imageElContainer = ref<HTMLElement>()
|
||||||
|
onMounted(async () => {
|
||||||
|
const res = (await Promise.all(
|
||||||
|
[...Object.values(import.meta.glob('./resources/*.png', { as: 'url' }))].map((it) => it())
|
||||||
|
)).map((url) => {
|
||||||
|
const img = new Image()
|
||||||
|
img.src = url
|
||||||
|
img.onanimationiteration = () => {
|
||||||
|
const newImg = logoQueue.shift()!
|
||||||
|
newImg.classList.add('dot')
|
||||||
|
Object.assign(newImg.style,{
|
||||||
|
position: 'relative',
|
||||||
|
left: (-40 * Math.random()) + 'px',
|
||||||
|
bottom: (-40 * Math.random()) + 'px'
|
||||||
|
})
|
||||||
|
img.replaceWith(newImg)
|
||||||
|
img.classList.remove('dot')
|
||||||
|
Object.assign(img.style,{
|
||||||
|
position: '',
|
||||||
|
left: '',
|
||||||
|
bottom: ''
|
||||||
|
})
|
||||||
|
logoQueue.push(img as HTMLImageElement)
|
||||||
|
}
|
||||||
|
|
||||||
Promise.all(
|
return img
|
||||||
[...Object.values(import.meta.glob('./resources/*.png', { as: 'url' }))].map((it) => it())
|
})
|
||||||
).then((res) => {
|
logoQueue.push(...res)
|
||||||
logoQueue.value = logoQueue.value.concat(res)
|
|
||||||
currentIndexToSrcMap.value = logoQueue.value.splice(0, rowCount * colCount)
|
for (let i = 0; i < rowCount * colCount; i++) {
|
||||||
|
const img = logoQueue.shift()!
|
||||||
|
|
||||||
|
Object.assign(img.style,{
|
||||||
|
position: 'relative',
|
||||||
|
left: (-40 * Math.random()) + 'px',
|
||||||
|
bottom: (-40 * Math.random()) + 'px'
|
||||||
|
})
|
||||||
|
|
||||||
|
img.classList.add('dot')
|
||||||
|
imageElContainer.value?.append(img)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleAnimationiteration = (ev, indexInSrcMap) => {
|
|
||||||
logoQueue.value.push(currentIndexToSrcMap.value[indexInSrcMap])
|
|
||||||
currentIndexToSrcMap.value[indexInSrcMap] = logoQueue.value.shift()
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.flying-company-logo-list-container {
|
||||||
|
height: 600px;
|
||||||
|
perspective: 600px;
|
||||||
|
display: grid;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
@keyframes fly-in {
|
@keyframes fly-in {
|
||||||
0% {
|
0% {
|
||||||
transform: translateZ(-2500px);
|
transform: translateZ(-5000px);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
25% {
|
70% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
75% {
|
90% {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
@@ -60,47 +88,38 @@ const handleAnimationiteration = (ev, indexInSrcMap) => {
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.flying-company-logo-list-container {
|
||||||
.container {
|
.dot {
|
||||||
height: 600px;
|
display: block;
|
||||||
perspective: 1200px;
|
--dot-run-duration: 3s;
|
||||||
display: grid;
|
animation: fly-in var(--dot-run-duration) linear infinite;
|
||||||
align-items: center;
|
transform-origin: center;
|
||||||
justify-items: center;
|
mix-blend-mode: darken;
|
||||||
justify-content: center;
|
width: 200px;
|
||||||
gap: 30px;
|
}
|
||||||
}
|
.dot:nth-child(2n) {
|
||||||
|
animation-delay: calc(0 * var(--dot-run-duration));
|
||||||
.dot {
|
}
|
||||||
display: block;
|
.dot:nth-child(2n + 1) {
|
||||||
--dot-run-duration: 1s;
|
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
||||||
animation: fly-in var(--dot-run-duration) linear infinite;
|
}
|
||||||
transform-origin: center;
|
.dot:nth-child(3n + 1) {
|
||||||
mix-blend-mode: darken;
|
animation-delay: calc(-0.2 * var(--dot-run-duration));
|
||||||
width: 200px;
|
}
|
||||||
}
|
.dot:nth-child(5n + 1) {
|
||||||
.dot:nth-child(2n) {
|
animation-delay: calc(-0.6 * var(--dot-run-duration));
|
||||||
animation-delay: calc(-1 * var(--dot-run-duration));
|
}
|
||||||
}
|
.dot:nth-child(7n + 1) {
|
||||||
.dot:nth-child(2n + 1) {
|
animation-delay: calc(-0.8 * var(--dot-run-duration));
|
||||||
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
}
|
||||||
}
|
.dot:nth-child(11n + 1) {
|
||||||
.dot:nth-child(3n + 1) {
|
animation-delay: calc(-0.5 * var(--dot-run-duration));
|
||||||
animation-delay: calc(-0.2 * var(--dot-run-duration));
|
}
|
||||||
}
|
.dot:nth-child(13n + 1) {
|
||||||
.dot:nth-child(5n + 1) {
|
animation-delay: calc(0 * var(--dot-run-duration));
|
||||||
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
}
|
||||||
}
|
.dot:nth-child(17n + 1) {
|
||||||
.dot:nth-child(7n + 1) {
|
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
||||||
animation-delay: calc(-0.4 * var(--dot-run-duration));
|
}
|
||||||
}
|
|
||||||
.dot:nth-child(11n + 1) {
|
|
||||||
animation-delay: calc(-0.5 * var(--dot-run-duration));
|
|
||||||
}
|
|
||||||
.dot:nth-child(13n + 1) {
|
|
||||||
animation-delay: calc(0 * var(--dot-run-duration));
|
|
||||||
}
|
|
||||||
.dot:nth-child(17n + 1) {
|
|
||||||
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user