부동산에서 받은 평면도 이미지가 있다. 이걸 배경에 깔고 위에 가구 배치하면 편할 것 같다.

파일 선택
<input
type="file"
accept="image/png,image/jpeg,image/gif,image/webp"
@change="handleFileSelect"
/>
이미지 로드
function handleFileSelect(e: Event) {
const input = e.target as HTMLInputElement;
const file = input.files?.[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (event) => {
const dataUrl = event.target?.result as string;
loadImage(dataUrl);
};
reader.readAsDataURL(file);
}
function loadImage(dataUrl: string) {
const img = new Image();
img.onload = () => {
backgroundImage.value = {
src: dataUrl,
width: img.width,
height: img.height,
x: 0,
y: 0,
opacity: 0.5,
scale: 1,
locked: false
};
};
img.src = dataUrl;
}
Konva에 렌더링
<v-image
v-if="backgroundImage"
:config="{
image: imageElement,
x: backgroundImage.x,
y: backgroundImage.y,
width: backgroundImage.width * backgroundImage.scale,
height: backgroundImage.height * backgroundImage.scale,
opacity: backgroundImage.opacity,
draggable: !backgroundImage.locked
}"
/>
Konva Image는 HTMLImageElement가 필요:
const imageElement = ref<HTMLImageElement | null>(null);
watch(() => backgroundImage.value?.src, (src) => {
if (!src) {
imageElement.value = null;
return;
}
const img = new Image();
img.onload = () => {
imageElement.value = img;
};
img.src = src;
});
투명도 조절
이미지가 너무 진하면 위에 그린 게 안 보임.
<input
type="range"
min="0.1"
max="1"
step="0.1"
v-model.number="backgroundImage.opacity"
/>
슬라이더로 0.1 ~ 1.0 조절.
크기 조절
평면도 실제 치수랑 맞추려면 크기 조절 필요:
<input
type="range"
min="0.1"
max="3"
step="0.1"
v-model.number="backgroundImage.scale"
/>
눈대중으로 방 크기 맞추면 됨.
잠금 기능
배경 이미지 실수로 움직이면 짜증남.
function toggleLock() {
backgroundImage.value.locked = !backgroundImage.value.locked;
}
잠금 상태면 draggable: false.
삭제
function removeImage() {
backgroundImage.value = null;
imageElement.value = null;
}
레이어 순서
이미지는 가구 아래에 있어야 함:
<v-layer>
<!-- 배경 이미지 (맨 아래) -->
<v-image ... />
</v-layer>
<v-layer>
<!-- 가구들 (위) -->
</v-layer>
Layer 순서로 조절.
다음 글에서 저장/불러오기.