|
|
@@ -1,12 +1,16 @@
|
|
1
|
1
|
import { createSelectorHook, createState } from "@state-designer/react"
|
|
2
|
2
|
import {
|
|
3
|
3
|
clamp,
|
|
|
4
|
+ getBoundsCenter,
|
|
4
|
5
|
getChildren,
|
|
5
|
6
|
getCommonBounds,
|
|
6
|
7
|
getPage,
|
|
|
8
|
+ getSelectedBounds,
|
|
|
9
|
+ getSelectedShapes,
|
|
7
|
10
|
getShape,
|
|
8
|
11
|
getSiblings,
|
|
9
|
12
|
screenToWorld,
|
|
|
13
|
+ setZoomCSS,
|
|
10
|
14
|
} from "utils/utils"
|
|
11
|
15
|
import * as vec from "utils/vec"
|
|
12
|
16
|
import {
|
|
|
@@ -68,6 +72,13 @@ const state = createState({
|
|
68
|
72
|
SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
|
|
69
|
73
|
TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
|
|
70
|
74
|
RESET_CAMERA: "resetCamera",
|
|
|
75
|
+ ZOOMED_TO_FIT: "zoomCameraToFit",
|
|
|
76
|
+ ZOOMED_TO_SELECTION: { if: "hasSelection", do: "zoomCameraToSelection" },
|
|
|
77
|
+ ZOOMED_TO_ACTUAL: {
|
|
|
78
|
+ if: "hasSelection",
|
|
|
79
|
+ do: "zoomCameraToSelectionActual",
|
|
|
80
|
+ else: "zoomCameraToActual",
|
|
|
81
|
+ },
|
|
71
|
82
|
},
|
|
72
|
83
|
initial: "loading",
|
|
73
|
84
|
states: {
|
|
|
@@ -480,7 +491,7 @@ const state = createState({
|
|
480
|
491
|
return data.isReadOnly
|
|
481
|
492
|
},
|
|
482
|
493
|
distanceImpliesDrag(data, payload: PointerInfo) {
|
|
483
|
|
- return vec.dist2(payload.origin, payload.point) > 16
|
|
|
494
|
+ return vec.dist2(payload.origin, payload.point) > 8
|
|
484
|
495
|
},
|
|
485
|
496
|
isPointedShapeSelected(data) {
|
|
486
|
497
|
return data.selectedIds.has(data.pointedId)
|
|
|
@@ -508,6 +519,9 @@ const state = createState({
|
|
508
|
519
|
) {
|
|
509
|
520
|
return payload.target === "rotate"
|
|
510
|
521
|
},
|
|
|
522
|
+ hasSelection(data) {
|
|
|
523
|
+ return data.selectedIds.size > 0
|
|
|
524
|
+ },
|
|
511
|
525
|
},
|
|
512
|
526
|
actions: {
|
|
513
|
527
|
/* --------------------- Shapes --------------------- */
|
|
|
@@ -565,7 +579,7 @@ const state = createState({
|
|
565
|
579
|
startTranslateSession(data, payload: PointerInfo) {
|
|
566
|
580
|
session = new Sessions.TranslateSession(
|
|
567
|
581
|
data,
|
|
568
|
|
- screenToWorld(payload.point, data),
|
|
|
582
|
+ screenToWorld(inputs.pointer.origin, data),
|
|
569
|
583
|
payload.altKey
|
|
570
|
584
|
)
|
|
571
|
585
|
},
|
|
|
@@ -697,29 +711,96 @@ const state = createState({
|
|
697
|
711
|
|
|
698
|
712
|
document.documentElement.style.setProperty("--camera-zoom", "1")
|
|
699
|
713
|
},
|
|
700
|
|
- centerCamera(data) {
|
|
|
714
|
+ zoomCameraToSelection(data) {
|
|
|
715
|
+ const { camera } = data
|
|
|
716
|
+
|
|
|
717
|
+ const bounds = getSelectedBounds(data)
|
|
|
718
|
+
|
|
|
719
|
+ const zoom =
|
|
|
720
|
+ bounds.width > bounds.height
|
|
|
721
|
+ ? (window.innerWidth - 128) / bounds.width
|
|
|
722
|
+ : (window.innerHeight - 128) / bounds.height
|
|
|
723
|
+
|
|
|
724
|
+ const mx = window.innerWidth - bounds.width * zoom
|
|
|
725
|
+ const my = window.innerHeight - bounds.height * zoom
|
|
|
726
|
+
|
|
|
727
|
+ camera.zoom = zoom
|
|
|
728
|
+
|
|
|
729
|
+ camera.point = vec.add(
|
|
|
730
|
+ [-bounds.minX, -bounds.minY],
|
|
|
731
|
+ [mx / 2 / zoom, my / 2 / zoom]
|
|
|
732
|
+ )
|
|
|
733
|
+
|
|
|
734
|
+ setZoomCSS(camera.zoom)
|
|
|
735
|
+ },
|
|
|
736
|
+ zoomCameraToSelectionActual(data) {
|
|
|
737
|
+ const { camera } = data
|
|
|
738
|
+
|
|
|
739
|
+ const bounds = getSelectedBounds(data)
|
|
|
740
|
+
|
|
|
741
|
+ const zoom = 1
|
|
|
742
|
+
|
|
|
743
|
+ const mx = window.innerWidth - 128 - bounds.width * zoom
|
|
|
744
|
+ const my = window.innerHeight - 128 - bounds.height * zoom
|
|
|
745
|
+
|
|
|
746
|
+ camera.zoom = zoom
|
|
|
747
|
+ camera.point = vec.add(
|
|
|
748
|
+ [-bounds.minX, -bounds.minY],
|
|
|
749
|
+ [mx / 2 / zoom, my / 2 / zoom]
|
|
|
750
|
+ )
|
|
|
751
|
+
|
|
|
752
|
+ setZoomCSS(camera.zoom)
|
|
|
753
|
+ },
|
|
|
754
|
+ zoomCameraToActual(data) {
|
|
|
755
|
+ const { camera } = data
|
|
|
756
|
+
|
|
|
757
|
+ const center = [window.innerWidth / 2, window.innerHeight / 2]
|
|
|
758
|
+
|
|
|
759
|
+ const p0 = screenToWorld(center, data)
|
|
|
760
|
+ camera.zoom = 1
|
|
|
761
|
+ const p1 = screenToWorld(center, data)
|
|
|
762
|
+ camera.point = vec.add(camera.point, vec.sub(p1, p0))
|
|
|
763
|
+
|
|
|
764
|
+ setZoomCSS(camera.zoom)
|
|
|
765
|
+ },
|
|
|
766
|
+ zoomCameraToFit(data) {
|
|
|
767
|
+ const { camera } = data
|
|
701
|
768
|
const { shapes } = getPage(data)
|
|
702
|
|
- getCommonBounds()
|
|
703
|
|
- data.camera.zoom = 1
|
|
704
|
|
- data.camera.point = [window.innerWidth / 2, window.innerHeight / 2]
|
|
705
|
769
|
|
|
706
|
|
- document.documentElement.style.setProperty("--camera-zoom", "1")
|
|
|
770
|
+ const bounds = getCommonBounds(
|
|
|
771
|
+ ...Object.values(shapes).map((shape) =>
|
|
|
772
|
+ getShapeUtils(shape).getBounds(shape)
|
|
|
773
|
+ )
|
|
|
774
|
+ )
|
|
|
775
|
+
|
|
|
776
|
+ const zoom =
|
|
|
777
|
+ bounds.width > bounds.height
|
|
|
778
|
+ ? (window.innerWidth - 104) / bounds.width
|
|
|
779
|
+ : (window.innerHeight - 104) / bounds.height
|
|
|
780
|
+
|
|
|
781
|
+ const mx = window.innerWidth - bounds.width * zoom
|
|
|
782
|
+ const my = window.innerHeight - bounds.height * zoom
|
|
|
783
|
+
|
|
|
784
|
+ camera.zoom = zoom
|
|
|
785
|
+ camera.point = vec.add(
|
|
|
786
|
+ [-bounds.minX, -bounds.minY],
|
|
|
787
|
+ [mx / 2 / zoom, my / 2 / zoom]
|
|
|
788
|
+ )
|
|
|
789
|
+
|
|
|
790
|
+ setZoomCSS(camera.zoom)
|
|
707
|
791
|
},
|
|
708
|
792
|
zoomCamera(data, payload: { delta: number; point: number[] }) {
|
|
709
|
793
|
const { camera } = data
|
|
710
|
794
|
const p0 = screenToWorld(payload.point, data)
|
|
711
|
795
|
camera.zoom = clamp(
|
|
712
|
796
|
camera.zoom - (payload.delta / 100) * camera.zoom,
|
|
713
|
|
- 0.5,
|
|
|
797
|
+ 0.1,
|
|
714
|
798
|
3
|
|
715
|
799
|
)
|
|
716
|
800
|
const p1 = screenToWorld(payload.point, data)
|
|
717
|
801
|
camera.point = vec.add(camera.point, vec.sub(p1, p0))
|
|
718
|
802
|
|
|
719
|
|
- document.documentElement.style.setProperty(
|
|
720
|
|
- "--camera-zoom",
|
|
721
|
|
- camera.zoom.toString()
|
|
722
|
|
- )
|
|
|
803
|
+ setZoomCSS(camera.zoom)
|
|
723
|
804
|
},
|
|
724
|
805
|
panCamera(data, payload: { delta: number[]; point: number[] }) {
|
|
725
|
806
|
const { camera } = data
|