mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-05-16 18:57:36 +08:00
refactor the implement of flying card - with pure dom operation
This commit is contained in:
@@ -1,58 +1,86 @@
|
||||
<template>
|
||||
<div
|
||||
class="container"
|
||||
class="flying-company-logo-list-container"
|
||||
:style="{
|
||||
gridTemplateColumns: `repeat(${colCount}, 1fr)`,
|
||||
gridTemplateRows: `repeat(${rowCount}, 1fr)`
|
||||
}"
|
||||
>
|
||||
<img
|
||||
v-for="n in rowCount * colCount"
|
||||
:key="n"
|
||||
class="dot"
|
||||
:src="currentIndexToSrcMap[n - 1]"
|
||||
@animationiteration="
|
||||
(ev) => {
|
||||
handleAnimationiteration(ev, n - 1)
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
ref="imageElContainer"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { logoQueueInjectKey } from './types'
|
||||
|
||||
const logoQueue = ref<string[]>([])
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
const rowCount = 4
|
||||
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(
|
||||
[...Object.values(import.meta.glob('./resources/*.png', { as: 'url' }))].map((it) => it())
|
||||
).then((res) => {
|
||||
logoQueue.value = logoQueue.value.concat(res)
|
||||
currentIndexToSrcMap.value = logoQueue.value.splice(0, rowCount * colCount)
|
||||
return img
|
||||
})
|
||||
logoQueue.push(...res)
|
||||
|
||||
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>
|
||||
|
||||
<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 {
|
||||
0% {
|
||||
transform: translateZ(-2500px);
|
||||
transform: translateZ(-5000px);
|
||||
opacity: 0;
|
||||
}
|
||||
25% {
|
||||
70% {
|
||||
opacity: 1;
|
||||
}
|
||||
75% {
|
||||
90% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
@@ -60,47 +88,38 @@ const handleAnimationiteration = (ev, indexInSrcMap) => {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 600px;
|
||||
perspective: 1200px;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
justify-content: center;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
display: block;
|
||||
--dot-run-duration: 1s;
|
||||
animation: fly-in var(--dot-run-duration) linear infinite;
|
||||
transform-origin: center;
|
||||
mix-blend-mode: darken;
|
||||
width: 200px;
|
||||
}
|
||||
.dot:nth-child(2n) {
|
||||
animation-delay: calc(-1 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(2n + 1) {
|
||||
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(3n + 1) {
|
||||
animation-delay: calc(-0.2 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(5n + 1) {
|
||||
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(7n + 1) {
|
||||
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));
|
||||
.flying-company-logo-list-container {
|
||||
.dot {
|
||||
display: block;
|
||||
--dot-run-duration: 3s;
|
||||
animation: fly-in var(--dot-run-duration) linear infinite;
|
||||
transform-origin: center;
|
||||
mix-blend-mode: darken;
|
||||
width: 200px;
|
||||
}
|
||||
.dot:nth-child(2n) {
|
||||
animation-delay: calc(0 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(2n + 1) {
|
||||
animation-delay: calc(-0.1 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(3n + 1) {
|
||||
animation-delay: calc(-0.2 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(5n + 1) {
|
||||
animation-delay: calc(-0.6 * var(--dot-run-duration));
|
||||
}
|
||||
.dot:nth-child(7n + 1) {
|
||||
animation-delay: calc(-0.8 * 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>
|
||||
|
||||
Reference in New Issue
Block a user