2025-04-03 02:40:51 +02:00

133 lines
3.4 KiB
Vue

<template>
<div
@click="openFileDialog"
@dragover.prevent="onDragOver"
@dragleave="onDragLeave"
@drop.prevent="onDrop"
class="border-2 border-dashed border-gray-600 rounded-lg p-8 text-center cursor-pointer transition-all"
:class="{'border-blue-500 bg-blue-500 bg-opacity-5': isDragOver}"
>
<i class="fas fa-cloud-upload-alt text-blue-500 text-3xl mb-4"></i>
<p class="text-gray-400">
Drag & drop sprite images here<br>or click to select files
</p>
<input
type="file"
ref="fileInput"
multiple
accept="image/*"
class="hidden"
@change="onFileChange"
>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { Sprite } from '../composables/useSpritesheetStore';
import { useSpritesheetStore } from '../composables/useSpritesheetStore';
export default defineComponent({
name: 'DropZone',
emits: ['files-uploaded'],
setup(props, { emit }) {
const store = useSpritesheetStore();
const fileInput = ref<HTMLInputElement | null>(null);
const isDragOver = ref(false);
const openFileDialog = () => {
if (fileInput.value) {
fileInput.value.click();
}
};
const onDragOver = () => {
isDragOver.value = true;
};
const onDragLeave = () => {
isDragOver.value = false;
};
const onDrop = (e: DragEvent) => {
isDragOver.value = false;
if (e.dataTransfer?.files.length) {
handleFiles(e.dataTransfer.files);
}
};
const onFileChange = (e: Event) => {
const input = e.target as HTMLInputElement;
if (input.files?.length) {
handleFiles(input.files);
}
};
const handleFiles = async (files: FileList) => {
const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/'));
if (imageFiles.length === 0) {
store.showNotification('Please upload image files only', 'error');
return;
}
const newSprites: Sprite[] = [];
for (let i = 0; i < imageFiles.length; i++) {
const file = imageFiles[i];
try {
const sprite = await createSpriteFromFile(file, i);
newSprites.push(sprite);
} catch (error) {
console.error('Error loading sprite:', error);
}
}
if (newSprites.length > 0) {
store.addSprites(newSprites);
emit('files-uploaded', newSprites);
store.showNotification(`Added ${newSprites.length} sprites successfully`);
}
};
const createSpriteFromFile = (file: File, index: number): Promise<Sprite> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
const img = new Image();
img.onload = () => {
resolve({
img,
width: img.width,
height: img.height,
x: 0,
y: 0,
name: file.name,
id: `sprite-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
uploadOrder: index
});
};
img.onerror = reject;
img.src = e.target?.result as string;
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
};
return {
fileInput,
isDragOver,
openFileDialog,
onDragOver,
onDragLeave,
onDrop,
onFileChange
};
}
});
</script>