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

const { width, height } = useWindowSize();

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

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

	const rect2 = new Konva.Rect({
		x: 180,
		y: 200,
		width: 100,
		height: 200,
		fill: 'green',
		name: 'rect',
		draggable: true,
	});
	layer.add(rect2);

	// 添加缩放
	const tr = new Konva.Transformer();
	layer.add(tr);
	tr.nodes([rect1, rect2]);

	const selectionRectangle = new Konva.Rect({
		fill: 'rgba(0,0,255,0.5)',
		visible: false,
		// disable events to not interrupt with events
		listening: false,
	});
	layer.add(selectionRectangle);

	let x1 = 0,
		y1 = 0,
		x2 = 0,
		y2 = 0;
	let selecting = false;
	stage.on('mousedown touchstart', e => {
		// do nothing if we mousedown on any shape
		if (e.target !== stage) {
			return;
		}
		e.evt.preventDefault();
		x1 = stage.getPointerPosition()!.x;
		y1 = stage.getPointerPosition()!.y;
		x2 = stage.getPointerPosition()!.x;
		y2 = stage.getPointerPosition()!.y;

		selectionRectangle.width(0);
		selectionRectangle.height(0);
		selecting = true;
	});

	stage.on('mousemove touchmove', e => {
		// do nothing if we didn't start selection
		if (!selecting) {
			return;
		}
		e.evt.preventDefault();
		x2 = stage.getPointerPosition()!.x;
		y2 = stage.getPointerPosition()!.y;

		selectionRectangle.setAttrs({
			visible: true,
			x: Math.min(x1, x2),
			y: Math.min(y1, y2),
			width: Math.abs(x2 - x1),
			height: Math.abs(y2 - y1),
		});
	});

	stage.on('mouseup touchend', e => {
		// do nothing if we didn't start selection
		selecting = false;
		if (!selectionRectangle.visible()) {
			return;
		}
		e.evt.preventDefault();
		// update visibility in timeout, so we can check it in click event
		selectionRectangle.visible(false);
		let shapes = stage.find('.rect');
		let box = selectionRectangle.getClientRect();
		let selected = shapes.filter(shape => Konva.Util.haveIntersection(box, shape.getClientRect()));
		tr.nodes(selected);
	});

	// clicks should select/deselect shapes
	stage.on('click tap', function (e) {
		// if we are selecting with rect, do nothing
		if (selectionRectangle.visible()) {
			return;
		}

		// if click on empty area - remove all selections
		if (e.target === stage) {
			tr.nodes([]);
			return;
		}

		// do nothing if clicked NOT on our rectangles
		if (!e.target.hasName('rect')) {
			return;
		}

		// do we pressed shift or ctrl?
		const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
		const isSelected = tr.nodes().indexOf(e.target) >= 0;

		if (!metaPressed && !isSelected) {
			// if no key pressed and the node is not selected
			// select just one
			tr.nodes([e.target]);
		} else if (metaPressed && isSelected) {
			// if we pressed keys and node was selected
			// we need to remove it from selection:
			const nodes = tr.nodes().slice(); // use slice to have new copy of array
			// remove node from array
			nodes.splice(nodes.indexOf(e.target), 1);
			tr.nodes(nodes);
		} else if (metaPressed && !isSelected) {
			// add the node into selection
			const nodes = tr.nodes().concat([e.target]);
			tr.nodes(nodes);
		}
	});

	stage.add(layer);
};

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

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

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