Compare commits

...

2 Commits

Author SHA1 Message Date
f52530d058 [FEAT] New Discord 2025-12-01 02:25:53 +01:00
bf95f4fbee UX enhancements 2025-11-26 20:29:30 +01:00
7 changed files with 31 additions and 13 deletions

View File

@@ -26,7 +26,7 @@
<meta name="title" content="Spritesheet generator - Create Game Spritesheets Online">
<meta name="description" content="Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.">
<meta name="keywords" content="Spritesheet generator, sprite sheet maker, game development, pixel art, sprite animation, game assets, 2D game tools">
<meta name="author" content="nu11ed">
<meta name="author" content="streetshadow">
<meta name="robots" content="index, follow">
<link rel="canonical" href="https://spritesheetgenerator.online/">

View File

@@ -78,7 +78,7 @@
import Breadcrumbs from './components/Breadcrumbs.vue';
import { useLayers } from './composables/useLayers';
const { layers } = useLayers();
const { layers, hasSprites } = useLayers();
const isHelpModalOpen = ref(false);
const isFeedbackModalOpen = ref(false);

View File

@@ -4,9 +4,6 @@
/* Dark mode transition */
html,
body {
transition:
background-color 0.3s ease,
color 0.3s ease;
-webkit-tap-highlight-color: transparent; /* Remove tap highlight on mobile */
}

View File

@@ -23,7 +23,7 @@
<div class="max-w-none text-gray-700 dark:text-gray-300">
<p class="mb-4 text-base leading-relaxed">Spritesheet generator is a free, open-source tool for creating spritesheets for game development and animation projects. This tool allows you to upload individual sprite images and arrange them into a spritesheet with customizable layout.</p>
<p class="mb-4 text-base leading-relaxed">Matrix: root@adhd.sh, Discord: nu11ed</p>
<p class="mb-4 text-base leading-relaxed">Matrix: root@adhd.sh, Discord: streetshadow</p>
<h4 class="mt-6 mb-3 text-lg font-medium text-gray-900 dark:text-gray-100">How to use:</h4>
<ol class="list-decimal pl-6 space-y-2 mb-4">
<li>Upload your sprite images by dragging and dropping them or clicking the upload area</li>

View File

@@ -1,6 +1,6 @@
<template>
<Teleport to="body">
<div v-if="showContextMenu" class="fixed bg-white dark:bg-gray-800 border-2 border-gray-300 dark:border-gray-600 rounded-xl shadow-2xl z-50 py-2 min-w-[200px] overflow-hidden" :style="{ left: contextMenuX + 'px', top: contextMenuY + 'px' }">
<div v-if="showContextMenu" @click.stop class="fixed bg-white dark:bg-gray-800 border-2 border-gray-300 dark:border-gray-600 rounded-xl shadow-2xl z-50 py-2 min-w-[200px] overflow-hidden" :style="{ left: contextMenuX + 'px', top: contextMenuY + 'px' }">
<button @click="addSprite" class="w-full px-5 py-3 text-left hover:bg-blue-50 dark:hover:bg-blue-900/30 text-gray-700 dark:text-gray-200 flex items-center gap-3 transition-colors font-medium">
<i class="fas fa-plus text-blue-600 dark:text-blue-400"></i>
<span>Add Sprite</span>
@@ -448,6 +448,11 @@
});
const startDrag = (event: MouseEvent) => {
// If the click originated from an interactive element (button, link, input), ignore drag handling
const target = event.target as HTMLElement;
if (target && target.closest('button, a, input, select, textarea')) {
return;
}
if (!gridContainerRef.value) return;
// Hide context menu if open
@@ -476,8 +481,22 @@
dragStart(event);
};
const pendingDrag = ref(false);
const latestEvent = ref<MouseEvent | null>(null);
const drag = (event: MouseEvent) => {
dragMove(event);
// Store the latest event and schedule a single animation frame update
latestEvent.value = event;
if (!pendingDrag.value) {
pendingDrag.value = true;
requestAnimationFrame(() => {
if (latestEvent.value) {
dragMove(latestEvent.value);
}
pendingDrag.value = false;
latestEvent.value = null;
});
}
};
const removeSprite = () => {
@@ -534,12 +553,11 @@
};
onMounted(() => {
// Hide context menu when clicking elsewhere
document.addEventListener('click', hideContextMenu);
document.addEventListener('mouseup', stopDrag);
});
onUnmounted(() => {
document.removeEventListener('click', hideContextMenu);
document.removeEventListener('mouseup', stopDrag);
});
// Watch for background color changes

View File

@@ -30,6 +30,8 @@ export const useLayers = () => {
const visibleLayers = computed(() => layers.value.filter(l => l.visible));
const hasSprites = computed(() => layers.value.some(l => l.sprites.length > 0));
const updateSpritePosition = (id: string, x: number, y: number) => {
const l = activeLayer.value;
if (!l) return;
@@ -238,6 +240,7 @@ export const useLayers = () => {
addLayer,
removeLayer,
moveLayer,
hasSprites,
};
};

View File

@@ -40,7 +40,7 @@
{ property: 'og:description', content: pageDescription },
{ property: 'og:image', content: pageImage },
{ property: 'og:site_name', content: 'Spritesheet Generator' },
{ property: 'article:author', content: computed(() => post.value?.author || 'nu11ed') },
{ property: 'article:author', content: computed(() => post.value?.author || 'streetshadow') },
{ property: 'article:published_time', content: computed(() => post.value?.date || '') },
// Twitter
@@ -95,7 +95,7 @@
image: `https://spritesheetgenerator.online${post.value.image}`,
author: {
'@type': 'Person',
name: post.value.author || 'nu11ed',
name: post.value.author || 'streetshadow',
},
publisher: {
'@type': 'Organization',