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);
+ });