File size: 3,103 Bytes
70b8e47
66ed450
 
32561d8
66ed450
a6e7e8f
32561d8
66ed450
 
560b99e
 
66ed450
560b99e
32561d8
 
560b99e
66ed450
560b99e
66ed450
 
560b99e
32561d8
560b99e
32561d8
 
 
66ed450
 
35946a9
32561d8
 
 
 
66ed450
 
 
 
560b99e
 
304976c
66ed450
a6e7e8f
 
 
 
 
 
 
66ed450
560b99e
 
66ed450
560b99e
66ed450
1d701d3
66ed450
70b8e47
 
560b99e
66ed450
 
 
32561d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66ed450
32561d8
 
 
 
 
 
70b8e47
 
 
66ed450
 
1d701d3
66ed450
 
560b99e
70b8e47
 
560b99e
 
70b8e47
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<script lang="ts">
	import { zoom, type ZoomTransform, zoomIdentity } from 'd3-zoom';
	import { select } from 'd3-selection';
	import { scaleLinear } from 'd3-scale';
	import { onMount } from 'svelte';
	import { currZoomTransform, myPresence, isPrompting, clickedPosition } from '$lib/store';

	const height = 512 * 5;
	const width = 512 * 5;

	let canvasEl: HTMLCanvasElement;
	let containerEl: HTMLDivElement;
	let canvasCtx: CanvasRenderingContext2D;
	let xScale: (x: number) => number;
	let yScale: (y: number) => number;

	const margin = { top: 100, right: 100, bottom: 100, left: 100 };
	const extent = [
		[-margin.left, -margin.top],
		[width + margin.right, height + margin.bottom]
	] as [[number, number], [number, number]];

	onMount(() => {
		xScale = scaleLinear().domain([0, width]).range([0, width]);
		yScale = scaleLinear().domain([0, height]).range([0, height]);

		const scale = width / containerEl.clientWidth;
		const zoomHandler = zoom()
			.scaleExtent([1 / scale / 1.5, 1])
			// .translateExtent([
			// 	[0, 0],
			// 	[width, height]
			// ])
			// .translateExtent(extent)
			.clickDistance(2)
			.on('zoom', zoomed);

		select(canvasEl.parentElement)
			.call(zoomHandler as any)
			// .call(zoomHandler.scaleTo as any, 1 / scale)
			.on('pointermove', handlePointerMove)
			.on('pointerleave', handlePointerLeave)
			.on('dblclick.zoom', null)
			.on('click', () => {
				$isPrompting = true;
				$clickedPosition = $myPresence.cursor;
				console.log($clickedPosition);
			});

		canvasCtx = canvasEl.getContext('2d') as CanvasRenderingContext2D;
		canvasCtx.fillStyle = 'red';
		canvasCtx.rect(10, 10, 160, 90);
		canvasCtx.fill();
		canvasCtx.strokeStyle = 'blue';
		canvasCtx.lineWidth = 10;
		canvasCtx.strokeRect(0, 0, width, height);
	});

	function zoomed(e: Event) {
		const transform = ($currZoomTransform = e.transform);
		canvasEl.style.transform = `translate(${transform.x}px, ${transform.y}px) scale(${transform.k})`;
	}

	const r = 8;
	function round(p, n) {
		return p % n < n / 2 ? p - (p % n) : p + n - (p % n);
	}
	const grid = 8;

	// Update cursor presence to current pointer location
	function handlePointerMove(event: PointerEvent) {
		event.preventDefault();
		const x = Math.round(event.layerX / grid) * grid; //round(Math.max(r, Math.min(512 * 5 - r, event.clientX)), 100);
		const y = Math.round(event.layerY / grid) * grid; //round(Math.max(r, Math.min(512 * 5 - r, event.clientY)), 100);
		// const x = round(Math.max(r, Math.min(512 * 5 - r, event.clientX)), grid);
		// const y = round(Math.max(r, Math.min(512 * 5 - r, event.clientY)), grid);

		$myPresence = {
			cursor: {
				x,
				y
			}
		};
	}

	// When the pointer leaves the page, set cursor presence to null
	function handlePointerLeave() {
		$myPresence = {
			cursor: null
		};
	}
</script>

<div
	bind:this={containerEl}
	class="absolute top-0 left-0 right-0 bottom-0 overflow-hidden border-4 border-black z-0"
>
	<canvas bind:this={canvasEl} {width} {height} class="absolute top-0 left-0" />
</div>

<style lang="postcss" scoped>
	canvas {
		transform-origin: 0 0;
	}
</style>