@realsee/dnalogel 2.0.0-alpha.6 → 2.0.0-alpha.7

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.
Files changed (117) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +44 -5
  3. package/dist/dnalogel.cjs.js +7 -2
  4. package/dist/dnalogel.es.js +3516 -159
  5. package/dist/dnalogel.umd.js +7 -2
  6. package/libs/PanoCompassPlugin/index.d.ts +3 -3
  7. package/libs/PanoCompassPlugin/index.js +56 -44
  8. package/libs/PanoMeasurePlugin/Controller/BaseController.d.ts +36 -0
  9. package/libs/PanoMeasurePlugin/Controller/BaseController.js +69 -0
  10. package/libs/PanoMeasurePlugin/Controller/EditController.d.ts +52 -0
  11. package/libs/PanoMeasurePlugin/Controller/EditController.js +216 -0
  12. package/libs/PanoMeasurePlugin/Controller/ShortcutKeyController.d.ts +12 -0
  13. package/libs/PanoMeasurePlugin/Controller/ShortcutKeyController.js +44 -0
  14. package/libs/PanoMeasurePlugin/Controller/WatchController.d.ts +25 -0
  15. package/libs/PanoMeasurePlugin/Controller/WatchController.js +223 -0
  16. package/libs/PanoMeasurePlugin/Controller/index.d.ts +61 -0
  17. package/libs/PanoMeasurePlugin/Controller/index.js +176 -0
  18. package/libs/PanoMeasurePlugin/Model/index.d.ts +38 -0
  19. package/libs/PanoMeasurePlugin/Model/index.js +114 -0
  20. package/libs/PanoMeasurePlugin/Model/line.d.ts +30 -0
  21. package/libs/PanoMeasurePlugin/Model/line.js +64 -0
  22. package/libs/PanoMeasurePlugin/Model/point.d.ts +16 -0
  23. package/libs/PanoMeasurePlugin/Model/point.js +28 -0
  24. package/libs/PanoMeasurePlugin/Model/polyline.d.ts +16 -0
  25. package/libs/PanoMeasurePlugin/Model/polyline.js +48 -0
  26. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.d.ts +2 -0
  27. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.js +15 -0
  28. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.d.ts +2 -0
  29. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.js +2 -0
  30. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_hover_bg.png.d.ts +2 -0
  31. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_hover_bg.png.js +2 -0
  32. package/libs/PanoMeasurePlugin/Modules/DeleteDom/index.d.ts +22 -0
  33. package/libs/PanoMeasurePlugin/Modules/DeleteDom/index.js +108 -0
  34. package/libs/PanoMeasurePlugin/Modules/FiveHelper.d.ts +11 -0
  35. package/libs/PanoMeasurePlugin/Modules/FiveHelper.js +33 -0
  36. package/libs/PanoMeasurePlugin/Modules/GuideController.d.ts +18 -0
  37. package/libs/PanoMeasurePlugin/Modules/GuideController.js +75 -0
  38. package/libs/PanoMeasurePlugin/Modules/Magnifier.d.ts +24 -0
  39. package/libs/PanoMeasurePlugin/Modules/Magnifier.js +103 -0
  40. package/libs/PanoMeasurePlugin/Modules/UIController/HTML.d.ts +6 -0
  41. package/libs/PanoMeasurePlugin/Modules/UIController/HTML.js +117 -0
  42. package/libs/PanoMeasurePlugin/Modules/UIController/MainBtnController.d.ts +18 -0
  43. package/libs/PanoMeasurePlugin/Modules/UIController/MainBtnController.js +102 -0
  44. package/libs/PanoMeasurePlugin/Modules/UIController/Revoke/index.d.ts +12 -0
  45. package/libs/PanoMeasurePlugin/Modules/UIController/Revoke/index.js +35 -0
  46. package/libs/PanoMeasurePlugin/Modules/UIController/index.d.ts +16 -0
  47. package/libs/PanoMeasurePlugin/Modules/UIController/index.js +69 -0
  48. package/libs/PanoMeasurePlugin/Modules/UIController/style.d.ts +17 -0
  49. package/libs/PanoMeasurePlugin/Modules/UIController/style.js +78 -0
  50. package/libs/PanoMeasurePlugin/index.d.ts +7 -0
  51. package/libs/PanoMeasurePlugin/index.js +5 -0
  52. package/libs/PanoMeasurePlugin/typings/data.d.ts +28 -0
  53. package/libs/PanoMeasurePlugin/typings/data.js +1 -0
  54. package/libs/PanoMeasurePlugin/typings/event.type.d.ts +28 -0
  55. package/libs/PanoMeasurePlugin/typings/event.type.js +1 -0
  56. package/libs/PanoMeasurePlugin/typings/utils.type.d.ts +1 -0
  57. package/libs/PanoMeasurePlugin/typings/utils.type.js +1 -0
  58. package/libs/PanoMeasurePlugin/utils/clearGroup.d.ts +2 -0
  59. package/libs/PanoMeasurePlugin/utils/clearGroup.js +3 -0
  60. package/libs/PanoMeasurePlugin/utils/constants.d.ts +4 -0
  61. package/libs/PanoMeasurePlugin/utils/constants.js +31 -0
  62. package/libs/PanoMeasurePlugin/utils/distanceDom.d.ts +28 -0
  63. package/libs/PanoMeasurePlugin/utils/distanceDom.js +114 -0
  64. package/libs/PanoMeasurePlugin/utils/findAssociatedLines.d.ts +2 -0
  65. package/libs/PanoMeasurePlugin/utils/findAssociatedLines.js +21 -0
  66. package/libs/PanoMeasurePlugin/utils/findClosestPoint.d.ts +10 -0
  67. package/libs/PanoMeasurePlugin/utils/findClosestPoint.js +27 -0
  68. package/libs/PanoMeasurePlugin/utils/getIntersectionFromEvent.d.ts +4 -0
  69. package/libs/PanoMeasurePlugin/utils/getIntersectionFromEvent.js +9 -0
  70. package/libs/PanoMeasurePlugin/utils/getPointFromHammerEvent.d.ts +10 -0
  71. package/libs/PanoMeasurePlugin/utils/getPointFromHammerEvent.js +14 -0
  72. package/libs/PanoMeasurePlugin/utils/ironbox.d.ts +1 -0
  73. package/libs/PanoMeasurePlugin/utils/ironbox.js +1 -0
  74. package/libs/PanoMeasurePlugin/utils/isNDCPointInScreen.d.ts +2 -0
  75. package/libs/PanoMeasurePlugin/utils/isNDCPointInScreen.js +6 -0
  76. package/libs/PanoMeasurePlugin/utils/line.d.ts +17 -0
  77. package/libs/PanoMeasurePlugin/utils/line.js +32 -0
  78. package/libs/PanoMeasurePlugin/utils/math.d.ts +17 -0
  79. package/libs/PanoMeasurePlugin/utils/math.js +44 -0
  80. package/libs/PanoMeasurePlugin/utils/mouseGroup.d.ts +2 -0
  81. package/libs/PanoMeasurePlugin/utils/mouseGroup.js +21 -0
  82. package/libs/PanoMeasurePlugin/utils/ndc2Screen.d.ts +5 -0
  83. package/libs/PanoMeasurePlugin/utils/ndc2Screen.js +6 -0
  84. package/libs/index.d.ts +2 -0
  85. package/libs/index.js +1 -0
  86. package/package.json +1 -1
  87. package/docs/.nojekyll +0 -1
  88. package/docs/assets/highlight.css +0 -29
  89. package/docs/assets/icons.css +0 -1043
  90. package/docs/assets/icons.png +0 -0
  91. package/docs/assets/icons@2x.png +0 -0
  92. package/docs/assets/main.js +0 -52
  93. package/docs/assets/search.js +0 -1
  94. package/docs/assets/style.css +0 -1413
  95. package/docs/assets/widgets.png +0 -0
  96. package/docs/assets/widgets@2x.png +0 -0
  97. package/docs/classes/ModelRoomLabelController.html +0 -20
  98. package/docs/enums/FLOOR_PLAN_ATTACHED_TO.html +0 -1
  99. package/docs/enums/ModelFloorplanErrorType.html +0 -1
  100. package/docs/index.html +0 -10
  101. package/docs/interfaces/ModelChassisCompassPluginData.html +0 -1
  102. package/docs/interfaces/ModelChassisCompassPluginExportType.html +0 -1
  103. package/docs/interfaces/ModelChassisCompassPluginParameterType.html +0 -1
  104. package/docs/interfaces/ModelEntryDoorGuidePluginData.html +0 -1
  105. package/docs/interfaces/ModelEntryDoorGuidePluginExportType.html +0 -1
  106. package/docs/interfaces/ModelFloorplanParameterType.html +0 -1
  107. package/docs/interfaces/ModelFloorplanViewEvent.html +0 -5
  108. package/docs/interfaces/ModelRoomLabelPluginData.html +0 -1
  109. package/docs/interfaces/PanoCompassPluginData.html +0 -1
  110. package/docs/interfaces/PanoCompassPluginParameterType.html +0 -1
  111. package/docs/interfaces/PanoCursorRaycasterPluginExportType.html +0 -11
  112. package/docs/interfaces/PanoRulerPluginExportType.html +0 -1
  113. package/docs/interfaces/PanoRulerPluginOptions.html +0 -1
  114. package/docs/interfaces/PanoRulerPluginParameterType.html +0 -1
  115. package/docs/interfaces/RoomLabel.html +0 -13
  116. package/docs/interfaces/TopviewFloorplanPluginParameterType.html +0 -1
  117. package/docs/modules.html +0 -26
@@ -5,15 +5,15 @@ export interface PanoCompassPluginParameterType {
5
5
  entryDoorImageUrl?: string;
6
6
  }
7
7
  export interface PanoCompassPluginData {
8
- entrance: null | {
9
- north_rad: number;
8
+ north_rad: null | number;
9
+ entrance: null | undefined | {
10
10
  position: {
11
11
  x: number;
12
12
  y: number;
13
13
  z: number;
14
14
  };
15
15
  };
16
- room_observers: {
16
+ room_observers: undefined | {
17
17
  index: number;
18
18
  floor_index: number;
19
19
  room: FloorplanServerRoomItem;
@@ -53,23 +53,28 @@ class PanoCompassController {
53
53
  async init() {
54
54
  if (!this.data || !this.modelLoaded)
55
55
  return;
56
- this.compassMesh = await this.loadCompassMesh();
57
- this.entryDoorMesh = await this.loadEntryDoorMesh();
58
- this.roomInfoWrapperInstance = this.loadRoomInfo();
59
- this.roomInfoInstance = getRoomInfoInstance();
60
- this.compassMesh.rotateX(-Math.PI / 2);
61
- this.entryDoorMesh.rotateX(-Math.PI / 2);
62
- const northRad = this.data.entrance.north_rad;
63
- this.compassMesh.rotateZ(northRad - Math.PI / 2);
56
+ const northRad = this.data.north_rad;
57
+ if (northRad != null) {
58
+ this.compassMesh = await this.loadCompassMesh();
59
+ this.compassMesh.rotateX(-Math.PI / 2);
60
+ this.compassMesh.rotateZ(northRad - Math.PI / 2);
61
+ this.group.add(this.compassMesh);
62
+ }
63
+ if (this.data.entrance != null) {
64
+ this.entryDoorMesh = await this.loadEntryDoorMesh();
65
+ this.roomInfoWrapperInstance = this.loadRoomInfo();
66
+ this.roomInfoInstance = getRoomInfoInstance();
67
+ this.entryDoorMesh.rotateX(-Math.PI / 2);
68
+ if (this.roomInfoWrapperInstance)
69
+ this.roomInfoInstance.appendTo(this.roomInfoWrapperInstance.container);
70
+ this.group.add(this.entryDoorMesh);
71
+ }
64
72
  this.onFivePanoArrived(this.five.panoIndex || 0);
65
- this.group.add(this.compassMesh);
66
- this.group.add(this.entryDoorMesh);
67
- if (this.roomInfoWrapperInstance)
68
- this.roomInfoInstance.appendTo(this.roomInfoWrapperInstance.container);
69
73
  this.five.needsRender = true;
70
74
  }
71
75
  async loadCompassMesh() {
72
- const compassImageUrl = this.config?.compassImageUrl || '//vrlab-image4.ljcdn.com/release/web/v3/north-point-circle.96498e69.png';
76
+ const compassImageUrl = this.config?.compassImageUrl ||
77
+ '//vrlab-image4.ljcdn.com/release/web/v3/north-point-circle.96498e69.png';
73
78
  const compassTexture = await loadTexture(compassImageUrl);
74
79
  const compassGeometry = new THREE.CircleGeometry(0.7, 32);
75
80
  const compassMaterial = new THREE.MeshBasicMaterial({
@@ -83,7 +88,8 @@ class PanoCompassController {
83
88
  return compassMesh;
84
89
  }
85
90
  async loadEntryDoorMesh() {
86
- const entryDoorImageUrl = this.config?.entryDoorImageUrl || '//vrlab-image4.ljcdn.com/release/web/enterDoor.831b8208.png';
91
+ const entryDoorImageUrl = this.config?.entryDoorImageUrl ||
92
+ '//vrlab-image4.ljcdn.com/release/web/enterDoor.831b8208.png';
87
93
  const entryDoorTexture = await loadTexture(entryDoorImageUrl);
88
94
  const entryDoorGeometry = new THREE.PlaneGeometry(0.2, 0.16);
89
95
  const entryDoorMaterial = new THREE.MeshBasicMaterial({
@@ -113,42 +119,48 @@ class PanoCompassController {
113
119
  this.compassMesh?.material.setValues({ opacity: 0 });
114
120
  };
115
121
  onFivePanoArrived = (panoIndex) => {
116
- if (!this.compassMesh || !this.entryDoorMesh || !this.roomInfoInstance || !this.roomInfoWrapperInstance)
117
- return;
118
- if (!this.data)
119
- return;
120
122
  // ======== fix compass position ========
121
123
  const standingPosition = this.five.work.observers[panoIndex].standingPosition;
122
- // 指南针上移 0.01m,防止与地板重合
123
- this.compassMesh.position.copy(standingPosition.clone().setY(standingPosition.y + 0.01));
124
+ if (this.compassMesh) {
125
+ // 指南针上移 0.01m,防止与地板重合
126
+ this.compassMesh.position.copy(standingPosition.clone().setY(standingPosition.y + 0.01));
127
+ if (this.compassMesh.material.opacity !== 0)
128
+ return;
129
+ this.compassMeshTween?.dispose();
130
+ this.compassMeshTween = tweenProgress(1000)
131
+ .onUpdate(({ progress }) => {
132
+ this.compassMesh?.material.setValues({ opacity: progress });
133
+ this.five.needsRender = true;
134
+ })
135
+ .play();
136
+ }
124
137
  // ======== fix entry door label position and rotation ========
125
- const entryDoorPosition = new THREE.Vector3(this.data.entrance.position.x, this.data.entrance.position.y, this.data.entrance.position.z);
126
- const panoToEntryDoorVector = entryDoorPosition.clone().setY(standingPosition.y).sub(standingPosition).normalize();
127
- const compassEntryDoorPosition = standingPosition
128
- .clone()
129
- .add(panoToEntryDoorVector.clone().multiplyScalar(0.7))
130
- .setY(standingPosition.y + 0.01);
131
- this.entryDoorMesh.rotation.z = new THREE.Vector3(0, 0, -1).angleTo(panoToEntryDoorVector);
132
- this.entryDoorMesh.position.copy(compassEntryDoorPosition);
138
+ if (this.entryDoorMesh) {
139
+ const entryDoorPosition = new THREE.Vector3(this.data.entrance.position.x, this.data.entrance.position.y, this.data.entrance.position.z);
140
+ const panoToEntryDoorVector = entryDoorPosition
141
+ .clone()
142
+ .setY(standingPosition.y)
143
+ .sub(standingPosition)
144
+ .normalize();
145
+ const compassEntryDoorPosition = standingPosition
146
+ .clone()
147
+ .add(panoToEntryDoorVector.clone().multiplyScalar(0.7))
148
+ .setY(standingPosition.y + 0.01);
149
+ this.entryDoorMesh.rotation.z = new THREE.Vector3(0, 0, -1).angleTo(panoToEntryDoorVector);
150
+ this.entryDoorMesh.position.copy(compassEntryDoorPosition);
151
+ // 不是客厅时,隐藏入户门指引
152
+ this.data?.room_observers[panoIndex].room.type === 1
153
+ ? this.entryDoorMesh?.material.setValues({ opacity: 1 })
154
+ : this.entryDoorMesh?.material.setValues({ opacity: 0 });
155
+ }
133
156
  // ======== fix room info ========
134
- this.roomInfoWrapperInstance.css3DObject.position.copy(standingPosition.clone().setY(standingPosition.y + 0.01));
135
- this.roomInfoInstance.setRoom(this.data.room_observers[panoIndex].room);
136
- // 不是客厅时,隐藏入户门指引
137
- this.data?.room_observers[panoIndex].room.type === 1
138
- ? this.entryDoorMesh?.material.setValues({ opacity: 1 })
139
- : this.entryDoorMesh?.material.setValues({ opacity: 0 });
157
+ if (this.roomInfoInstance && this.roomInfoWrapperInstance) {
158
+ this.roomInfoWrapperInstance.css3DObject.position.copy(standingPosition.clone().setY(standingPosition.y + 0.01));
159
+ this.roomInfoInstance.setRoom(this.data.room_observers[panoIndex].room);
160
+ }
140
161
  this.five.needsRender = true;
141
- if (this.compassMesh.material.opacity !== 0)
142
- return;
143
- this.compassMeshTween?.dispose();
144
- this.compassMeshTween = tweenProgress(1000)
145
- .onUpdate(({ progress }) => {
146
- this.compassMesh?.material.setValues({ opacity: progress });
147
- this.five.needsRender = true;
148
- })
149
- .play();
150
162
  };
151
- onFiveCameraDirectionUpdate = ({ longitude, latitude }) => {
163
+ onFiveCameraDirectionUpdate = ({ longitude, latitude, }) => {
152
164
  if (!this.roomInfoWrapperInstance)
153
165
  return;
154
166
  this.roomInfoWrapperInstance.css3DObject.rotation.z = longitude;
@@ -0,0 +1,36 @@
1
+ import Line from '../Model/line';
2
+ import Magnifier from '../Modules/Magnifier';
3
+ import FiveHelper from '../Modules/FiveHelper';
4
+ import { Group } from 'three';
5
+ import { Model } from '../Model';
6
+ import { PluginEvent } from '../typings/event.type';
7
+ import { Five, Intersection, IntersectMeshInterface, Subscribe } from '@realsee/five';
8
+ import { UserDistanceItem } from '../utils/distanceDom';
9
+ export interface IControllerParams {
10
+ five: Five;
11
+ group: Group;
12
+ model: Model;
13
+ mouseGroup: Group;
14
+ container: Element;
15
+ magnifier: Magnifier;
16
+ fiveHelper: FiveHelper;
17
+ hook: Subscribe<PluginEvent>;
18
+ userDistanceItemCreator?: () => UserDistanceItem;
19
+ }
20
+ export default abstract class BaseController {
21
+ protected five: Five;
22
+ protected group: Group;
23
+ protected model: Model;
24
+ protected disposed: boolean;
25
+ protected mouseGroup: Group;
26
+ protected container: Element;
27
+ protected fiveHelper: FiveHelper;
28
+ protected hook: IControllerParams['hook'];
29
+ protected magnifier: IControllerParams['magnifier'];
30
+ protected userDistanceItemCreator: IControllerParams['userDistanceItemCreator'];
31
+ constructor(params: IControllerParams);
32
+ protected removeLine(line: Line): void;
33
+ protected updateDistanceUI: () => void;
34
+ protected updateMouseGroup(intersection: Intersection, mesh?: IntersectMeshInterface): Group;
35
+ protected dispose(): void;
36
+ }
@@ -0,0 +1,69 @@
1
+ import { preventDefault } from '../utils/ironbox';
2
+ export default class BaseController {
3
+ five;
4
+ group;
5
+ model;
6
+ disposed = false;
7
+ mouseGroup;
8
+ container;
9
+ fiveHelper;
10
+ hook;
11
+ magnifier;
12
+ userDistanceItemCreator;
13
+ constructor(params) {
14
+ // ==================== Params ====================
15
+ this.five = params.five;
16
+ this.hook = params.hook;
17
+ this.model = params.model;
18
+ this.magnifier = params.magnifier;
19
+ this.container = params.container;
20
+ this.fiveHelper = params.fiveHelper;
21
+ this.userDistanceItemCreator = params.userDistanceItemCreator;
22
+ // ==================== Groups ====================
23
+ this.group = params.group;
24
+ this.mouseGroup = params.mouseGroup;
25
+ const fiveElement = this.five.getElement();
26
+ if (fiveElement) {
27
+ fiveElement.addEventListener('touchstart', preventDefault);
28
+ fiveElement.addEventListener('contextmenu', preventDefault);
29
+ }
30
+ }
31
+ removeLine(line) {
32
+ this.group.remove(line.mesh, line.lightMesh);
33
+ line.distanceItem.remove();
34
+ this.five.needsRender = true;
35
+ }
36
+ updateDistanceUI = () => {
37
+ this.model.lines.forEach((line) => line.distanceItem.update(this.five));
38
+ };
39
+ updateMouseGroup(intersection, mesh) {
40
+ if (!intersection)
41
+ return this.mouseGroup;
42
+ // ============ update mouseGroup position ============
43
+ const adsorbentPoint = this.fiveHelper.getAdsorbentPoint(intersection);
44
+ const viewPosition = adsorbentPoint ? adsorbentPoint : intersection.point;
45
+ this.mouseGroup.position.copy(viewPosition);
46
+ // ============ update mouseGroup quaternion ============
47
+ if (mesh) {
48
+ this.mouseGroup.quaternion.copy(mesh.quaternion);
49
+ }
50
+ else if (intersection.face) {
51
+ const normal = intersection.face.normal;
52
+ const positionVector = normal.clone().multiplyScalar(0.05);
53
+ const position = intersection.point.clone().add(positionVector);
54
+ const lookAtVector = position.clone().add(positionVector);
55
+ this.mouseGroup.lookAt(lookAtVector);
56
+ }
57
+ return this.mouseGroup;
58
+ }
59
+ dispose() {
60
+ this.disposed = true;
61
+ this.magnifier.dispose();
62
+ this.model.lines.forEach((line) => this.removeLine(line));
63
+ const fiveElement = this.five.getElement();
64
+ if (fiveElement) {
65
+ fiveElement.removeEventListener('touchstart', preventDefault);
66
+ fiveElement.removeEventListener('contextmenu', preventDefault);
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,52 @@
1
+ import { Model } from '../Model';
2
+ import Line from '../Model/line';
3
+ import { LineJson } from '../typings/data';
4
+ import BaseController, { IControllerParams } from './BaseController';
5
+ export interface EditEvent {
6
+ editedLineChange: (lines: LineJson[]) => void;
7
+ }
8
+ export default class EditController extends BaseController {
9
+ type: string;
10
+ model: Model;
11
+ private pressPoint?;
12
+ private hasAppendDashed;
13
+ private hasAppendMouseGroup;
14
+ private fiveElement?;
15
+ /** 上一个端点位置 */
16
+ private lastPoint;
17
+ /** 鼠标点到上一个端点连接的虚线 */
18
+ private dashed;
19
+ private hammer?;
20
+ /** 根据 intersection 更新放大镜和吸附点 */
21
+ private onIntersectionUpdate;
22
+ constructor(params: IControllerParams);
23
+ dispose(): void;
24
+ getEditingLines(): Line[];
25
+ /** 撤销编辑 */
26
+ revoke: () => void;
27
+ private onMouseLeave;
28
+ /** 编辑线条发生改变时通知外部 */
29
+ private onLineChanged;
30
+ private onPress;
31
+ /**
32
+ * 1. 如果之前没有长按行为「即没有长按点时」-> 滑动全景
33
+ * 2. 如果有长按点,把长按点位置更新为当前位置
34
+ */
35
+ private onPan;
36
+ private onPanEnd;
37
+ /**
38
+ * 1. 如果存在上一个点,需要绘制当前点到上一个点的连线
39
+ * 2. 把上一个点的位置更新为当前点的位置
40
+ * 3. 清除 mouseGroup 和 magnifier
41
+ */
42
+ private onTap;
43
+ private onWantsTapGesture;
44
+ /** 编辑时取消走点 */
45
+ private onWantsToMoveToPano;
46
+ /** 存在长按点时不能移动全景 */
47
+ private onWantsPanGesture;
48
+ /** 移动全景时更新 distanceItem 在屏幕上的位置 */
49
+ private onCameraUpdate;
50
+ /** 更新虚线 */
51
+ private updateDashed;
52
+ }
@@ -0,0 +1,216 @@
1
+ import Hammer from 'hammerjs';
2
+ import { Model } from '../Model';
3
+ import Line from '../Model/line';
4
+ import Point from '../Model/point';
5
+ import throttle from '../../shared-utils/throttle';
6
+ import BaseController from './BaseController';
7
+ import { getIntersectionFromEvent } from '../utils/getIntersectionFromEvent';
8
+ export default class EditController extends BaseController {
9
+ type = 'edit';
10
+ model = new Model({ userDistanceItemCreator: this.userDistanceItemCreator });
11
+ pressPoint;
12
+ hasAppendDashed = false;
13
+ hasAppendMouseGroup = false;
14
+ fiveElement;
15
+ /** 上一个端点位置 */
16
+ lastPoint = null;
17
+ /** 鼠标点到上一个端点连接的虚线 */
18
+ dashed;
19
+ hammer;
20
+ /** 根据 intersection 更新放大镜和吸附点 */
21
+ onIntersectionUpdate = throttle((intersection, mesh) => {
22
+ if (this.hasAppendMouseGroup === false) {
23
+ this.group.add(this.mouseGroup);
24
+ this.magnifier.appendTo(this.container);
25
+ this.hasAppendMouseGroup = true;
26
+ }
27
+ const position = this.updateMouseGroup(intersection, mesh).position;
28
+ this.pressPoint?.position.copy(position);
29
+ this.updateDashed();
30
+ requestAnimationFrame(() => this.magnifier.updateWithPoint(this.mouseGroup.position));
31
+ this.five.needsRender = true;
32
+ }, 20);
33
+ constructor(params) {
34
+ super(params);
35
+ // ==================== 虚线 ====================
36
+ this.dashed = new Line(new Point([0, 0, 0]), new Point([0, 0, 0]), this.model);
37
+ this.dashed.mesh.setMaterial({ dashed: true, dashScale: 100 });
38
+ // ==================== 事件监听 ====================
39
+ // five
40
+ this.five.on('cameraUpdate', this.onCameraUpdate);
41
+ this.five.on('wantsPanGesture', this.onWantsPanGesture);
42
+ this.five.on('wantsTapGesture', this.onWantsTapGesture);
43
+ this.five.on('wantsToMoveToPano', this.onWantsToMoveToPano);
44
+ this.five.on('intersectionOnModelUpdate', this.onIntersectionUpdate);
45
+ // model
46
+ this.model.hook.on('lineAdded', this.onLineChanged);
47
+ this.model.hook.on('lineRemoved', this.onLineChanged);
48
+ // hammer
49
+ const fiveElement = this.five.getElement();
50
+ if (fiveElement) {
51
+ this.fiveElement = fiveElement;
52
+ const hammer = new Hammer(fiveElement);
53
+ this.hammer = hammer;
54
+ hammer.on('tap', this.onTap);
55
+ hammer.on('pan', this.onPan);
56
+ hammer.on('press', this.onPress);
57
+ hammer.on('panend', this.onPanEnd);
58
+ }
59
+ // fiveElement
60
+ this.fiveElement?.addEventListener('mouseleave', this.onMouseLeave);
61
+ // ==================== 其他 ====================
62
+ this.hook.emit('anchorChange', null);
63
+ this.five.refresh();
64
+ }
65
+ dispose() {
66
+ super.dispose();
67
+ this.group.remove(this.mouseGroup, this.dashed.mesh);
68
+ // ==================== 解除事件监听 ====================
69
+ // five
70
+ this.five.off('cameraUpdate', this.onCameraUpdate);
71
+ this.five.off('wantsPanGesture', this.onWantsPanGesture);
72
+ this.five.off('wantsTapGesture', this.onWantsTapGesture);
73
+ this.five.off('wantsToMoveToPano', this.onWantsToMoveToPano);
74
+ this.five.off('intersectionOnModelUpdate', this.onIntersectionUpdate);
75
+ // model
76
+ this.model.hook.off('lineAdded', this.onLineChanged);
77
+ this.model.hook.off('lineRemoved', this.onLineChanged);
78
+ // hammer
79
+ this.hammer?.destroy();
80
+ // fiveElement
81
+ this.fiveElement?.removeEventListener('mouseleave', this.onMouseLeave);
82
+ this.magnifier.dispose();
83
+ this.dashed.distanceItem.remove();
84
+ this.five.needsRender = true;
85
+ }
86
+ getEditingLines() {
87
+ return this.model.lines;
88
+ }
89
+ /** 撤销编辑 */
90
+ revoke = () => {
91
+ // ============ revoke points ============
92
+ // 如果当前没有虚线,只有起始点,需要删除起始点,重置起始状态。并删除虚线实例
93
+ if (this.model.lines.length === 0 && this.lastPoint) {
94
+ this.lastPoint = null;
95
+ this.hasAppendDashed = false;
96
+ this.dashed.distanceItem.remove();
97
+ this.group.remove(this.dashed.mesh);
98
+ this.hook.emit('anchorChange', null);
99
+ this.five.needsRender = true;
100
+ return;
101
+ }
102
+ if (this.model.lines.length === 0 && !this.lastPoint)
103
+ return;
104
+ if (!this.lastPoint)
105
+ return;
106
+ const revokedLine = this.model.lines[this.model.lines.length - 1];
107
+ const lastPoint = revokedLine.findAnotherPoint(this.lastPoint);
108
+ if (!lastPoint)
109
+ return;
110
+ this.lastPoint = lastPoint;
111
+ this.hook.emit('anchorChange', lastPoint.position);
112
+ // ============ revoke lines ============
113
+ this.group.remove(revokedLine.mesh);
114
+ this.model.removeLine(revokedLine);
115
+ // ============ revoke mouse group ============
116
+ this.hasAppendMouseGroup = false;
117
+ this.mouseGroup.position.copy(this.lastPoint.position);
118
+ this.group.remove(this.mouseGroup);
119
+ // ============ revoke lineDistance ============
120
+ revokedLine.distanceItem.remove();
121
+ // ============ revoke dashed ============
122
+ this.updateDashed();
123
+ // ============ revoke magnifier ============
124
+ this.magnifier.dispose();
125
+ this.five.needsRender = true;
126
+ };
127
+ onMouseLeave = () => {
128
+ this.magnifier.dispose();
129
+ this.group.remove(this.mouseGroup);
130
+ this.hasAppendMouseGroup = false;
131
+ if (this.lastPoint) {
132
+ this.mouseGroup.position.copy(this.lastPoint.position);
133
+ this.updateDashed();
134
+ }
135
+ };
136
+ /** 编辑线条发生改变时通知外部 */
137
+ onLineChanged = () => {
138
+ this.hook.emit('editedLineChange', this.model.lines.map((line) => line.toCompletelyJson()));
139
+ };
140
+ onPress = (e) => {
141
+ const [intersection] = getIntersectionFromEvent(this.five, e);
142
+ if (!intersection || !intersection.face)
143
+ return;
144
+ const nowPoint = new Point(intersection.point);
145
+ this.pressPoint = nowPoint;
146
+ this.onIntersectionUpdate(intersection);
147
+ };
148
+ /**
149
+ * 1. 如果之前没有长按行为「即没有长按点时」-> 滑动全景
150
+ * 2. 如果有长按点,把长按点位置更新为当前位置
151
+ */
152
+ onPan = (e) => {
153
+ if (!this.pressPoint)
154
+ return;
155
+ const [intersection] = getIntersectionFromEvent(this.five, e);
156
+ if (!intersection || !intersection.face)
157
+ return;
158
+ this.onIntersectionUpdate(intersection);
159
+ };
160
+ onPanEnd = (e) => {
161
+ if (!this.pressPoint)
162
+ return;
163
+ this.onTap(e);
164
+ };
165
+ /**
166
+ * 1. 如果存在上一个点,需要绘制当前点到上一个点的连线
167
+ * 2. 把上一个点的位置更新为当前点的位置
168
+ * 3. 清除 mouseGroup 和 magnifier
169
+ */
170
+ onTap = (e) => {
171
+ if (!this.hasAppendDashed) {
172
+ this.dashed.distanceItem.appendTo(this.container);
173
+ this.group.add(this.dashed.mesh);
174
+ }
175
+ this.hasAppendDashed = true;
176
+ const [intersection] = getIntersectionFromEvent(this.five, e);
177
+ this.updateMouseGroup(intersection);
178
+ const nowPoint = new Point(this.mouseGroup.position);
179
+ const lastPoint = this.lastPoint;
180
+ if (nowPoint)
181
+ this.lastPoint = nowPoint;
182
+ if (nowPoint && lastPoint) {
183
+ const line = new Line(lastPoint, nowPoint, this.model);
184
+ line.distanceItem.appendTo(this.container);
185
+ this.model.addLine(line);
186
+ this.group.add(line.mesh);
187
+ line.distanceItem.update(this.five);
188
+ }
189
+ this.pressPoint = undefined;
190
+ this.hasAppendMouseGroup = false;
191
+ this.magnifier.dispose();
192
+ this.group.remove(this.mouseGroup);
193
+ this.updateDashed();
194
+ this.five.needsRender = true;
195
+ this.hook.emit('anchorChange', nowPoint.position);
196
+ };
197
+ onWantsTapGesture = () => false;
198
+ /** 编辑时取消走点 */
199
+ onWantsToMoveToPano = () => false;
200
+ /** 存在长按点时不能移动全景 */
201
+ onWantsPanGesture = () => (this.pressPoint ? false : undefined);
202
+ /** 移动全景时更新 distanceItem 在屏幕上的位置 */
203
+ onCameraUpdate = () => {
204
+ this.updateDistanceUI();
205
+ this.dashed.distanceItem.update(this.five);
206
+ };
207
+ /** 更新虚线 */
208
+ updateDashed = () => {
209
+ if (!this.lastPoint)
210
+ return;
211
+ this.dashed.points[0].position.copy(this.lastPoint.position);
212
+ this.dashed.points[1].position.copy(this.mouseGroup.position);
213
+ this.dashed.mesh.setPoints(this.lastPoint.position, this.mouseGroup.position);
214
+ this.dashed.distanceItem.update(this.five);
215
+ };
216
+ }
@@ -0,0 +1,12 @@
1
+ import MeasureController from '.';
2
+ import { Five } from '@realsee/five';
3
+ /** 快捷键控制器 */
4
+ export declare class ShortcutKeyController {
5
+ five: Five;
6
+ measureController: MeasureController;
7
+ constructor(measureController: MeasureController, five: Five);
8
+ dispose(): void;
9
+ private escape;
10
+ private onKeyDown;
11
+ private onMouseDown;
12
+ }
@@ -0,0 +1,44 @@
1
+ /** 快捷键控制器 */
2
+ export class ShortcutKeyController {
3
+ five;
4
+ measureController;
5
+ constructor(measureController, five) {
6
+ this.five = five;
7
+ this.measureController = measureController;
8
+ const fiveElement = this.five.getElement();
9
+ if (!fiveElement)
10
+ return;
11
+ document.body.addEventListener('keydown', this.onKeyDown);
12
+ fiveElement.addEventListener('mousedown', this.onMouseDown);
13
+ }
14
+ dispose() {
15
+ const fiveElement = this.five.getElement();
16
+ if (!fiveElement)
17
+ return;
18
+ document.body.removeEventListener('keydown', this.onKeyDown);
19
+ fiveElement.removeEventListener('mousedown', this.onMouseDown);
20
+ }
21
+ escape() {
22
+ if (this.measureController.getCurrentMode() === 'Watch')
23
+ return this.measureController.disable();
24
+ return this.measureController.changeMode('Watch');
25
+ }
26
+ onKeyDown = (e) => {
27
+ // Command + S -> 保存 & 更改场景
28
+ if (e.metaKey && e.code === 'KeyS') {
29
+ this.measureController.save().changeMode('Watch');
30
+ e.preventDefault();
31
+ return;
32
+ }
33
+ // Escape -> 切换到观察模式 / 如果已经在观察模式,退出功能
34
+ if (e.code === 'Escape')
35
+ return this.escape();
36
+ };
37
+ onMouseDown = (e) => {
38
+ // 鼠标右键取消
39
+ if (e.button !== 2)
40
+ return;
41
+ e.preventDefault();
42
+ this.escape();
43
+ };
44
+ }
@@ -0,0 +1,25 @@
1
+ import Line from '../Model/line';
2
+ import BaseController, { IControllerParams } from './BaseController';
3
+ export default class WatchController extends BaseController {
4
+ type: string;
5
+ private deleteDom;
6
+ private highlightedLines;
7
+ private fiveElement?;
8
+ private editPointState?;
9
+ private hammer?;
10
+ constructor(params: IControllerParams);
11
+ dispose(): void;
12
+ highlightLine(line: Line): void;
13
+ clearHighlightLines(): void;
14
+ private onPanStart;
15
+ private onPanEnd;
16
+ private onPan;
17
+ private onIntersectionUpdate;
18
+ private wantsPanGesture;
19
+ private wantsTapGesture;
20
+ private chooseLine;
21
+ private highlightLines;
22
+ private lineRemoved;
23
+ private onCameraUpdate;
24
+ private deleteDomClickCallback;
25
+ }