<script setup lang="ts">
import { useWindowSize } from '@vueuse/core';
import Konva from 'konva/lib';
import { onMounted } from 'vue';

const { width, height } = useWindowSize();

const initial = () => {
	const stage = new Konva.Stage({ container: 'container', width: width.value, height: height.value });
	const layer = new Konva.Layer();
	stage.add(layer);

	const xSnaps = Math.round(stage.width() / 100);
	const ySnaps = Math.round(stage.height() / 100);
	const cellWidth = stage.width() / xSnaps;
	const cellHeight = stage.height() / ySnaps;

	for (let i = 0; i < xSnaps; i++) {
		layer.add(
			new Konva.Line({
				x: i * cellWidth,
				points: [0, 0, 0, stage.height()],
				stroke: '#96e04d',
				strokeWidth: 1,
			}),
		);
	}

	for (let i = 0; i < ySnaps; i++) {
		layer.add(
			new Konva.Line({
				y: i * cellHeight,
				// points: [0, 0, stage.width(), 0],
				points: [0, 0, stage.width(), 0],
				stroke: '#96e04d',
				strokeWidth: 1,
			}),
		);
	}

	const rect = new Konva.Rect({
		x: 90,
		y: 90,
		width: 100,
		height: 100,
		fill: 'red',
		draggable: true,
	});
	layer.add(rect);

	const tr = new Konva.Transformer({
		nodes: [rect],
		anchorDragBoundFunc: function (oldPos, newPos, event) {
			// oldPos - is old absolute position of the anchor
			// newPos - is a new (possible) absolute position of the anchor based on pointer position
			// it is possible that anchor will have a different absolute position after this function
			// because every anchor has its own limits on position, based on resizing logic

			// do not snap rotating point
			if (tr.getActiveAnchor() === 'rotater') {
				return newPos;
			}

			const dist = Math.sqrt(Math.pow(newPos.x - oldPos.x, 2) + Math.pow(newPos.y - oldPos.y, 2));

			// do not do any snapping with new absolute position (pointer position)
			// is too far away from old position
			if (dist > 10) {
				return newPos;
			}

			const closestX = Math.round(newPos.x / cellWidth) * cellWidth;
			const diffX = Math.abs(newPos.x - closestX);

			const closestY = Math.round(newPos.y / cellHeight) * cellHeight;
			const diffY = Math.abs(newPos.y - closestY);

			const snappedX = diffX < 10;
			const snappedY = diffY < 10;

			// a bit different snap strategies based on snap direction
			// we need to reuse old position for better UX
			if (snappedX && !snappedY) {
				return {
					x: closestX,
					y: oldPos.y,
				};
			} else if (snappedY && !snappedX) {
				return {
					x: oldPos.x,
					y: closestY,
				};
			} else if (snappedX && snappedY) {
				return {
					x: closestX,
					y: closestY,
				};
			}
			return newPos;
		},
	});
	layer.add(tr);
};

onMounted(() => {
	initial();
});
</script>

<template>
	<div id="container"></div>
</template>

<style scoped lang="scss"></style>
