[FEAT] Bug fixes
This commit is contained in:
@@ -9,6 +9,14 @@ html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Disable selection on images and canvases */
|
||||
img,
|
||||
canvas {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-100 antialiased font-sans;
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -85,13 +85,12 @@
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- Current frame sprites -->
|
||||
<!-- Current frame sprites - maintaining layer order -->
|
||||
<template v-for="layer in getVisibleLayers()" :key="layer.id">
|
||||
<img
|
||||
v-if="layer.sprites[currentFrameIndex]"
|
||||
:src="layer.sprites[currentFrameIndex].url"
|
||||
class="absolute"
|
||||
:class="{ 'cursor-move': isDraggable }"
|
||||
:style="{
|
||||
left: `${Math.round(getCellPosition(0).x + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].x)}px`,
|
||||
top: `${Math.round(getCellPosition(0).y + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].y)}px`,
|
||||
@@ -100,12 +99,29 @@
|
||||
imageRendering: settingsStore.pixelPerfect ? 'pixelated' : 'auto',
|
||||
transform: `rotate(${layer.sprites[currentFrameIndex].rotation || 0}deg) scale(${layer.sprites[currentFrameIndex].flipX ? -1 : 1}, ${layer.sprites[currentFrameIndex].flipY ? -1 : 1})`,
|
||||
}"
|
||||
@mousedown="startDrag($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||
@touchstart="handleTouchStart($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||
@contextmenu.prevent="openContextMenu($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||
draggable="false"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- Invisible drag overlay for active layer sprite - sits on top to capture mouse events -->
|
||||
<template v-if="isDraggable">
|
||||
<template v-for="layer in getVisibleLayers()" :key="'drag-' + layer.id">
|
||||
<div
|
||||
v-if="layer.sprites[currentFrameIndex] && (layer.id === props.activeLayerId || repositionAllLayers)"
|
||||
class="absolute cursor-move"
|
||||
:style="{
|
||||
left: `${Math.round(getCellPosition(0).x + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].x)}px`,
|
||||
top: `${Math.round(getCellPosition(0).y + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].y)}px`,
|
||||
width: `${Math.round(layer.sprites[currentFrameIndex].width)}px`,
|
||||
height: `${Math.round(layer.sprites[currentFrameIndex].height)}px`,
|
||||
zIndex: 100,
|
||||
}"
|
||||
@mousedown="startDrag($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||
@touchstart="handleTouchStart($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Mobile zoom controls -->
|
||||
@@ -320,6 +336,17 @@
|
||||
});
|
||||
|
||||
const getVisibleLayers = () => props.layers.filter(l => l.visible);
|
||||
// Reversed order so active layer renders on top for drag operations
|
||||
const getVisibleLayersReversed = () => {
|
||||
const visible = props.layers.filter(l => l.visible);
|
||||
// Put active layer last so it renders on top
|
||||
const activeIdx = visible.findIndex(l => l.id === props.activeLayerId);
|
||||
if (activeIdx > -1) {
|
||||
const active = visible.splice(activeIdx, 1)[0];
|
||||
visible.push(active);
|
||||
}
|
||||
return visible;
|
||||
};
|
||||
const maxFrames = () => Math.max(0, ...getVisibleLayers().map(l => l.sprites.length));
|
||||
|
||||
const { currentFrameIndex, isPlaying, fps, hiddenFrames, visibleFrames, visibleFramesCount, visibleFrameIndex, visibleFrameNumber, togglePlayback, nextFrame, previousFrame, handleSliderInput, toggleHiddenFrame, showAllFrames, hideAllFrames, stopAnimation } = useAnimationFrames({
|
||||
|
||||
@@ -615,27 +615,27 @@
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
};
|
||||
const insertIndex = frameIndex + fileIdx;
|
||||
if (insertIndex < layer.sprites.length) {
|
||||
layer.sprites = [...layer.sprites.slice(0, insertIndex), sprite, ...layer.sprites.slice(insertIndex + 1)];
|
||||
} else {
|
||||
while (layer.sprites.length < insertIndex) {
|
||||
layer.sprites.push({
|
||||
id: crypto.randomUUID(),
|
||||
file: new File([], 'empty'),
|
||||
img: new Image(),
|
||||
url: '',
|
||||
width: 0,
|
||||
height: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
});
|
||||
}
|
||||
layer.sprites = [...layer.sprites, sprite];
|
||||
const targetIndex = frameIndex + fileIdx;
|
||||
|
||||
// Extend the array with empty slots if needed
|
||||
while (layer.sprites.length <= targetIndex) {
|
||||
layer.sprites.push({
|
||||
id: crypto.randomUUID(),
|
||||
file: new File([], 'empty'),
|
||||
img: new Image(),
|
||||
url: '',
|
||||
width: 0,
|
||||
height: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
flipX: false,
|
||||
flipY: false,
|
||||
});
|
||||
}
|
||||
|
||||
// Now replace at target index (either existing sprite or empty placeholder)
|
||||
layer.sprites = [...layer.sprites.slice(0, targetIndex), sprite, ...layer.sprites.slice(targetIndex + 1)];
|
||||
};
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user