-
{{ error }}
-
-
- No board layouts found
-
-
-
+
+
+
+
{{ error }}
+
+
+
+ No board layouts found
+
+
+
-
-
-
diff --git a/web/components/PartListItem.vue b/web/components/PartListItem.vue
index 0773f30..4754a61 100644
--- a/web/components/PartListItem.vue
+++ b/web/components/PartListItem.vue
@@ -14,7 +14,6 @@ const height = usePx(() => props.placement.lengthM);
const left = usePx(() => props.placement.leftM);
const bottom = usePx(() => props.placement.bottomM);
-const getPx = useGetPx();
const fontSize = usePx(() =>
Math.min(
props.placement.widthM / 2,
@@ -44,6 +43,12 @@ const showPartNumbers = useShowPartNumbers();
{{ placement.partNumber }}
-
+
+
+
diff --git a/web/components/ScaleController.vue b/web/components/ScaleController.vue
index 5433bba..84de5f4 100644
--- a/web/components/ScaleController.vue
+++ b/web/components/ScaleController.vue
@@ -1,8 +1,15 @@
@@ -13,23 +20,24 @@ const percent = computed(() => `${Math.round(scale.value * 100)}%`);
size="lg"
color="black"
icon="i-heroicons-minus"
- @click="zoomOut"
+ @click="emit('zoomOut')"
/>
{{ percent }}
diff --git a/web/composables/useGetPx.ts b/web/composables/useGetPx.ts
index 4be0d53..5a7b4e2 100644
--- a/web/composables/useGetPx.ts
+++ b/web/composables/useGetPx.ts
@@ -1,4 +1,3 @@
export default function () {
- const scale = useScale();
- return (value: number) => `${value * 500 * scale.value}px`;
+ return (value: number) => `${value * 500}px`;
}
diff --git a/web/composables/usePanZoom.ts b/web/composables/usePanZoom.ts
new file mode 100644
index 0000000..eec09fa
--- /dev/null
+++ b/web/composables/usePanZoom.ts
@@ -0,0 +1,51 @@
+import type { PanZoom } from 'panzoom';
+import panzoom from 'panzoom';
+
+export default function (container: Ref
) {
+ let instance = ref();
+ const scale = ref();
+
+ whenever(container, (container) => {
+ instance.value = panzoom(container, {
+ autocenter: true,
+ minZoom: 0.2,
+ maxZoom: 10,
+ });
+ scale.value = instance.value.getTransform().scale;
+ instance.value.on('zoom', () => {
+ scale.value = instance.value?.getTransform().scale;
+ });
+ });
+ whenever(
+ () => !container.value,
+ () => {
+ instance.value?.dispose();
+ },
+ );
+ onUnmounted(() => {
+ instance.value?.dispose();
+ });
+
+ const setZoom = (cb: (scale: number) => number, x?: number, y?: number) => {
+ if (instance.value == null) return;
+ const current = instance.value.getTransform();
+ const currentScale = current.scale;
+ const newScale = cb(current.scale);
+ instance.value?.smoothZoom(
+ x ?? current.x,
+ y ?? current.y,
+ newScale / currentScale,
+ );
+ };
+ const zoomBy = (increment: number) => setZoom((scale) => scale + increment);
+
+ return {
+ scale,
+ zoomIn: () => zoomBy(0.1),
+ zoomOut: () => zoomBy(-0.1),
+ resetZoom: () => {
+ setZoom(() => 1);
+ instance.value?.smoothMoveTo(0, 0);
+ },
+ };
+}
diff --git a/web/composables/useScale.ts b/web/composables/useScale.ts
deleted file mode 100644
index b77105e..0000000
--- a/web/composables/useScale.ts
+++ /dev/null
@@ -1 +0,0 @@
-export default createGlobalState(() => useSessionStorage('@cutlist/scale', 1));
diff --git a/web/composables/useScaleControls.ts b/web/composables/useScaleControls.ts
deleted file mode 100644
index ffbcd65..0000000
--- a/web/composables/useScaleControls.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export default function () {
- const scale = useScale();
- return {
- zoomIn: () => void (scale.value += 0.1),
- zoomOut: () => void (scale.value = Math.max(scale.value - 0.1, 0.1)),
- resetZoom: () => void (scale.value = 1),
- };
-}
diff --git a/web/pages/index.vue b/web/pages/index.vue
index f4137e7..d22103f 100644
--- a/web/pages/index.vue
+++ b/web/pages/index.vue
@@ -7,23 +7,23 @@ const isExpanded = useIsExpanded();
-
+