refactor the implement of flying card - with pure dom operation

This commit is contained in:
geekgeekrun
2024-03-10 13:56:33 +08:00
parent d3029b9ebb
commit 3ff4500737
@@ -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>