Allow concatenating images
This commit is contained in:
@@ -17,6 +17,14 @@ function onFileChange(event: Event): void {
|
|||||||
}
|
}
|
||||||
reader.readAsDataURL(files[0]);
|
reader.readAsDataURL(files[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDragStart(event: DragEvent, idx: number): void {
|
||||||
|
event.dataTransfer!.setData('text/plain', idx.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
images
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -24,7 +32,7 @@ function onFileChange(event: Event): void {
|
|||||||
<input id="file-upload" type="file" @change="onFileChange">
|
<input id="file-upload" type="file" @change="onFileChange">
|
||||||
<label for="file-upload" class="button">Add</label>
|
<label for="file-upload" class="button">Add</label>
|
||||||
<div v-for="(img, idx) in images" :key="idx" class="image-file">
|
<div v-for="(img, idx) in images" :key="idx" class="image-file">
|
||||||
<img :src="img.src" width="64" height="64" alt="" @click="$emit('selected', img)">
|
<img :src="img.src" width="64" height="64" alt="" draggable="true" @click="$emit('selected', img)" @dragstart="onDragStart($event, idx)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@@ -4,6 +4,8 @@ import { blackAndWhite, grayScale } from '../processing/gray-scale.ts';
|
|||||||
import ImageCollection from './ImageCollection.vue';
|
import ImageCollection from './ImageCollection.vue';
|
||||||
|
|
||||||
const canvas = ref<HTMLCanvasElement | null>(null);
|
const canvas = ref<HTMLCanvasElement | null>(null);
|
||||||
|
const collection = ref<typeof ImageCollection>();
|
||||||
|
const overlay = ref<string | null>(null);
|
||||||
const currentWidth = ref(100);
|
const currentWidth = ref(100);
|
||||||
const currentHeight = ref(100);
|
const currentHeight = ref(100);
|
||||||
let img: HTMLImageElement;
|
let img: HTMLImageElement;
|
||||||
@@ -44,11 +46,45 @@ function onChangeSlideHeight() {
|
|||||||
canvas.value!.height = height;
|
canvas.value!.height = height;
|
||||||
ctx.drawImage(img, 0, 0, canvas.value!.width, height);
|
ctx.drawImage(img, 0, 0, canvas.value!.width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDragOver(event: DragEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.dataTransfer!.dropEffect = 'copy';
|
||||||
|
if (event.offsetX > canvas.value!.width / 2) {
|
||||||
|
overlay.value = 'right';
|
||||||
|
} else {
|
||||||
|
overlay.value = 'bottom';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDrop(event: DragEvent) {
|
||||||
|
event.preventDefault();
|
||||||
|
overlay.value = null;
|
||||||
|
const id = event.dataTransfer!.getData('text/plain');
|
||||||
|
const img: HTMLImageElement = collection.value!.images[parseInt(id)];
|
||||||
|
if (event.offsetX > canvas.value!.width / 2) {
|
||||||
|
const dx = canvas.value!.width;
|
||||||
|
const imageData = ctx.getImageData(0, 0, canvas.value!.width, canvas.value!.height);
|
||||||
|
canvas.value!.width += img.width;
|
||||||
|
ctx.putImageData(imageData, 0, 0)
|
||||||
|
ctx.drawImage(img, dx, 0);
|
||||||
|
} else {
|
||||||
|
const dy = canvas.value!.height;
|
||||||
|
const imageData = ctx.getImageData(0, 0, canvas.value!.width, canvas.value!.height);
|
||||||
|
canvas.value!.height += img.height;
|
||||||
|
ctx.putImageData(imageData, 0, 0)
|
||||||
|
ctx.drawImage(img, 0, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDragLeave() {
|
||||||
|
overlay.value = null;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="editor">
|
<div class="editor">
|
||||||
<ImageCollection @selected="onSelected" />
|
<ImageCollection ref="collection" @selected="onSelected" />
|
||||||
<div class="working-area">
|
<div class="working-area">
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<button @click="blackAndWhiteApply">
|
<button @click="blackAndWhiteApply">
|
||||||
@@ -60,8 +96,9 @@ function onChangeSlideHeight() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<input v-model="currentHeight" type="range" min="1" max="200" value="100" orient="vertical" @change="onChangeSlideHeight">
|
<input v-model="currentHeight" type="range" min="1" max="200" value="100" orient="vertical" @change="onChangeSlideHeight">
|
||||||
<div class="preview">
|
<div class="preview" @dragover="onDragOver" @dragleave="onDragLeave" @drop="onDrop">
|
||||||
<canvas ref="canvas"></canvas>
|
<canvas ref="canvas"></canvas>
|
||||||
|
<div v-if="overlay" :class="`overlay overlay-${overlay}`"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
@@ -83,3 +83,28 @@ button:focus-visible,
|
|||||||
background-color: #f9f9f9;
|
background-color: #f9f9f9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
place-content: center;
|
||||||
|
z-index: 100;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.overlay-right {
|
||||||
|
width: 50%;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
.overlay-bottom {
|
||||||
|
height: 50%;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user