@inweb/viewer-visualize 26.10.2 → 26.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -772,6 +772,161 @@ class MeasureLineDragger extends OdBaseDragger {
772
772
  }
773
773
  }
774
774
 
775
+ class OdJoyStickDragger {
776
+ constructor(global, container, callback, canvasElement) {
777
+ this.hasEventListeners = false;
778
+ const internalLineWidth = 2;
779
+ const internalStrokeColor = "#003300";
780
+ const externalLineWidth = 2;
781
+ const externalStrokeColor = "#35436E";
782
+ this.container = container;
783
+ this.container.style.touchAction = "none";
784
+ this.canvas = document.createElement("canvas");
785
+ this.canvas.id = "odJoyStickCanvas";
786
+ this.canvas.width = 200;
787
+ this.canvas.height = 200;
788
+ this.container.appendChild(this.canvas);
789
+ const context = this.canvas.getContext("2d");
790
+ let pressed = 0;
791
+ const circumference = 2 * Math.PI;
792
+ const internalRadius = (this.canvas.width - (this.canvas.width / 2 + 10)) / 2;
793
+ const maxMoveStick = internalRadius + 5;
794
+ const externalRadius = internalRadius + 30;
795
+ const centerX = this.canvas.width / 2;
796
+ const centerY = this.canvas.height / 2;
797
+ let movedX = centerX;
798
+ let movedY = centerY;
799
+ this.onMouseDown = () => {
800
+ event.preventDefault();
801
+ pressed = 1;
802
+ };
803
+ this.onMouseMove = (event) => {
804
+ event.preventDefault();
805
+ if (pressed === 1) {
806
+ movedX = event.pageX;
807
+ movedY = event.pageY;
808
+ if (this.canvas.offsetParent && this.canvas.offsetParent.tagName.toUpperCase() === "BODY") {
809
+ movedX -= this.canvas.offsetLeft;
810
+ movedY -= this.canvas.offsetTop;
811
+ }
812
+ else if (this.canvas.offsetParent) {
813
+ movedX -= this.canvas.offsetParent.offsetLeft;
814
+ movedY -= this.canvas.offsetParent.offsetTop;
815
+ }
816
+ context.clearRect(0, 0, this.canvas.width, this.canvas.height);
817
+ this.drawExternal();
818
+ this.drawInternal();
819
+ callback({
820
+ x: 100 * ((movedX - centerX) / maxMoveStick),
821
+ y: 100 * ((movedY - centerY) / maxMoveStick) * -1,
822
+ global: global,
823
+ });
824
+ }
825
+ };
826
+ this.onMouseUp = () => {
827
+ event.preventDefault();
828
+ pressed = 0;
829
+ movedX = centerX;
830
+ movedY = centerY;
831
+ context.clearRect(0, 0, this.canvas.width, this.canvas.height);
832
+ this.drawExternal();
833
+ this.drawInternal();
834
+ callback({
835
+ x: 100 * ((movedX - centerX) / maxMoveStick),
836
+ y: 100 * ((movedY - centerY) / maxMoveStick) * -1,
837
+ global: global,
838
+ });
839
+ };
840
+ this.drawExternal = () => {
841
+ context.beginPath();
842
+ context.arc(centerX, centerY, externalRadius, 0, circumference, false);
843
+ context.lineWidth = externalLineWidth;
844
+ context.strokeStyle = externalStrokeColor;
845
+ context.globalAlpha = 0.5;
846
+ context.stroke();
847
+ };
848
+ this.drawInternal = () => {
849
+ context.beginPath();
850
+ if (movedX < internalRadius) {
851
+ movedX = maxMoveStick;
852
+ }
853
+ if (movedX + internalRadius > this.canvas.width) {
854
+ movedX = this.canvas.width - maxMoveStick;
855
+ }
856
+ if (movedY < internalRadius) {
857
+ movedY = maxMoveStick;
858
+ }
859
+ if (movedY + internalRadius > this.canvas.height) {
860
+ movedY = this.canvas.height - maxMoveStick;
861
+ }
862
+ context.arc(movedX, movedY, internalRadius, 0, circumference, false);
863
+ context.fillStyle = externalStrokeColor;
864
+ context.lineWidth = internalLineWidth;
865
+ context.strokeStyle = internalStrokeColor;
866
+ context.globalAlpha = 0.5;
867
+ context.fill();
868
+ context.stroke();
869
+ };
870
+ const addEventListeners = () => {
871
+ if (!this.hasEventListeners) {
872
+ this.canvas.addEventListener("pointerdown", this.onMouseDown, false);
873
+ document.addEventListener("pointermove", this.onMouseMove, false);
874
+ document.addEventListener("pointerup", this.onMouseUp, false);
875
+ this.hasEventListeners = true;
876
+ }
877
+ };
878
+ const removeEventListeners = () => {
879
+ if (this.hasEventListeners) {
880
+ this.canvas.removeEventListener("pointerdown", this.onMouseDown, false);
881
+ document.removeEventListener("pointermove", this.onMouseMove, false);
882
+ document.removeEventListener("pointerup", this.onMouseUp, false);
883
+ this.hasEventListeners = false;
884
+ }
885
+ };
886
+ const updateContainerPosition = () => {
887
+ if (canvasElement) {
888
+ const rect = canvasElement.getBoundingClientRect();
889
+ this.container.style.top = `${rect.height - 200}px`;
890
+ this.container.style.left = `${rect.left}px`;
891
+ this.container.style.width = `200px`;
892
+ this.container.style.height = `200px`;
893
+ }
894
+ };
895
+ const updateVisibility = () => {
896
+ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
897
+ const isNarrowScreen = window.innerWidth < 1024;
898
+ const shouldShow = isMobile || isNarrowScreen;
899
+ if (shouldShow) {
900
+ this.container.style.display = "block";
901
+ addEventListeners();
902
+ }
903
+ else {
904
+ this.container.style.display = "none";
905
+ removeEventListeners();
906
+ }
907
+ };
908
+ this.onResize = () => {
909
+ updateVisibility();
910
+ setTimeout(updateContainerPosition, 500);
911
+ };
912
+ updateVisibility();
913
+ updateContainerPosition();
914
+ window.addEventListener("resize", this.onResize, false);
915
+ this.drawExternal();
916
+ this.drawInternal();
917
+ }
918
+ cleanup() {
919
+ window.removeEventListener("resize", this.onResize, false);
920
+ if (this.hasEventListeners) {
921
+ this.canvas.removeEventListener("pointerdown", this.onMouseDown, false);
922
+ document.removeEventListener("pointermove", this.onMouseMove, false);
923
+ document.removeEventListener("pointerup", this.onMouseUp, false);
924
+ this.hasEventListeners = false;
925
+ }
926
+ this.canvas.remove();
927
+ }
928
+ }
929
+
775
930
  const FocalLengthConst$1 = 42.0;
776
931
  const calcFocalLength$1 = (lensLength, fieldWidth, fieldHeight) => {
777
932
  return (lensLength / FocalLengthConst$1) * Math.sqrt(fieldWidth * fieldWidth + fieldHeight * fieldHeight);
@@ -781,15 +936,19 @@ class OdaWalkDragger extends OdBaseDragger {
781
936
  super(subject);
782
937
  this.viewer = undefined;
783
938
  this.multiplier = 5;
784
- this.speed = 1;
939
+ this.baseSpeed = 1;
785
940
  this.keyPressMap = new Set();
786
941
  this.keydown = this.keydown.bind(this);
787
942
  this.keyup = this.keyup.bind(this);
788
943
  this.lastFrameTS = 0;
944
+ this.lastFrameJoyStickTS = 0;
789
945
  this.animationId = undefined;
790
946
  this.processMovement = this.processMovement.bind(this);
947
+ this.processJoyStickMovement = this.processJoyStickMovement.bind(this);
791
948
  this.deltaAngle = Math.PI / 3600;
792
949
  this.autoSelect = true;
950
+ this.isJoyStickMoving = false;
951
+ this.addJoyStickDragger();
793
952
  }
794
953
  initialize() {
795
954
  super.initialize();
@@ -800,7 +959,7 @@ class OdaWalkDragger extends OdBaseDragger {
800
959
  this.viewer.setEnableWCS(false);
801
960
  const view = this.viewer.activeView;
802
961
  const maxDimension = this.getMaxDimension(view);
803
- this.speed = maxDimension / 30000;
962
+ this.baseSpeed = maxDimension / 30000;
804
963
  this.subject.emitEvent({ type: "walkstart" });
805
964
  this.viewParams = this.getViewParams();
806
965
  this.setViewParams(this.viewParams);
@@ -840,6 +999,8 @@ class OdaWalkDragger extends OdBaseDragger {
840
999
  }
841
1000
  this.subject.update(true);
842
1001
  this.subject.options.enableZoomWheel = this.enableZoomWheelPreviousValue;
1002
+ this.joyStickOverlayElement.remove();
1003
+ this.joyStickDragger.cleanup();
843
1004
  }
844
1005
  keydown(ev) {
845
1006
  switch (ev.code) {
@@ -881,31 +1042,32 @@ class OdaWalkDragger extends OdBaseDragger {
881
1042
  this.animationId = requestAnimationFrame(this.processMovement);
882
1043
  if (this.lastFrameTS !== 0) {
883
1044
  const deltaTS = timestamp - this.lastFrameTS;
884
- const currentDelta = this.multiplier * deltaTS * this.speed;
885
- for (const keyCode of this.keyPressMap) {
886
- switch (keyCode) {
887
- case "KeyW":
888
- this.moveForward(currentDelta);
889
- break;
890
- case "KeyS":
891
- this.moveBackward(currentDelta);
892
- break;
893
- case "KeyA":
894
- this.cameraWalker.moveLeft(currentDelta);
895
- break;
896
- case "KeyD":
897
- this.cameraWalker.moveRight(currentDelta);
898
- break;
899
- case "KeyQ":
900
- this.cameraWalker.moveUp(currentDelta);
901
- break;
902
- case "KeyE":
903
- this.cameraWalker.moveDown(currentDelta);
904
- break;
905
- }
1045
+ if (deltaTS > 0) {
1046
+ const currentDelta = this.multiplier * deltaTS * this.baseSpeed;
1047
+ Array.from(this.keyPressMap).forEach((keyCode) => {
1048
+ switch (keyCode) {
1049
+ case "KeyW":
1050
+ this.moveForward(currentDelta);
1051
+ break;
1052
+ case "KeyS":
1053
+ this.moveBackward(currentDelta);
1054
+ break;
1055
+ case "KeyA":
1056
+ this.cameraWalker.moveLeft(currentDelta);
1057
+ break;
1058
+ case "KeyD":
1059
+ this.cameraWalker.moveRight(currentDelta);
1060
+ break;
1061
+ case "KeyQ":
1062
+ this.cameraWalker.moveUp(currentDelta);
1063
+ break;
1064
+ case "KeyE":
1065
+ this.cameraWalker.moveDown(currentDelta);
1066
+ break;
1067
+ }
1068
+ });
1069
+ this.proceedChangeCamera();
906
1070
  }
907
- this.subject.update();
908
- this.subject.emitEvent({ type: "changecamera" });
909
1071
  }
910
1072
  this.lastFrameTS = timestamp;
911
1073
  }
@@ -991,6 +1153,58 @@ class OdaWalkDragger extends OdBaseDragger {
991
1153
  const volume = [xmax - xmin, ymax - ymin, zmax - zmin];
992
1154
  return Math.max(...volume);
993
1155
  }
1156
+ addJoyStickDragger() {
1157
+ this.joyStickOverlayElement = document.createElement("div");
1158
+ this.joyStickOverlayElement.id = "joyStickDiv";
1159
+ this.joyStickOverlayElement.style.background = "rgba(0,0,0,0)";
1160
+ this.joyStickOverlayElement.style.position = "fixed";
1161
+ this.joyStickOverlayElement.style.zIndex = "0";
1162
+ document.body.appendChild(this.joyStickOverlayElement);
1163
+ this.joyStickDragger = new OdJoyStickDragger(this, this.joyStickOverlayElement, (stickData) => {
1164
+ if (Math.sqrt(stickData.x * stickData.x + stickData.y * stickData.y) > 20) {
1165
+ this.lastJoyStickCoord = { x: stickData.x, y: stickData.y };
1166
+ if (!this.animationId && !this.isJoyStickMoving) {
1167
+ this.isJoyStickMoving = true;
1168
+ this.processJoyStickMovement(0);
1169
+ }
1170
+ }
1171
+ else {
1172
+ this.isJoyStickMoving = false;
1173
+ window.cancelAnimationFrame(this.animationId);
1174
+ this.animationId = undefined;
1175
+ this.lastFrameJoyStickTS = 0;
1176
+ }
1177
+ }, this.m_module.canvas);
1178
+ }
1179
+ processJoyStickMovement(timestamp) {
1180
+ if (!this.isJoyStickMoving)
1181
+ return;
1182
+ this.animationId = requestAnimationFrame(this.processJoyStickMovement);
1183
+ if (this.lastFrameJoyStickTS !== 0) {
1184
+ const deltaTS = timestamp - this.lastFrameJoyStickTS;
1185
+ if (deltaTS > 0) {
1186
+ const maxJoystickDistance = 100;
1187
+ const forward = this.lastJoyStickCoord.y / maxJoystickDistance;
1188
+ const right = this.lastJoyStickCoord.x / maxJoystickDistance;
1189
+ const currentDelta = this.multiplier * deltaTS * this.baseSpeed;
1190
+ this.moveTotal(currentDelta, forward, right);
1191
+ }
1192
+ }
1193
+ this.lastFrameJoyStickTS = timestamp;
1194
+ }
1195
+ moveTotal(currentDelta, forward, right) {
1196
+ if (forward !== 0) {
1197
+ this.moveForward(currentDelta * forward);
1198
+ }
1199
+ if (right !== 0) {
1200
+ this.cameraWalker.moveRight(currentDelta * right);
1201
+ }
1202
+ this.proceedChangeCamera();
1203
+ }
1204
+ proceedChangeCamera() {
1205
+ this.subject.update();
1206
+ this.subject.emitEvent({ type: "changecamera" });
1207
+ }
994
1208
  }
995
1209
 
996
1210
  const FocalLengthConst = 42.0;
@@ -1007,10 +1221,34 @@ class OdaFlyDragger extends OdBaseDragger {
1007
1221
  this.keydown = this.keydown.bind(this);
1008
1222
  this.keyup = this.keyup.bind(this);
1009
1223
  this.lastFrameTS = 0;
1224
+ this.lastFrameJoyStickTS = 0;
1010
1225
  this.animationId = undefined;
1011
1226
  this.processMovement = this.processMovement.bind(this);
1227
+ this.processJoyMovement = this.processJoyMovement.bind(this);
1012
1228
  this.deltaAngle = Math.PI / 3600;
1013
1229
  this.autoSelect = true;
1230
+ this.moving = false;
1231
+ this.joyStickOverlayElement = document.createElement("div");
1232
+ this.joyStickOverlayElement.id = "joyStickDiv";
1233
+ this.joyStickOverlayElement.style.background = "rgba(0,0,0,0)";
1234
+ this.joyStickOverlayElement.style.position = "fixed";
1235
+ this.joyStickOverlayElement.style.zIndex = "0";
1236
+ document.body.appendChild(this.joyStickOverlayElement);
1237
+ this.joyStickDragger = new OdJoyStickDragger(this, this.joyStickOverlayElement, (stickData) => {
1238
+ if (Math.sqrt(stickData.x * stickData.x + stickData.y * stickData.y) > 20) {
1239
+ this.lastJoyStickCoord = { x: stickData.x, y: stickData.y };
1240
+ if (!this.animationId && !this.moving) {
1241
+ this.moving = true;
1242
+ this.processJoyMovement(0);
1243
+ }
1244
+ }
1245
+ else {
1246
+ this.moving = false;
1247
+ window.cancelAnimationFrame(this.animationId);
1248
+ this.animationId = undefined;
1249
+ this.lastFrameJoyStickTS = 0;
1250
+ }
1251
+ }, this.m_module.canvas);
1014
1252
  }
1015
1253
  initialize() {
1016
1254
  super.initialize();
@@ -1061,6 +1299,8 @@ class OdaFlyDragger extends OdBaseDragger {
1061
1299
  }
1062
1300
  this.subject.update(true);
1063
1301
  this.subject.options.enableZoomWheel = this.enableZoomWheelPreviousValue;
1302
+ this.joyStickOverlayElement.remove();
1303
+ this.joyStickDragger.cleanup();
1064
1304
  }
1065
1305
  keydown(ev) {
1066
1306
  switch (ev.code) {
@@ -1191,6 +1431,37 @@ class OdaFlyDragger extends OdBaseDragger {
1191
1431
  const volume = [xmax - xmin, ymax - ymin, zmax - zmin];
1192
1432
  return Math.max(...volume);
1193
1433
  }
1434
+ processJoyMovement(timestamp) {
1435
+ if (!this.moving)
1436
+ return;
1437
+ this.animationId = requestAnimationFrame(this.processJoyMovement);
1438
+ if (this.lastFrameJoyStickTS !== 0) {
1439
+ const deltaTS = timestamp - this.lastFrameJoyStickTS;
1440
+ if (deltaTS > 0) {
1441
+ const maxJoystickDistance = 100;
1442
+ const forward = this.lastJoyStickCoord.y / maxJoystickDistance;
1443
+ const right = this.lastJoyStickCoord.x / maxJoystickDistance;
1444
+ const currentDelta = this.multiplier * deltaTS * this.speed;
1445
+ this.moveTotal(currentDelta, forward, right);
1446
+ }
1447
+ }
1448
+ this.lastFrameJoyStickTS = timestamp;
1449
+ }
1450
+ moveTotal(currentDelta, forward, right) {
1451
+ if (forward !== 0) {
1452
+ if (forward > 0) {
1453
+ this.cameraFlyer.moveForward(currentDelta * forward);
1454
+ }
1455
+ else {
1456
+ this.cameraFlyer.moveBackward(currentDelta * Math.abs(forward));
1457
+ }
1458
+ }
1459
+ if (right !== 0) {
1460
+ this.cameraFlyer.moveRight(currentDelta * right);
1461
+ }
1462
+ this.subject.update();
1463
+ this.subject.emitEvent({ type: "changecamera" });
1464
+ }
1194
1465
  }
1195
1466
 
1196
1467
  class OdBaseCuttingPlaneDragger extends OdBaseDragger {
@@ -2381,6 +2652,46 @@ commands.registerCommandAlias("clearMarkup", "clearOverlay");
2381
2652
  commands.registerCommandAlias("clearSelected", "unselect");
2382
2653
  commands.registerCommandAlias("zoomToExtents", "zoomExtents");
2383
2654
 
2655
+ class CameraComponent {
2656
+ constructor(viewer) {
2657
+ this.optionsChange = () => {
2658
+ this.switchCameraMode(this.viewer.options.cameraMode);
2659
+ };
2660
+ this.geometryEnd = () => {
2661
+ const activeView = this.viewer.visViewer().activeView;
2662
+ const mode = this.getCameraMode(activeView);
2663
+ this.viewer.options.cameraMode = mode;
2664
+ this.viewer.emitEvent({ type: "changecameramode", mode });
2665
+ activeView.delete();
2666
+ };
2667
+ this.viewer = viewer;
2668
+ this.viewer.addEventListener("databasechunk", this.geometryEnd);
2669
+ this.viewer.addEventListener("clear", this.geometryEnd);
2670
+ this.viewer.addEventListener("optionschange", this.optionsChange);
2671
+ this.viewer.addEventListener("initialize", this.optionsChange);
2672
+ }
2673
+ dispose() {
2674
+ this.viewer.removeEventListener("databasechunk", this.geometryEnd);
2675
+ this.viewer.removeEventListener("clear", this.geometryEnd);
2676
+ this.viewer.removeEventListener("optionschange", this.optionsChange);
2677
+ this.viewer.removeEventListener("initialize", this.optionsChange);
2678
+ }
2679
+ getCameraMode(view) {
2680
+ return view.perspective ? "perspective" : "orthographic";
2681
+ }
2682
+ switchCameraMode(mode) {
2683
+ if (!mode)
2684
+ return;
2685
+ const activeView = this.viewer.visViewer().activeView;
2686
+ if (mode !== this.getCameraMode(activeView)) {
2687
+ activeView.perspective = !activeView.perspective;
2688
+ this.viewer.update();
2689
+ this.viewer.emitEvent({ type: "changecameramode", mode });
2690
+ }
2691
+ activeView.delete();
2692
+ }
2693
+ }
2694
+
2384
2695
  class RenderLoopComponent {
2385
2696
  constructor(viewer) {
2386
2697
  this.animate = (time = 0) => {
@@ -2663,6 +2974,7 @@ class ResetComponent {
2663
2974
  }
2664
2975
 
2665
2976
  const components = componentsRegistry("visualizejs");
2977
+ components.registerComponent("CameraComponent", (viewer) => new CameraComponent(viewer));
2666
2978
  components.registerComponent("ResizeCanvasComponent", (viewer) => new ResizeCanvasComponent(viewer));
2667
2979
  components.registerComponent("RenderLoopComponent", (viewer) => new RenderLoopComponent(viewer));
2668
2980
  components.registerComponent("ZoomWheelComponent", (viewer) => new ZoomWheelComponent(viewer));