diff --git a/frontend/app/components/Sprite.vue b/frontend/app/components/Sprite.vue index ca576dd..672477a 100644 --- a/frontend/app/components/Sprite.vue +++ b/frontend/app/components/Sprite.vue @@ -33,17 +33,16 @@ onMounted(() => { position: absolute; z-index: 1; width: 1300px; - + margin-left: 20px; + @media screen and (max-width: 1200px) and (min-width: 900px) { width: 975px; + margin-top: 210px; + margin-left: 75px; } - @media screen and (max-width: 900px) and (min-width: 600px) { - width: 650px; - } - - @media screen and (max-width: 600px){ - width: 425px; + @media screen and (max-width: 900px){ + display: none; } } \ No newline at end of file diff --git a/frontend/app/components/layouts/FixedLayout.vue b/frontend/app/components/layouts/FixedLayout.vue index 5a8f0f0..0d26848 100644 --- a/frontend/app/components/layouts/FixedLayout.vue +++ b/frontend/app/components/layouts/FixedLayout.vue @@ -7,13 +7,13 @@ \ No newline at end of file diff --git a/frontend/app/components/parts/TableHeader.vue b/frontend/app/components/parts/TableHeader.vue index af452bf..f930b31 100644 --- a/frontend/app/components/parts/TableHeader.vue +++ b/frontend/app/components/parts/TableHeader.vue @@ -2,7 +2,6 @@ import HeaderLinks from './HeaderLinks.vue'; import SiteOptions from './site_options/SiteOptions.vue'; import StickyHeader from './StickyHeader.vue'; - import { accent } from '~/composables/theme' const spritePath = computed(() => { return `/sprites/${accent.value}/${accent.value}.gif` @@ -16,7 +15,12 @@ const asciiArt = [ ]; const fullText = asciiArt.join('\n'); -const displayedArt = ref(""); +interface ArtChar { + char: string; + done: boolean; +} + +const displayedArt = ref([]); let charIndex = 0; let intervalId: ReturnType | null = null; @@ -36,36 +40,69 @@ const preloadImages = (imageArray) => { ) } -onMounted(() => { - preloadImages(sprite_names); + onMounted(() => { + preloadImages(sprite_names); - if (hasAnimated.value || displayedArt.value === fullText) { - displayedArt.value = fullText; - return; - } + if (hasAnimated.value || displayedArt.value.length === fullText.length) { + for (let i = 0; i < fullText.length; i++) { + displayedArt.value.push({ char: fullText[i], done: true }); + } + return; + } - intervalId = setInterval(() => { - if (charIndex < fullText.length) { - displayedArt.value += fullText[charIndex]; - charIndex++; - } else { - clearInterval(intervalId!); - intervalId = null; - hasAnimated.value = true; - } - }, 5); - }); + intervalId = setInterval(() => { + if (charIndex < fullText.length) { + displayedArt.value[charIndex] = { char: fullText[charIndex], done: true }; + charIndex++; + } else { + clearInterval(intervalId!); + intervalId = null; + hasAnimated.value = true; + } + }, 5); + }); - onBeforeUnmount(() => { - if (intervalId) clearInterval(intervalId); - }); + const getGridPos = (idx: number) => { + let x = 0, y = 0; + for (let j = 0; j < idx; j++) { + if (fullText[j] === '\n') { y++; x = 0; } + else { x++; } + } + return { x, y }; + }; + + const onCharClick = (index: number, spanEl: HTMLElement) => { + for (let i = 0; i < fullText.length; i++) { + if (fullText[i] === '\n') continue; + const indexGrid = getGridPos(index); + const charGrid = getGridPos(i); + let manhattanDistance = Math.abs(indexGrid.x - charGrid.x) + Math.abs(indexGrid.y - charGrid.y); + let delay = manhattanDistance * 20; + setTimeout(() => { + displayedArt.value[i] = { char: fullText[i], done: true }; + const targetSpan = document.querySelector(`.ascii-art span[index="${i}"]`) as HTMLElement; + if (targetSpan) { + targetSpan.style.transition = 'color 80ms ease-out'; + targetSpan.style.color = 'var(--color-link)'; + requestAnimationFrame(() => { + setTimeout(() => { + targetSpan.style.color = ''; + }, 150); + }); + } + }, delay); + } + }; + onBeforeUnmount(() => { + if (intervalId) clearInterval(intervalId); + });