Spaces:
Runtime error
Runtime error
center zoom free translation
Browse files- frontend/package.json +2 -0
- frontend/src/lib/PaintCanvas.svelte +45 -9
frontend/package.json
CHANGED
@@ -17,6 +17,7 @@
|
|
17 |
"@tailwindcss/forms": "^0.5.3",
|
18 |
"@tailwindcss/line-clamp": "^0.4.2",
|
19 |
"@types/cookie": "^0.5.1",
|
|
|
20 |
"@types/d3-drag": "^3.0.1",
|
21 |
"@types/d3-selection": "^3.0.3",
|
22 |
"@types/d3-zoom": "^3.0.1",
|
@@ -42,6 +43,7 @@
|
|
42 |
"dependencies": {
|
43 |
"@fontsource/fira-mono": "^4.5.0",
|
44 |
"@liveblocks/client": "^0.18.2",
|
|
|
45 |
"d3-drag": "^3.0.0",
|
46 |
"d3-selection": "^3.0.0",
|
47 |
"d3-zoom": "^3.0.0",
|
|
|
17 |
"@tailwindcss/forms": "^0.5.3",
|
18 |
"@tailwindcss/line-clamp": "^0.4.2",
|
19 |
"@types/cookie": "^0.5.1",
|
20 |
+
"@types/d3-array": "^3.0.3",
|
21 |
"@types/d3-drag": "^3.0.1",
|
22 |
"@types/d3-selection": "^3.0.3",
|
23 |
"@types/d3-zoom": "^3.0.1",
|
|
|
43 |
"dependencies": {
|
44 |
"@fontsource/fira-mono": "^4.5.0",
|
45 |
"@liveblocks/client": "^0.18.2",
|
46 |
+
"d3-array": "^3.2.0",
|
47 |
"d3-drag": "^3.0.0",
|
48 |
"d3-selection": "^3.0.0",
|
49 |
"d3-zoom": "^3.0.0",
|
frontend/src/lib/PaintCanvas.svelte
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { zoom, zoomIdentity } from 'd3-zoom';
|
|
|
3 |
import { select } from 'd3-selection';
|
4 |
import { onMount } from 'svelte';
|
5 |
import { PUBLIC_UPLOADS } from '$env/static/public';
|
@@ -56,8 +57,24 @@
|
|
56 |
renderImages(promptImgList);
|
57 |
}
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
onMount(() => {
|
60 |
-
const padding =
|
61 |
const scale =
|
62 |
(width + padding * 2) /
|
63 |
(containerEl.clientHeight > containerEl.clientWidth
|
@@ -65,17 +82,27 @@
|
|
65 |
: containerEl.clientHeight);
|
66 |
const zoomHandler = zoom()
|
67 |
.scaleExtent([1 / scale / 2, 3])
|
68 |
-
.translateExtent([
|
69 |
-
|
70 |
-
|
71 |
-
])
|
72 |
.tapDistance(10)
|
73 |
.on('zoom', zoomed);
|
74 |
|
75 |
const selection = select($canvasEl.parentElement)
|
76 |
.call(zoomHandler as any)
|
77 |
-
.call(
|
78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
.on('pointermove', handlePointerMove)
|
80 |
.on('pointerleave', handlePointerLeave);
|
81 |
|
@@ -86,8 +113,17 @@
|
|
86 |
(containerEl.clientHeight > containerEl.clientWidth
|
87 |
? containerEl.clientWidth
|
88 |
: containerEl.clientHeight);
|
89 |
-
selection.call(
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
}
|
92 |
window.addEventListener('resize', zoomReset);
|
93 |
return () => {
|
|
|
1 |
<script lang="ts">
|
2 |
import { zoom, zoomIdentity } from 'd3-zoom';
|
3 |
+
import { min } from 'd3-array';
|
4 |
import { select } from 'd3-selection';
|
5 |
import { onMount } from 'svelte';
|
6 |
import { PUBLIC_UPLOADS } from '$env/static/public';
|
|
|
57 |
renderImages(promptImgList);
|
58 |
}
|
59 |
|
60 |
+
function to_bbox(
|
61 |
+
W: number,
|
62 |
+
H: number,
|
63 |
+
center: { x: number; y: number },
|
64 |
+
w: number,
|
65 |
+
h: number,
|
66 |
+
margin: number
|
67 |
+
) {
|
68 |
+
//https://bl.ocks.org/fabiovalse/b9224bfd64ca96c47f8cdcb57b35b8e2
|
69 |
+
const kw = (W - margin) / w;
|
70 |
+
const kh = (H - margin) / h;
|
71 |
+
const k = min([kw, kh]);
|
72 |
+
const x = W / 2 - center.x * k;
|
73 |
+
const y = H / 2 - center.y * k;
|
74 |
+
return zoomIdentity.translate(x, y).scale(k);
|
75 |
+
}
|
76 |
onMount(() => {
|
77 |
+
const padding = 100;
|
78 |
const scale =
|
79 |
(width + padding * 2) /
|
80 |
(containerEl.clientHeight > containerEl.clientWidth
|
|
|
82 |
: containerEl.clientHeight);
|
83 |
const zoomHandler = zoom()
|
84 |
.scaleExtent([1 / scale / 2, 3])
|
85 |
+
// .translateExtent([
|
86 |
+
// [-padding, -padding],
|
87 |
+
// [width + padding, height + padding]
|
88 |
+
// ])
|
89 |
.tapDistance(10)
|
90 |
.on('zoom', zoomed);
|
91 |
|
92 |
const selection = select($canvasEl.parentElement)
|
93 |
.call(zoomHandler as any)
|
94 |
+
.call(
|
95 |
+
zoomHandler.transform as any,
|
96 |
+
to_bbox(
|
97 |
+
containerEl.clientWidth,
|
98 |
+
containerEl.clientHeight,
|
99 |
+
{ x: width / 2, y: height / 2 },
|
100 |
+
width,
|
101 |
+
height,
|
102 |
+
padding
|
103 |
+
)
|
104 |
+
)
|
105 |
+
// .call(zoomHandler.scaleTo as any, 1 / scale)
|
106 |
.on('pointermove', handlePointerMove)
|
107 |
.on('pointerleave', handlePointerLeave);
|
108 |
|
|
|
113 |
(containerEl.clientHeight > containerEl.clientWidth
|
114 |
? containerEl.clientWidth
|
115 |
: containerEl.clientHeight);
|
116 |
+
selection.call(
|
117 |
+
zoomHandler.transform as any,
|
118 |
+
to_bbox(
|
119 |
+
containerEl.clientWidth,
|
120 |
+
containerEl.clientHeight,
|
121 |
+
{ x: width / 2, y: height / 2 },
|
122 |
+
width,
|
123 |
+
height,
|
124 |
+
padding
|
125 |
+
)
|
126 |
+
);
|
127 |
}
|
128 |
window.addEventListener('resize', zoomReset);
|
129 |
return () => {
|