This commit is contained in:
Dennis Postma 2025-04-03 04:16:03 +02:00
parent 9c0f10b977
commit 5218669744
3 changed files with 106 additions and 0 deletions

View File

@ -73,6 +73,7 @@
const isModalOpen = computed(() => store.isModalOpen.value);
const sprites = computed(() => store.sprites.value);
const animation = computed(() => store.animation);
const previewBorder = computed(() => store.previewBorder);
const currentFrame = ref(0);
const position = ref({ x: 0, y: 0 });
@ -268,6 +269,17 @@
{ deep: true }
);
// Watch for changes in border settings to update the preview
watch(
() => previewBorder.value,
() => {
if (isModalOpen.value && sprites.value.length > 0) {
store.renderAnimationFrame(currentFrame.value);
}
},
{ deep: true }
);
// Expose openModal for external use
defineExpose({ openModal });
</script>

View File

@ -59,6 +59,36 @@
</div>
</div>
<!-- Preview Border Settings Section -->
<div class="mb-8">
<h3 class="text-lg font-medium text-gray-200 mb-4 flex items-center gap-2"><i class="fas fa-border-style text-blue-500"></i> Preview border</h3>
<div class="mb-4">
<div class="flex items-center justify-between mb-2">
<label class="text-sm text-gray-400">Enable border (preview only)</label>
<div class="relative inline-block w-10 align-middle select-none">
<input type="checkbox" v-model="previewBorder.enabled" id="toggle-border" class="sr-only" />
<label for="toggle-border" class="block h-6 rounded-full bg-gray-600 cursor-pointer"></label>
<div :class="{ 'translate-x-4': previewBorder.enabled, 'translate-x-0': !previewBorder.enabled }" class="absolute left-0 top-0 w-6 h-6 rounded-full bg-white border border-gray-300 transform transition-transform duration-200 ease-in-out"></div>
</div>
</div>
<div class="grid grid-cols-2 gap-4 mt-4" v-if="previewBorder.enabled">
<div>
<label class="block text-sm text-gray-400 mb-2">Border color</label>
<input type="color" v-model="previewBorder.color" class="w-full h-8 bg-gray-700 rounded cursor-pointer" />
</div>
<div>
<label class="block text-sm text-gray-400 mb-2">Border width: {{ previewBorder.width }}px</label>
<input type="range" v-model.number="previewBorder.width" min="1" max="10" class="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer" />
</div>
</div>
<div class="text-xs text-gray-400 mt-2">
<i class="fas fa-info-circle mr-1"></i> Border will only be visible in the preview and won't be included in the downloaded spritesheet.
</div>
</div>
</div>
<!-- Keyboard Shortcuts Section -->
<div>
<h3 class="text-lg font-medium text-gray-200 mb-4 flex items-center gap-2"><i class="fas fa-keyboard text-blue-500"></i> Keyboard shortcuts</h3>
@ -93,6 +123,7 @@
const store = useSpritesheetStore();
const sprites = computed(() => store.sprites.value);
const isModalOpen = computed(() => store.isSettingsModalOpen.value);
const previewBorder = computed(() => store.previewBorder);
// Column count control
const columnCount = ref(store.columns.value);
@ -130,3 +161,47 @@
store.showNotification(`Column count updated to ${columnCount.value}`);
};
</script>
<style scoped>
/* Toggle switch styles */
input[type='checkbox'] + label {
width: 2.5rem;
}
input[type='checkbox']:checked + label {
background-color: #0096ff;
}
/* Range input styles */
input[type='range']::-webkit-slider-thumb {
appearance: none;
width: 15px;
height: 15px;
background: #0096ff;
border-radius: 50%;
cursor: pointer;
}
input[type='range']::-moz-range-thumb {
width: 15px;
height: 15px;
background: #0096ff;
border-radius: 50%;
cursor: pointer;
}
/* Color input styles */
input[type='color'] {
-webkit-appearance: none;
border: none;
}
input[type='color']::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type='color']::-webkit-color-swatch {
border: none;
border-radius: 4px;
}
</style>

View File

@ -41,6 +41,13 @@ const isSettingsModalOpen = ref(false);
const isSpritesModalOpen = ref(false);
const zoomLevel = ref(1); // Default zoom level (1 = 100%)
// Preview border settings
const previewBorder = reactive({
enabled: false,
color: '#ff0000', // Default red color
width: 2 // Default width in pixels
});
export function useSpritesheetStore() {
const animation = reactive<AnimationState>({
canvas: null,
@ -399,6 +406,10 @@ export function useSpritesheetStore() {
animation.ctx.clearRect(0, 0, animation.canvas.width, animation.canvas.height);
// Draw background (transparent by default)
animation.ctx.fillStyle = 'transparent';
animation.ctx.fillRect(0, 0, animation.canvas.width, animation.canvas.height);
const currentSprite = sprites.value[frameIndex % sprites.value.length];
const cellX = Math.floor(currentSprite.x / cellSize.width);
@ -408,6 +419,13 @@ export function useSpritesheetStore() {
const offsetY = currentSprite.y - cellY * cellSize.height;
animation.ctx.drawImage(currentSprite.img, offsetX, offsetY);
// Draw border if enabled (only for preview, not included in download)
if (previewBorder.enabled) {
animation.ctx.strokeStyle = previewBorder.color;
animation.ctx.lineWidth = previewBorder.width;
animation.ctx.strokeRect(0, 0, animation.canvas.width, animation.canvas.height);
}
}
function animationLoop(timestamp?: number) {
@ -480,6 +498,7 @@ export function useSpritesheetStore() {
animation,
notification,
zoomLevel,
previewBorder,
addSprites,
updateCellSize,
updateCanvasSize,