Skip to content

Commit a4db387

Browse files
committed
Drag to pan tile view (when zoomed)
1 parent 0c1bcec commit a4db387

1 file changed

Lines changed: 60 additions & 9 deletions

File tree

src/ThreeTiles.civet

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from solid-js import { createMemo, For, type JSX }
1+
from solid-js import { createEffect, createMemo, createSignal, For, type JSX }
22
operator { max } := Math
33
from @solid-primitives/tween import { createTween }
44

@@ -167,6 +167,12 @@ function ceilLog2(glues: number): number
167167
maxVal <<= 1
168168
nBits
169169

170+
function svgPoint(svg: SVGSVGElement, x: number, y: number): DOMPoint
171+
pt := svg.createSVGPoint()
172+
pt.x = x
173+
pt.y = y
174+
pt.matrixTransform svg.getScreenCTM()!.inverse()
175+
170176
export function unsignedToSigned(tiles: Prototile[], glues: number): {tiles: Prototile[], glues: number}
171177
// Remove aliasing
172178
tiles = for each tile of tiles
@@ -226,12 +232,57 @@ export function ThreeTiles(props: {tiles: Prototile[], glues: number, zoom: numb
226232
ease: (t) => 0.5 - Math.cos(Math.PI * t) / 2
227233
center := createMemo =>
228234
`${polys().wheelPoly.maxX()/2} ${polys().wheelPoly.maxY()/2}`
235+
width := createMemo => polys().shurikenPoly.maxX() + 2*margin
236+
height := createMemo => polys().shurikenPoly.maxY() + 2*margin
237+
238+
[panX, setPanX] := createSignal 0
239+
[panY, setPanY] := createSignal 0
240+
createEffect =>
241+
// Keep pan within bounds
242+
if panX() >= 0
243+
setPanX 0
244+
else
245+
if width() - panX() > width() * props.zoom
246+
setPanX -(width() * props.zoom - width())
247+
if panY() >= 0
248+
setPanY 0
249+
else
250+
if height() - panY() > height() * props.zoom
251+
setPanY -(height() * props.zoom - height())
252+
starts: Record<number, {
253+
panX: number
254+
panY: number
255+
start: {x: number, y: number}
256+
}> := {}
229257

230-
<svg viewBox=`${-margin} ${-margin} ${polys().shurikenPoly.maxX() + 2*margin} ${polys().shurikenPoly.maxY() + 2*margin}` width=`${props.zoom*100}%`>
231-
<Polygon .ptile turtle=polys().staplePoly>
232-
<g transform=`rotate(${angle()} ${center()})`>
233-
<Polygon .ptile turtle=polys().wheelPoly>
234-
<For each=polys().gluePolys>
235-
(poly) =>
236-
<Polygon .pglue turtle=poly>
237-
<Polygon .ptile turtle=polys().shurikenPoly>
258+
let svg!: SVGSVGElement
259+
<svg ref=svg viewBox=`${-margin} ${-margin} ${width()} ${height()}`
260+
onPointerDown=
261+
(e) =>
262+
starts[e.pointerId] = {
263+
panX(), panY()
264+
start: svgPoint svg, e.clientX, e.clientY
265+
}
266+
svg.setPointerCapture e.pointerId
267+
onPointerMove=
268+
(e) =>
269+
return unless starts[e.pointerId]?
270+
current := svgPoint svg, e.clientX, e.clientY
271+
{panX, panY, start} := starts[e.pointerId]
272+
setPanX panX + (current.x - start.x)
273+
setPanY panY + (current.y - start.y)
274+
onPointerUp=
275+
(e) =>
276+
delete starts[e.pointerId]
277+
onPointerLeave=
278+
(e) =>
279+
delete starts[e.pointerId]
280+
>
281+
<g transform=`translate(${panX()} ${panY()}) scale(${props.zoom})`>
282+
<Polygon .ptile turtle=polys().staplePoly>
283+
<g transform=`rotate(${angle()} ${center()})`>
284+
<Polygon .ptile turtle=polys().wheelPoly>
285+
<For each=polys().gluePolys>
286+
(poly) =>
287+
<Polygon .pglue turtle=poly>
288+
<Polygon .ptile turtle=polys().shurikenPoly>

0 commit comments

Comments
 (0)