[FEAT] Add drop event listener for new images

This commit is contained in:
2025-11-17 01:35:46 +01:00
parent e54edf8af6
commit 266a463817
2 changed files with 164 additions and 2 deletions

View File

@@ -46,7 +46,12 @@
@touchmove="handleTouchMove"
@touchend="stopDrag"
@contextmenu.prevent
class="w-full"
@dragover="handleDragOver"
@dragenter="handleDragEnter"
@dragleave="handleDragLeave"
@drop="handleDrop"
class="w-full transition-all"
:class="{ 'ring-4 ring-blue-500 ring-opacity-50': isDragOver }"
:style="settingsStore.pixelPerfect ? { 'image-rendering': 'pixelated' } : {}"
></canvas>
@@ -119,6 +124,7 @@
(e: 'removeSprite', id: string): void;
(e: 'replaceSprite', id: string, file: File): void;
(e: 'addSprite', file: File): void;
(e: 'addSpriteWithResize', file: File): void;
}>();
// Get settings from store
@@ -149,6 +155,7 @@
const contextMenuSpriteId = ref<string | null>(null);
const replacingSpriteId = ref<string | null>(null);
const fileInput = ref<HTMLInputElement | null>(null);
const isDragOver = ref(false);
const spritePositions = computed(() => {
const { maxWidth, maxHeight } = calculateMaxDimensions();
@@ -446,6 +453,88 @@
contextMenuSpriteId.value = null;
};
// Drag and drop handlers
const handleDragOver = (event: DragEvent) => {
event.preventDefault();
event.stopPropagation();
if (event.dataTransfer) {
event.dataTransfer.dropEffect = 'copy';
}
isDragOver.value = true;
};
const handleDragEnter = (event: DragEvent) => {
event.preventDefault();
event.stopPropagation();
isDragOver.value = true;
};
const handleDragLeave = (event: DragEvent) => {
event.preventDefault();
event.stopPropagation();
// Only set to false if we're leaving the canvas entirely
const rect = canvasRef.value?.getBoundingClientRect();
if (rect && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom)) {
isDragOver.value = false;
}
};
const handleDrop = async (event: DragEvent) => {
event.preventDefault();
event.stopPropagation();
isDragOver.value = false;
if (!event.dataTransfer?.files || event.dataTransfer.files.length === 0) {
return;
}
const files = Array.from(event.dataTransfer.files).filter(file => file.type.startsWith('image/'));
if (files.length === 0) {
alert('Please drop image files only.');
return;
}
// Process each dropped file
for (const file of files) {
await processDroppedImage(file);
}
};
const processDroppedImage = (file: File): Promise<void> => {
return new Promise((resolve, reject) => {
const img = new Image();
const reader = new FileReader();
reader.onload = e => {
if (e.target?.result) {
img.src = e.target.result as string;
}
};
img.onload = () => {
const { maxWidth, maxHeight } = calculateMaxDimensions();
// Check if the dropped image is larger than current cells
if (img.naturalWidth > maxWidth || img.naturalHeight > maxHeight) {
// Emit event with resize flag
emit('addSpriteWithResize', file);
} else {
// Normal add
emit('addSprite', file);
}
resolve();
};
img.onerror = () => {
console.error('Failed to load image:', file.name);
reject(new Error('Failed to load image'));
};
reader.readAsDataURL(file);
});
};
const handleTouchMove = (event: TouchEvent) => {
// Only prevent default when we're actually dragging
if (isDragging.value) {