@realsee/dnalogel 2.0.0-alpha.7 → 2.0.0-beta.36

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 (605) hide show
  1. package/README.md +78 -28
  2. package/components/index.js +1450 -0
  3. package/dist/CSS3DRenderPlugin/Plugin.d.ts +49 -0
  4. package/dist/CSS3DRenderPlugin/index.d.ts +4 -0
  5. package/dist/CSS3DRenderPlugin/index.js +234 -0
  6. package/dist/CSS3DRenderPlugin/utils/createResizeObserver.d.ts +7 -0
  7. package/dist/CameraMovementPlugin/CameraMovementPlugin.d.ts +7 -0
  8. package/dist/CameraMovementPlugin/index.d.ts +5 -0
  9. package/dist/CameraMovementPlugin/index.js +302 -0
  10. package/dist/CameraMovementPlugin/typing.d.ts +68 -0
  11. package/dist/ItemLabelPlugin/Plugin.d.ts +4 -0
  12. package/dist/ItemLabelPlugin/events.type.d.ts +9 -0
  13. package/dist/ItemLabelPlugin/index.d.ts +9 -0
  14. package/dist/ItemLabelPlugin/index.js +941 -0
  15. package/dist/ItemLabelPlugin/typings.d.ts +59 -0
  16. package/dist/ItemLabelPlugin/utils/getLabelTransform.d.ts +1 -0
  17. package/dist/ItemLabelPlugin/utils/getStrokeLength.d.ts +5 -0
  18. package/dist/ItemLabelPlugin/utils/isImpacted.d.ts +6 -0
  19. package/dist/ItemLabelPlugin/utils/parseData.d.ts +3 -0
  20. package/dist/ItemLabelPlugin/utils/transform2RenderData.d.ts +3 -0
  21. package/dist/ModelChassisCompassPlugin/Plugin.d.ts +19 -0
  22. package/dist/ModelChassisCompassPlugin/index.d.ts +4 -0
  23. package/dist/ModelChassisCompassPlugin/index.js +145 -0
  24. package/dist/ModelEntryDoorGuidePlugin/Plugin.d.ts +26 -0
  25. package/dist/ModelEntryDoorGuidePlugin/index.d.ts +4 -0
  26. package/dist/ModelEntryDoorGuidePlugin/index.js +196 -0
  27. package/dist/ModelItemLabelPlugin/ModelItemLabelPlugin.d.ts +4 -0
  28. package/dist/ModelItemLabelPlugin/events.type.d.ts +9 -0
  29. package/dist/ModelItemLabelPlugin/index.d.ts +9 -0
  30. package/dist/ModelItemLabelPlugin/index.js +674 -0
  31. package/dist/ModelItemLabelPlugin/typings.d.ts +56 -0
  32. package/dist/ModelItemLabelPlugin/utils/parseData.d.ts +3 -0
  33. package/dist/ModelRoomLabelPlugin/Assets/roomLabelBg.d.ts +1 -0
  34. package/dist/ModelRoomLabelPlugin/Controller.d.ts +36 -0
  35. package/dist/ModelRoomLabelPlugin/index.d.ts +12 -0
  36. package/dist/ModelRoomLabelPlugin/index.js +541 -0
  37. package/dist/ModelRoomLabelPlugin/typings.d.ts +35 -0
  38. package/dist/ModelRoomLabelPlugin/utils/parseData.d.ts +3 -0
  39. package/dist/ModelTVVideoPlugin/Plugin.d.ts +4 -0
  40. package/dist/ModelTVVideoPlugin/index.d.ts +5 -0
  41. package/dist/ModelTVVideoPlugin/index.js +301 -0
  42. package/dist/ModelTVVideoPlugin/typings.d.ts +25 -0
  43. package/dist/ModelTVVideoPlugin/utils/parseData.d.ts +2 -0
  44. package/dist/ModelViewPlugin/Plugin.d.ts +17 -0
  45. package/dist/ModelViewPlugin/index.d.ts +4 -0
  46. package/dist/ModelViewPlugin/index.js +187 -0
  47. package/dist/PanoCompassPlugin/Assets/roomInfoIcon.d.ts +1 -0
  48. package/dist/PanoCompassPlugin/Plugin.d.ts +47 -0
  49. package/dist/PanoCompassPlugin/getRoomInfoInstance.d.ts +8 -0
  50. package/dist/PanoCompassPlugin/index.d.ts +8 -0
  51. package/dist/PanoCompassPlugin/index.js +636 -0
  52. package/dist/PanoCursorRaycasterPlugin/index.d.ts +48 -0
  53. package/dist/PanoCursorRaycasterPlugin/index.js +90 -0
  54. package/dist/PanoMeasurePlugin/Controller/BaseController.d.ts +39 -0
  55. package/dist/PanoMeasurePlugin/Controller/EditController.d.ts +52 -0
  56. package/dist/PanoMeasurePlugin/Controller/MixedController.d.ts +44 -0
  57. package/dist/PanoMeasurePlugin/Controller/ShortcutKeyController.d.ts +12 -0
  58. package/dist/PanoMeasurePlugin/Controller/WatchController.d.ts +26 -0
  59. package/dist/PanoMeasurePlugin/Controller/index.d.ts +70 -0
  60. package/dist/PanoMeasurePlugin/Model/index.d.ts +38 -0
  61. package/dist/PanoMeasurePlugin/Model/line.d.ts +30 -0
  62. package/dist/PanoMeasurePlugin/Model/point.d.ts +16 -0
  63. package/dist/PanoMeasurePlugin/Model/polyline.d.ts +16 -0
  64. package/dist/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.d.ts +2 -0
  65. package/dist/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.d.ts +2 -0
  66. package/dist/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_hover_bg.png.d.ts +2 -0
  67. package/dist/PanoMeasurePlugin/Modules/DeleteDom/index.d.ts +25 -0
  68. package/dist/PanoMeasurePlugin/Modules/FiveHelper.d.ts +11 -0
  69. package/dist/PanoMeasurePlugin/Modules/GuideController.d.ts +18 -0
  70. package/dist/PanoMeasurePlugin/Modules/Magnifier.d.ts +59 -0
  71. package/dist/PanoMeasurePlugin/Modules/UIController/HTML.d.ts +6 -0
  72. package/dist/PanoMeasurePlugin/Modules/UIController/MainBtnController.d.ts +18 -0
  73. package/dist/PanoMeasurePlugin/Modules/UIController/NewMainBtnController.d.ts +12 -0
  74. package/dist/PanoMeasurePlugin/Modules/UIController/Revoke/index.d.ts +13 -0
  75. package/dist/PanoMeasurePlugin/Modules/UIController/index.d.ts +20 -0
  76. package/dist/PanoMeasurePlugin/Modules/UIController/mobileHTML.d.ts +2 -0
  77. package/dist/PanoMeasurePlugin/Modules/UIController/style.d.ts +19 -0
  78. package/dist/PanoMeasurePlugin/Modules/rangePiece/html.d.ts +4 -0
  79. package/dist/PanoMeasurePlugin/Modules/rangePiece/index.d.ts +42 -0
  80. package/dist/PanoMeasurePlugin/index.d.ts +10 -0
  81. package/dist/PanoMeasurePlugin/index.js +3996 -0
  82. package/dist/PanoMeasurePlugin/typings/data.d.ts +32 -0
  83. package/dist/PanoMeasurePlugin/typings/event.type.d.ts +37 -0
  84. package/dist/PanoMeasurePlugin/typings/utils.type.d.ts +1 -0
  85. package/dist/PanoMeasurePlugin/utils/calculateThreeMouse.d.ts +10 -0
  86. package/dist/PanoMeasurePlugin/utils/clearGroup.d.ts +2 -0
  87. package/dist/PanoMeasurePlugin/utils/constants.d.ts +4 -0
  88. package/dist/PanoMeasurePlugin/utils/distanceDom.d.ts +28 -0
  89. package/dist/PanoMeasurePlugin/utils/findAssociatedLines.d.ts +2 -0
  90. package/dist/PanoMeasurePlugin/utils/findClosestPoint.d.ts +10 -0
  91. package/dist/PanoMeasurePlugin/utils/getIntersectionFromEvent.d.ts +4 -0
  92. package/dist/PanoMeasurePlugin/utils/getPointFromHammerEvent.d.ts +10 -0
  93. package/dist/PanoMeasurePlugin/utils/ironbox.d.ts +1 -0
  94. package/dist/PanoMeasurePlugin/utils/isNDCPointInScreen.d.ts +2 -0
  95. package/dist/PanoMeasurePlugin/utils/line.d.ts +17 -0
  96. package/dist/PanoMeasurePlugin/utils/math.d.ts +17 -0
  97. package/dist/PanoMeasurePlugin/utils/mouseGroup.d.ts +2 -0
  98. package/dist/PanoMeasurePlugin/utils/ndc2Screen.d.ts +5 -0
  99. package/dist/PanoRulerPlugin/Plugin.d.ts +31 -0
  100. package/dist/PanoRulerPlugin/index.d.ts +5 -0
  101. package/dist/PanoRulerPlugin/index.js +610 -0
  102. package/dist/PanoRulerPlugin/style.d.ts +2 -0
  103. package/dist/PanoRulerPlugin/typings.d.ts +21 -0
  104. package/dist/PanoSpatialTagPlugin/Plugin.d.ts +35 -0
  105. package/dist/PanoSpatialTagPlugin/index.d.ts +5 -0
  106. package/dist/PanoSpatialTagPlugin/index.js +1307 -0
  107. package/dist/PanoSpatialTagPlugin/store.d.ts +1 -0
  108. package/dist/PanoSpatialTagPlugin/style.d.ts +1 -0
  109. package/dist/PanoSpatialTagPlugin/typings.d.ts +40 -0
  110. package/dist/base/BasePlugin.d.ts +100 -0
  111. package/dist/base/BasePluginWithData.d.ts +34 -0
  112. package/dist/components/PaintBrush/Controller.d.ts +43 -0
  113. package/dist/components/PaintBrush/Subscribe.d.ts +76 -0
  114. package/dist/components/PaintBrush/index.d.ts +27 -0
  115. package/dist/components/PaintBrush/style.d.ts +2 -0
  116. package/dist/components/PaintBrush/tween.d.ts +62 -0
  117. package/dist/components/PaintBrush/typings.d.ts +58 -0
  118. package/dist/components/PaintBrush/utils.d.ts +26 -0
  119. package/dist/components/index.d.ts +2 -0
  120. package/dist/floorplan/Assets/camera.d.ts +1 -0
  121. package/dist/floorplan/Assets/compass.d.ts +1 -0
  122. package/dist/floorplan/Assets/floorplanExtraObject.d.ts +1 -0
  123. package/dist/floorplan/ModelFloorplanPlugin/Controller.d.ts +97 -0
  124. package/dist/floorplan/ModelFloorplanPlugin/index.d.ts +7 -0
  125. package/dist/floorplan/ModelFloorplanPlugin/index.js +4526 -0
  126. package/dist/floorplan/ModelFloorplanPlugin/typing.d.ts +107 -0
  127. package/dist/floorplan/ModelFloorplanPlugin/typings/events.type.d.ts +23 -0
  128. package/dist/floorplan/ModelFloorplanPlugin/utils/constant.d.ts +15 -0
  129. package/dist/floorplan/ModelFloorplanPlugin/utils/correctFiveState.d.ts +14 -0
  130. package/dist/floorplan/PanoFloorplanRadarPlugin/Controller.d.ts +36 -0
  131. package/dist/floorplan/PanoFloorplanRadarPlugin/index.d.ts +7 -0
  132. package/dist/floorplan/PanoFloorplanRadarPlugin/index.js +2008 -0
  133. package/dist/floorplan/PanoFloorplanRadarPlugin/typing.d.ts +52 -0
  134. package/dist/floorplan/TopviewFloorplanPlugin/Controller.d.ts +67 -0
  135. package/dist/floorplan/TopviewFloorplanPlugin/index.d.ts +7 -0
  136. package/dist/floorplan/TopviewFloorplanPlugin/index.js +4236 -0
  137. package/dist/floorplan/TopviewFloorplanPlugin/style.d.ts +1 -0
  138. package/dist/floorplan/TopviewFloorplanPlugin/typing.d.ts +86 -0
  139. package/dist/floorplan/constant.d.ts +5 -0
  140. package/dist/floorplan/index.d.ts +6 -0
  141. package/dist/floorplan/typings/floorplanData.d.ts +137 -0
  142. package/dist/floorplan/typings/floorplanServerData.d.ts +131 -0
  143. package/dist/floorplan/typings/utility.d.ts +2 -0
  144. package/dist/floorplan/utils/constant.d.ts +22 -0
  145. package/dist/floorplan/utils/correctFiveState.d.ts +15 -0
  146. package/dist/floorplan/utils/formatData.d.ts +5 -0
  147. package/dist/floorplan/utils/formatPosition.d.ts +36 -0
  148. package/dist/index.d.ts +15 -0
  149. package/dist/index.es.js +15436 -0
  150. package/dist/index.js +15488 -0
  151. package/dist/index.umd.js +15480 -0
  152. package/dist/shared-utils/Preloader.d.ts +6 -0
  153. package/dist/shared-utils/Subscribe.d.ts +45 -0
  154. package/dist/shared-utils/animationFrame/BetterTween.d.ts +11 -0
  155. package/dist/shared-utils/animationFrame/calculateProgress.d.ts +8 -0
  156. package/dist/shared-utils/animationFrame/formatRad.d.ts +15 -0
  157. package/dist/shared-utils/animationFrame/index.d.ts +15 -0
  158. package/dist/shared-utils/animationFrame/tween.d.ts +75 -0
  159. package/dist/shared-utils/changeModelCanvasOpacity.d.ts +2 -0
  160. package/dist/shared-utils/createCanvasTextTexture.d.ts +8 -0
  161. package/dist/shared-utils/createLine/index.d.ts +3 -0
  162. package/dist/shared-utils/debounce.d.ts +6 -0
  163. package/dist/shared-utils/equal.d.ts +11 -0
  164. package/dist/shared-utils/filter.d.ts +27 -0
  165. package/dist/shared-utils/five/changeMode.d.ts +5 -0
  166. package/dist/shared-utils/formatRad.d.ts +7 -0
  167. package/dist/shared-utils/getPxmm.d.ts +19 -0
  168. package/dist/shared-utils/getRandomColor.d.ts +1 -0
  169. package/dist/shared-utils/index.d.ts +1 -0
  170. package/dist/shared-utils/isNil.d.ts +10 -0
  171. package/dist/shared-utils/isTruelyObject.d.ts +18 -0
  172. package/dist/shared-utils/math/Interval.d.ts +13 -0
  173. package/dist/shared-utils/math/Rectangle.d.ts +27 -0
  174. package/dist/shared-utils/math/evenNumber.d.ts +3 -0
  175. package/dist/shared-utils/math/index.d.ts +2 -0
  176. package/dist/shared-utils/math/planimetry.d.ts +116 -0
  177. package/dist/shared-utils/math/rad2Deg.d.ts +1 -0
  178. package/dist/shared-utils/nearlyEqual.d.ts +7 -0
  179. package/dist/shared-utils/nextFrame.d.ts +1 -0
  180. package/dist/shared-utils/noop.d.ts +5 -0
  181. package/dist/shared-utils/object3d2LocalMatrix.d.ts +12 -0
  182. package/dist/shared-utils/px2rem.d.ts +1 -0
  183. package/dist/shared-utils/removeArrayItem.d.ts +7 -0
  184. package/dist/shared-utils/tap.d.ts +8 -0
  185. package/dist/shared-utils/three/centerPoint.d.ts +2 -0
  186. package/dist/shared-utils/three/getExtraModelLoader.d.ts +6 -0
  187. package/dist/shared-utils/three/getNormal.d.ts +2 -0
  188. package/dist/shared-utils/three/getTextureLoader.d.ts +6 -0
  189. package/dist/shared-utils/three/loadFbxObj.d.ts +2 -0
  190. package/dist/shared-utils/three/loadTexture.d.ts +2 -0
  191. package/dist/shared-utils/three/transformPositionToVector3.d.ts +7 -0
  192. package/dist/shared-utils/three/transfromToMeshBasicMaterial.d.ts +2 -0
  193. package/dist/shared-utils/throttle.d.ts +7 -0
  194. package/dist/shared-utils/tinyEJSrender.d.ts +5 -0
  195. package/dist/shared-utils/to.d.ts +8 -0
  196. package/dist/shared-utils/uuid.d.ts +5 -0
  197. package/dist/shared-utils/vectorTocoordinates.d.ts +7 -0
  198. package/dist/typings/math.type.d.ts +44 -0
  199. package/dist/typings/utils.type.d.ts +2 -0
  200. package/docs/.nojekyll +1 -0
  201. package/docs/assets/highlight.css +78 -0
  202. package/docs/assets/icons.css +1043 -0
  203. package/docs/assets/icons.png +0 -0
  204. package/docs/assets/icons@2x.png +0 -0
  205. package/docs/assets/main.js +52 -0
  206. package/docs/assets/search.js +1 -0
  207. package/docs/assets/style.css +1413 -0
  208. package/docs/assets/widgets.png +0 -0
  209. package/docs/assets/widgets@2x.png +0 -0
  210. package/docs/classes/Magnifier.html +9 -0
  211. package/docs/classes/ModelRoomLabelController.html +17 -0
  212. package/docs/enums/CameraMovementEffect.html +3 -0
  213. package/docs/enums/DIRECTION.html +1 -0
  214. package/docs/enums/DISPLAY_STRATEGY_TYPE.html +1 -0
  215. package/docs/enums/FLOOR_PLAN_ATTACHED_TO.html +1 -0
  216. package/docs/enums/ITEM_LABEL_PLUGIN_DISPLAY_STRATEGY_TYPE.html +1 -0
  217. package/docs/enums/Rotation.html +3 -0
  218. package/docs/index.html +88 -0
  219. package/docs/interfaces/CSS3DRenderPluginExportType.html +4 -0
  220. package/docs/interfaces/CameraMovementPluginExportType.html +17 -0
  221. package/docs/interfaces/FloorplanBounding.html +10 -0
  222. package/docs/interfaces/FloorplanData.html +3 -0
  223. package/docs/interfaces/FloorplanEntrance.html +15 -0
  224. package/docs/interfaces/FloorplanExtraObject.html +7 -0
  225. package/docs/interfaces/FloorplanExtraObject3D.html +3 -0
  226. package/docs/interfaces/FloorplanFloorData.html +3 -0
  227. package/docs/interfaces/FloorplanImagePosition.html +3 -0
  228. package/docs/interfaces/FloorplanObserver.html +5 -0
  229. package/docs/interfaces/FloorplanOutlineItem.html +3 -0
  230. package/docs/interfaces/FloorplanPosition.html +3 -0
  231. package/docs/interfaces/FloorplanRoomItem.html +17 -0
  232. package/docs/interfaces/FloorplanRoomLabelItem.html +7 -0
  233. package/docs/interfaces/FloorplanServerBounding.html +10 -0
  234. package/docs/interfaces/FloorplanServerComputedData.html +1 -0
  235. package/docs/interfaces/FloorplanServerData.html +3 -0
  236. package/docs/interfaces/FloorplanServerEntrance.html +15 -0
  237. package/docs/interfaces/FloorplanServerFloorData.html +3 -0
  238. package/docs/interfaces/FloorplanServerImagePosition.html +3 -0
  239. package/docs/interfaces/FloorplanServerObserver.html +5 -0
  240. package/docs/interfaces/FloorplanServerOutlineItem.html +3 -0
  241. package/docs/interfaces/FloorplanServerPosition.html +3 -0
  242. package/docs/interfaces/FloorplanServerRoomItem.html +20 -0
  243. package/docs/interfaces/FloorplanServerRoomLabelItem.html +7 -0
  244. package/docs/interfaces/ItemLabelPluginData.html +1 -0
  245. package/docs/interfaces/ItemLabelPluginExportReturnsType.html +1 -0
  246. package/docs/interfaces/ItemLabelPluginParametersType.html +1 -0
  247. package/docs/interfaces/LineJson.html +1 -0
  248. package/docs/interfaces/ModelChassisCompassPluginData.html +1 -0
  249. package/docs/interfaces/ModelChassisCompassPluginExportType.html +1 -0
  250. package/docs/interfaces/ModelChassisCompassPluginParameterType.html +1 -0
  251. package/docs/interfaces/ModelEntryDoorGuidePluginData.html +1 -0
  252. package/docs/interfaces/ModelEntryDoorGuidePluginExportType.html +1 -0
  253. package/docs/interfaces/ModelItemLabelPluginData.html +1 -0
  254. package/docs/interfaces/ModelItemLabelPluginExportReturnsType.html +1 -0
  255. package/docs/interfaces/ModelItemLabelPluginParametersType.html +1 -0
  256. package/docs/interfaces/ModelRoomLabelPluginData.html +1 -0
  257. package/docs/interfaces/ModelTVVideoPluginData.html +1 -0
  258. package/docs/interfaces/ModelTVVideoPluginExportType.html +1 -0
  259. package/docs/interfaces/ModelTVVideoPluginParameterType.html +1 -0
  260. package/docs/interfaces/ModelViewPluginExportType.html +1 -0
  261. package/docs/interfaces/OpenParameter.html +3 -0
  262. package/docs/interfaces/PanoCompassPluginData.html +1 -0
  263. package/docs/interfaces/PanoCompassPluginParameterType.html +1 -0
  264. package/docs/interfaces/PanoCursorRaycasterPluginExportType.html +11 -0
  265. package/docs/interfaces/PanoCursorRaycasterPluginParameterType.html +1 -0
  266. package/docs/interfaces/PanoMeasureParameterType.html +1 -0
  267. package/docs/interfaces/PanoRulerPluginExportType.html +1 -0
  268. package/docs/interfaces/PanoRulerPluginOptions.html +1 -0
  269. package/docs/interfaces/PanoRulerPluginParameterType.html +1 -0
  270. package/docs/interfaces/PanoSpatialTagPluginContentEvent.html +1 -0
  271. package/docs/interfaces/PanoSpatialTagPluginContentReplacement.html +1 -0
  272. package/docs/interfaces/PanoSpatialTagPluginData.html +1 -0
  273. package/docs/interfaces/PanoSpatialTagPluginDataElement.html +1 -0
  274. package/docs/interfaces/PanoSpatialTagPluginExportType.html +1 -0
  275. package/docs/interfaces/PanoSpatialTagPluginOriginElement.html +1 -0
  276. package/docs/interfaces/PanoSpatialTagPluginParameterType.html +1 -0
  277. package/docs/interfaces/PanoSpatialTagPluginPointElement.html +1 -0
  278. package/docs/interfaces/PanoSpatialTagPluginTagElement.html +1 -0
  279. package/docs/interfaces/Point.html +1 -0
  280. package/docs/interfaces/PointJson.html +1 -0
  281. package/docs/interfaces/Room.html +1 -0
  282. package/docs/interfaces/RoomInfo.html +1 -0
  283. package/docs/interfaces/RoomLabel.html +13 -0
  284. package/docs/interfaces/RoomRules.html +1 -0
  285. package/docs/interfaces/Rooms.html +1 -0
  286. package/docs/modules.html +34 -0
  287. package/libs/CSS3DRenderPlugin/Plugin.d.ts +49 -0
  288. package/libs/CSS3DRenderPlugin/Plugin.js +182 -0
  289. package/libs/CSS3DRenderPlugin/index.d.ts +3 -48
  290. package/libs/CSS3DRenderPlugin/index.js +2 -180
  291. package/libs/CameraMovementPlugin/CameraMovementPlugin.d.ts +7 -0
  292. package/libs/CameraMovementPlugin/CameraMovementPlugin.js +159 -0
  293. package/libs/CameraMovementPlugin/index.d.ts +4 -6
  294. package/libs/CameraMovementPlugin/index.js +3 -158
  295. package/libs/CameraMovementPlugin/typing.d.ts +1 -1
  296. package/libs/ItemLabelPlugin/ItemLabelComponent.js +577 -0
  297. package/libs/ItemLabelPlugin/ItemLabelItem.js +227 -0
  298. package/libs/ItemLabelPlugin/Plugin.d.ts +4 -0
  299. package/libs/ItemLabelPlugin/Plugin.js +120 -0
  300. package/libs/ItemLabelPlugin/events.type.d.ts +9 -0
  301. package/libs/ItemLabelPlugin/events.type.js +1 -0
  302. package/libs/ItemLabelPlugin/index.d.ts +9 -0
  303. package/libs/ItemLabelPlugin/index.js +8 -0
  304. package/libs/ItemLabelPlugin/typings.d.ts +59 -0
  305. package/libs/ItemLabelPlugin/typings.js +7 -0
  306. package/libs/ItemLabelPlugin/utils/getLabelTransform.d.ts +1 -0
  307. package/libs/ItemLabelPlugin/utils/getLabelTransform.js +3 -0
  308. package/libs/ItemLabelPlugin/utils/getStrokeLength.d.ts +5 -0
  309. package/libs/ItemLabelPlugin/utils/getStrokeLength.js +16 -0
  310. package/libs/ItemLabelPlugin/utils/isImpacted.d.ts +6 -0
  311. package/libs/ItemLabelPlugin/utils/isImpacted.js +13 -0
  312. package/libs/ItemLabelPlugin/utils/parseData.d.ts +3 -0
  313. package/libs/ItemLabelPlugin/utils/parseData.js +4 -0
  314. package/libs/ItemLabelPlugin/utils/transform2RenderData.d.ts +3 -0
  315. package/libs/ItemLabelPlugin/utils/transform2RenderData.js +4 -0
  316. package/libs/ModelChassisCompassPlugin/Plugin.d.ts +19 -0
  317. package/libs/ModelChassisCompassPlugin/Plugin.js +77 -0
  318. package/libs/ModelChassisCompassPlugin/index.d.ts +3 -18
  319. package/libs/ModelChassisCompassPlugin/index.js +2 -74
  320. package/libs/ModelEntryDoorGuidePlugin/Plugin.d.ts +26 -0
  321. package/libs/ModelEntryDoorGuidePlugin/Plugin.js +140 -0
  322. package/libs/ModelEntryDoorGuidePlugin/index.d.ts +3 -25
  323. package/libs/ModelEntryDoorGuidePlugin/index.js +2 -135
  324. package/libs/ModelItemLabelPlugin/ItemLabelComponent.js +409 -0
  325. package/libs/ModelItemLabelPlugin/ItemLabelItem.js +133 -0
  326. package/libs/ModelItemLabelPlugin/ModelItemLabelPlugin.d.ts +4 -0
  327. package/libs/ModelItemLabelPlugin/ModelItemLabelPlugin.js +120 -0
  328. package/libs/ModelItemLabelPlugin/events.type.d.ts +9 -0
  329. package/libs/ModelItemLabelPlugin/events.type.js +1 -0
  330. package/libs/ModelItemLabelPlugin/index.d.ts +9 -0
  331. package/libs/ModelItemLabelPlugin/index.js +8 -0
  332. package/libs/ModelItemLabelPlugin/typings.d.ts +56 -0
  333. package/libs/ModelItemLabelPlugin/typings.js +7 -0
  334. package/libs/ModelItemLabelPlugin/utils/parseData.d.ts +3 -0
  335. package/libs/ModelItemLabelPlugin/utils/parseData.js +4 -0
  336. package/libs/ModelRoomLabelPlugin/Controller.js +67 -25
  337. package/libs/ModelRoomLabelPlugin/RoomLabelItem.js +121 -0
  338. package/libs/ModelRoomLabelPlugin/RoomLabelItems.js +291 -0
  339. package/libs/ModelRoomLabelPlugin/utils/parseData.d.ts +1 -1
  340. package/libs/ModelSimulationPlugin/index.d.ts +33 -0
  341. package/libs/ModelSimulationPlugin/index.js +166 -0
  342. package/libs/ModelSimulationPlugin/shaders/fragment.d.ts +2 -0
  343. package/libs/ModelSimulationPlugin/shaders/fragment.js +96 -0
  344. package/libs/ModelSimulationPlugin/shaders/vertex.d.ts +2 -0
  345. package/libs/ModelSimulationPlugin/shaders/vertex.js +23 -0
  346. package/libs/ModelTVVideoPlugin/Plugin.d.ts +4 -0
  347. package/libs/ModelTVVideoPlugin/Plugin.js +254 -0
  348. package/libs/ModelTVVideoPlugin/index.d.ts +5 -0
  349. package/libs/ModelTVVideoPlugin/index.js +4 -0
  350. package/libs/ModelTVVideoPlugin/typings.d.ts +25 -0
  351. package/libs/ModelTVVideoPlugin/typings.js +8 -0
  352. package/libs/ModelTVVideoPlugin/utils/parseData.d.ts +2 -0
  353. package/libs/ModelTVVideoPlugin/utils/parseData.js +13 -0
  354. package/libs/ModelViewPlugin/Plugin.d.ts +17 -0
  355. package/libs/ModelViewPlugin/Plugin.js +160 -0
  356. package/libs/ModelViewPlugin/index.d.ts +3 -16
  357. package/libs/ModelViewPlugin/index.js +2 -159
  358. package/libs/PanoCompassPlugin/Plugin.d.ts +47 -0
  359. package/libs/PanoCompassPlugin/Plugin.js +249 -0
  360. package/libs/PanoCompassPlugin/index.d.ts +4 -47
  361. package/libs/PanoCompassPlugin/index.js +3 -167
  362. package/libs/PanoCursorRaycasterPlugin/index.d.ts +1 -1
  363. package/libs/PanoCursorRaycasterPlugin/index.js +5 -3
  364. package/libs/PanoMeasurePlugin/Controller/BaseController.d.ts +12 -9
  365. package/libs/PanoMeasurePlugin/Controller/BaseController.js +77 -14
  366. package/libs/PanoMeasurePlugin/Controller/EditController.d.ts +1 -1
  367. package/libs/PanoMeasurePlugin/Controller/EditController.js +267 -154
  368. package/libs/PanoMeasurePlugin/Controller/MixedController.d.ts +44 -0
  369. package/libs/PanoMeasurePlugin/Controller/MixedController.js +337 -0
  370. package/libs/PanoMeasurePlugin/Controller/ShortcutKeyController.d.ts +2 -2
  371. package/libs/PanoMeasurePlugin/Controller/ShortcutKeyController.js +40 -20
  372. package/libs/PanoMeasurePlugin/Controller/WatchController.d.ts +2 -1
  373. package/libs/PanoMeasurePlugin/Controller/WatchController.js +246 -153
  374. package/libs/PanoMeasurePlugin/Controller/index.d.ts +18 -9
  375. package/libs/PanoMeasurePlugin/Controller/index.js +182 -54
  376. package/libs/PanoMeasurePlugin/Model/index.d.ts +2 -2
  377. package/libs/PanoMeasurePlugin/Model/index.js +30 -5
  378. package/libs/PanoMeasurePlugin/Model/line.d.ts +5 -5
  379. package/libs/PanoMeasurePlugin/Model/line.js +61 -11
  380. package/libs/PanoMeasurePlugin/Model/point.d.ts +2 -2
  381. package/libs/PanoMeasurePlugin/Model/point.js +24 -4
  382. package/libs/PanoMeasurePlugin/Model/polyline.d.ts +3 -3
  383. package/libs/PanoMeasurePlugin/Model/polyline.js +20 -3
  384. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.d.ts +1 -1
  385. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.js +11 -14
  386. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.d.ts +1 -1
  387. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.js +1 -1
  388. package/libs/PanoMeasurePlugin/Modules/DeleteDom/index.d.ts +5 -2
  389. package/libs/PanoMeasurePlugin/Modules/DeleteDom/index.js +107 -25
  390. package/libs/PanoMeasurePlugin/Modules/FiveHelper.d.ts +1 -1
  391. package/libs/PanoMeasurePlugin/Modules/FiveHelper.js +23 -8
  392. package/libs/PanoMeasurePlugin/Modules/GuideController.d.ts +1 -1
  393. package/libs/PanoMeasurePlugin/Modules/GuideController.js +61 -26
  394. package/libs/PanoMeasurePlugin/Modules/Magnifier.d.ts +50 -15
  395. package/libs/PanoMeasurePlugin/Modules/Magnifier.js +234 -59
  396. package/libs/PanoMeasurePlugin/Modules/UIController/MainBtnController.d.ts +1 -1
  397. package/libs/PanoMeasurePlugin/Modules/UIController/MainBtnController.js +84 -38
  398. package/libs/PanoMeasurePlugin/Modules/UIController/NewMainBtnController.d.ts +12 -0
  399. package/libs/PanoMeasurePlugin/Modules/UIController/NewMainBtnController.js +98 -0
  400. package/libs/PanoMeasurePlugin/Modules/UIController/Revoke/index.d.ts +2 -1
  401. package/libs/PanoMeasurePlugin/Modules/UIController/Revoke/index.js +52 -17
  402. package/libs/PanoMeasurePlugin/Modules/UIController/index.d.ts +5 -1
  403. package/libs/PanoMeasurePlugin/Modules/UIController/index.js +84 -34
  404. package/libs/PanoMeasurePlugin/Modules/UIController/mobileHTML.d.ts +2 -0
  405. package/libs/PanoMeasurePlugin/Modules/UIController/mobileHTML.js +80 -0
  406. package/libs/PanoMeasurePlugin/Modules/UIController/style.d.ts +2 -0
  407. package/libs/PanoMeasurePlugin/Modules/UIController/style.js +11 -1
  408. package/libs/PanoMeasurePlugin/Modules/rangePiece/html.d.ts +4 -0
  409. package/libs/PanoMeasurePlugin/Modules/rangePiece/html.js +64 -0
  410. package/libs/PanoMeasurePlugin/Modules/rangePiece/index.d.ts +42 -0
  411. package/libs/PanoMeasurePlugin/Modules/rangePiece/index.js +265 -0
  412. package/libs/PanoMeasurePlugin/index.d.ts +9 -6
  413. package/libs/PanoMeasurePlugin/index.js +3 -1
  414. package/libs/PanoMeasurePlugin/typings/data.d.ts +4 -0
  415. package/libs/PanoMeasurePlugin/typings/event.type.d.ts +14 -5
  416. package/libs/PanoMeasurePlugin/utils/calculateThreeMouse.d.ts +10 -0
  417. package/libs/PanoMeasurePlugin/utils/calculateThreeMouse.js +15 -0
  418. package/libs/PanoMeasurePlugin/utils/clearGroup.d.ts +1 -1
  419. package/libs/PanoMeasurePlugin/utils/constants.d.ts +1 -1
  420. package/libs/PanoMeasurePlugin/utils/constants.js +7 -7
  421. package/libs/PanoMeasurePlugin/utils/distanceDom.d.ts +3 -3
  422. package/libs/PanoMeasurePlugin/utils/distanceDom.js +22 -16
  423. package/libs/PanoMeasurePlugin/utils/findAssociatedLines.d.ts +1 -1
  424. package/libs/PanoMeasurePlugin/utils/findClosestPoint.d.ts +3 -3
  425. package/libs/PanoMeasurePlugin/utils/getIntersectionFromEvent.d.ts +2 -2
  426. package/libs/PanoMeasurePlugin/utils/getPointFromHammerEvent.d.ts +1 -1
  427. package/libs/PanoMeasurePlugin/utils/isNDCPointInScreen.d.ts +1 -1
  428. package/libs/PanoMeasurePlugin/utils/line.d.ts +1 -1
  429. package/libs/PanoMeasurePlugin/utils/line.js +8 -7
  430. package/libs/PanoMeasurePlugin/utils/mouseGroup.d.ts +2 -2
  431. package/libs/PanoMeasurePlugin/utils/mouseGroup.js +5 -5
  432. package/libs/PanoRulerPlugin/Plugin.d.ts +31 -0
  433. package/libs/PanoRulerPlugin/Plugin.js +403 -0
  434. package/libs/PanoRulerPlugin/index.d.ts +4 -30
  435. package/libs/PanoRulerPlugin/index.js +2 -397
  436. package/libs/PanoSpatialTagPlugin/Components/origins.js +168 -0
  437. package/libs/PanoSpatialTagPlugin/Components/tag.js +302 -0
  438. package/libs/PanoSpatialTagPlugin/Plugin.d.ts +35 -0
  439. package/libs/PanoSpatialTagPlugin/Plugin.js +426 -0
  440. package/libs/PanoSpatialTagPlugin/index.d.ts +5 -0
  441. package/libs/PanoSpatialTagPlugin/index.js +5 -0
  442. package/libs/PanoSpatialTagPlugin/store.d.ts +1 -0
  443. package/libs/PanoSpatialTagPlugin/store.js +2 -0
  444. package/libs/PanoSpatialTagPlugin/style.d.ts +1 -0
  445. package/libs/PanoSpatialTagPlugin/style.js +8 -0
  446. package/libs/PanoSpatialTagPlugin/typings.d.ts +40 -0
  447. package/libs/PanoSpatialTagPlugin/typings.js +1 -0
  448. package/libs/base/BasePlugin.d.ts +100 -0
  449. package/libs/base/BasePlugin.js +31 -0
  450. package/libs/base/BasePluginWithData.d.ts +34 -0
  451. package/libs/base/BasePluginWithData.js +4 -0
  452. package/libs/components/PaintBrush/Controller.d.ts +43 -0
  453. package/libs/components/PaintBrush/Controller.js +575 -0
  454. package/libs/components/PaintBrush/Subscribe.d.ts +76 -0
  455. package/libs/components/PaintBrush/Subscribe.js +121 -0
  456. package/libs/components/PaintBrush/index.d.ts +27 -0
  457. package/libs/components/PaintBrush/index.js +57 -0
  458. package/libs/components/PaintBrush/style.d.ts +2 -0
  459. package/libs/components/PaintBrush/style.js +102 -0
  460. package/libs/components/PaintBrush/tween.d.ts +62 -0
  461. package/libs/components/PaintBrush/tween.js +15 -0
  462. package/libs/components/PaintBrush/typings.d.ts +58 -0
  463. package/libs/components/PaintBrush/typings.js +6 -0
  464. package/libs/components/PaintBrush/utils.d.ts +26 -0
  465. package/libs/components/PaintBrush/utils.js +51 -0
  466. package/libs/components/index.d.ts +2 -0
  467. package/libs/components/index.js +3 -0
  468. package/libs/floorplan/Assets/compass.d.ts +1 -0
  469. package/libs/floorplan/Assets/compass.js +1 -0
  470. package/libs/floorplan/Components/BaseImage.js +222 -0
  471. package/libs/floorplan/Components/Camera.js +120 -0
  472. package/libs/floorplan/Components/Compass.js +120 -0
  473. package/libs/floorplan/Components/CurrentFloor.js +469 -0
  474. package/libs/floorplan/Components/Main.js +470 -0
  475. package/libs/floorplan/Components/Normalmage.js +63 -0
  476. package/libs/floorplan/Components/RoomHighlight/Room.js +107 -0
  477. package/libs/floorplan/Components/RoomHighlight/RoomHighlight.js +216 -0
  478. package/libs/floorplan/Components/RoomLabels/RoomLabel.js +322 -0
  479. package/libs/floorplan/Components/RoomLabels/RoomLabels.js +309 -0
  480. package/libs/floorplan/Components/RoomMaterials/RoomMaterial.js +331 -0
  481. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_0.js +64 -0
  482. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_1.js +104 -0
  483. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_2.js +142 -0
  484. package/libs/floorplan/Components/RuleLabels/RuleItem.js +284 -0
  485. package/libs/floorplan/Components/RuleLabels/RuleLabels.js +269 -0
  486. package/libs/floorplan/Components/SvgImage.js +83 -0
  487. package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.js +120 -0
  488. package/libs/floorplan/ModelFloorplanPlugin/Components/Compass.js +106 -0
  489. package/libs/floorplan/ModelFloorplanPlugin/Components/CurrentFloor/CurrentFloor.js +463 -0
  490. package/libs/floorplan/ModelFloorplanPlugin/Components/Main.js +375 -0
  491. package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabel.js +171 -0
  492. package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabels.js +265 -0
  493. package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleItem.js +301 -0
  494. package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleLabels.js +219 -0
  495. package/libs/floorplan/ModelFloorplanPlugin/Controller.d.ts +70 -77
  496. package/libs/floorplan/ModelFloorplanPlugin/Controller.js +661 -326
  497. package/libs/floorplan/ModelFloorplanPlugin/index.d.ts +5 -7
  498. package/libs/floorplan/ModelFloorplanPlugin/index.js +2 -2
  499. package/libs/floorplan/ModelFloorplanPlugin/typing.d.ts +107 -0
  500. package/libs/floorplan/ModelFloorplanPlugin/typing.js +1 -0
  501. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/Camera.js +168 -0
  502. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/CurrentFloor/CurrentFloor.js +250 -0
  503. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/CurrentFloor/ExtraObjects.js +154 -0
  504. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/Main.js +373 -0
  505. package/libs/floorplan/PanoFloorplanRadarPlugin/Controller.d.ts +24 -16
  506. package/libs/floorplan/PanoFloorplanRadarPlugin/Controller.js +195 -43
  507. package/libs/floorplan/PanoFloorplanRadarPlugin/index.d.ts +5 -6
  508. package/libs/floorplan/PanoFloorplanRadarPlugin/index.js +2 -2
  509. package/libs/floorplan/PanoFloorplanRadarPlugin/typing.d.ts +52 -0
  510. package/libs/floorplan/PanoFloorplanRadarPlugin/typing.js +1 -0
  511. package/libs/floorplan/TopviewFloorplanPlugin/Controller.d.ts +53 -47
  512. package/libs/floorplan/TopviewFloorplanPlugin/Controller.js +450 -154
  513. package/libs/floorplan/TopviewFloorplanPlugin/index.d.ts +6 -4
  514. package/libs/floorplan/TopviewFloorplanPlugin/index.js +2 -2
  515. package/libs/floorplan/TopviewFloorplanPlugin/style.js +1 -1
  516. package/libs/floorplan/TopviewFloorplanPlugin/typing.d.ts +86 -0
  517. package/libs/floorplan/TopviewFloorplanPlugin/typing.js +1 -0
  518. package/libs/floorplan/index.d.ts +6 -0
  519. package/libs/floorplan/index.js +7 -0
  520. package/libs/floorplan/utils/constant.d.ts +22 -0
  521. package/libs/floorplan/utils/constant.js +23 -0
  522. package/libs/floorplan/utils/correctFiveState.d.ts +15 -0
  523. package/libs/floorplan/utils/correctFiveState.js +46 -0
  524. package/libs/floorplan/utils/formatPosition.d.ts +1 -1
  525. package/libs/floorplan/utils/formatPosition.js +3 -3
  526. package/libs/index.d.ts +15 -24
  527. package/libs/index.js +25 -14
  528. package/libs/shared-utils/Subscribe.js +8 -1
  529. package/libs/shared-utils/animationFrame/BetterTween.js +47 -18
  530. package/libs/shared-utils/createCanvasTextTexture.js +6 -5
  531. package/libs/shared-utils/five/changeMode.d.ts +4 -1
  532. package/libs/shared-utils/five/changeMode.js +34 -13
  533. package/libs/shared-utils/getPxmm.d.ts +8 -0
  534. package/libs/shared-utils/getPxmm.js +25 -20
  535. package/libs/shared-utils/index.d.ts +1 -0
  536. package/libs/shared-utils/index.js +1 -0
  537. package/libs/shared-utils/math/Interval.d.ts +13 -0
  538. package/libs/shared-utils/math/Interval.js +40 -0
  539. package/libs/shared-utils/math/Rectangle.d.ts +27 -0
  540. package/libs/shared-utils/math/Rectangle.js +50 -0
  541. package/libs/shared-utils/math/evenNumber.js +1 -1
  542. package/libs/shared-utils/math/index.d.ts +2 -0
  543. package/libs/shared-utils/math/index.js +2 -0
  544. package/libs/shared-utils/three/getExtraModelLoader.d.ts +1 -1
  545. package/libs/shared-utils/three/getNormal.d.ts +1 -1
  546. package/libs/shared-utils/three/getTextureLoader.d.ts +1 -1
  547. package/libs/shared-utils/three/loadFbxObj.d.ts +1 -1
  548. package/libs/shared-utils/three/transfromToMeshBasicMaterial.js +2 -1
  549. package/libs/shared-utils/tinyEJSrender.d.ts +5 -0
  550. package/libs/shared-utils/tinyEJSrender.js +210 -0
  551. package/libs/shared-utils/uuid.d.ts +1 -0
  552. package/libs/shared-utils/uuid.js +1 -0
  553. package/libs/shared-utils/vectorTocoordinates.d.ts +1 -1
  554. package/package.json +29 -14
  555. package/CHANGELOG.md +0 -21
  556. package/dist/dnalogel.cjs.js +0 -7
  557. package/dist/dnalogel.es.js +0 -41280
  558. package/dist/dnalogel.umd.js +0 -7
  559. package/dist/style.css +0 -1
  560. package/libs/ModelRoomLabelPlugin/RoomLabelItem.svelte +0 -63
  561. package/libs/ModelRoomLabelPlugin/RoomLabelItem.svelte.map +0 -1
  562. package/libs/ModelRoomLabelPlugin/RoomLabelItems.svelte +0 -80
  563. package/libs/ModelRoomLabelPlugin/RoomLabelItems.svelte.map +0 -1
  564. package/libs/floorplan/Components/BaseImage.svelte +0 -25
  565. package/libs/floorplan/Components/BaseImage.svelte.map +0 -1
  566. package/libs/floorplan/Components/Normalmage.svelte +0 -11
  567. package/libs/floorplan/Components/Normalmage.svelte.map +0 -1
  568. package/libs/floorplan/Components/RoomHighlight/Room.svelte +0 -21
  569. package/libs/floorplan/Components/RoomHighlight/Room.svelte.map +0 -1
  570. package/libs/floorplan/Components/RoomHighlight/RoomHighlight.svelte +0 -60
  571. package/libs/floorplan/Components/RoomHighlight/RoomHighlight.svelte.map +0 -1
  572. package/libs/floorplan/Components/RoomMaterials/RoomMaterial.svelte +0 -35
  573. package/libs/floorplan/Components/RoomMaterials/RoomMaterial.svelte.map +0 -1
  574. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_0.svelte +0 -7
  575. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_0.svelte.map +0 -1
  576. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_1.svelte +0 -16
  577. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_1.svelte.map +0 -1
  578. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_2.svelte +0 -17
  579. package/libs/floorplan/Components/RoomMaterials/RoomMaterial_2.svelte.map +0 -1
  580. package/libs/floorplan/Components/SvgImage.svelte +0 -25
  581. package/libs/floorplan/Components/SvgImage.svelte.map +0 -1
  582. package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.svelte +0 -46
  583. package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.svelte.map +0 -1
  584. package/libs/floorplan/ModelFloorplanPlugin/Components/Compass.svelte +0 -48
  585. package/libs/floorplan/ModelFloorplanPlugin/Components/Compass.svelte.map +0 -1
  586. package/libs/floorplan/ModelFloorplanPlugin/Components/CurrentFloor/CurrentFloor.svelte +0 -37
  587. package/libs/floorplan/ModelFloorplanPlugin/Components/CurrentFloor/CurrentFloor.svelte.map +0 -1
  588. package/libs/floorplan/ModelFloorplanPlugin/Components/Main.svelte +0 -50
  589. package/libs/floorplan/ModelFloorplanPlugin/Components/Main.svelte.map +0 -1
  590. package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabel.svelte +0 -41
  591. package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabel.svelte.map +0 -1
  592. package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabels.svelte +0 -25
  593. package/libs/floorplan/ModelFloorplanPlugin/Components/RoomLabels/RoomLabels.svelte.map +0 -1
  594. package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleItem.svelte +0 -148
  595. package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleItem.svelte.map +0 -1
  596. package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleLabels.svelte +0 -15
  597. package/libs/floorplan/ModelFloorplanPlugin/Components/RuleLabels/RuleLabels.svelte.map +0 -1
  598. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/Camera.svelte +0 -84
  599. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/Camera.svelte.map +0 -1
  600. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/CurrentFloor/CurrentFloor.svelte +0 -18
  601. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/CurrentFloor/CurrentFloor.svelte.map +0 -1
  602. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/CurrentFloor/ExtraObjects.svelte +0 -40
  603. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/CurrentFloor/ExtraObjects.svelte.map +0 -1
  604. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/Main.svelte +0 -61
  605. package/libs/floorplan/PanoFloorplanRadarPlugin/Components/Main.svelte.map +0 -1
@@ -0,0 +1,3996 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var Hammer = require('hammerjs');
6
+ var THREE = require('three');
7
+ var five = require('@realsee/five');
8
+ var line = require('@realsee/five/line');
9
+ var TWEEN = require('@tweenjs/tween.js');
10
+
11
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
+
13
+ function _interopNamespace(e) {
14
+ if (e && e.__esModule) return e;
15
+ var n = Object.create(null);
16
+ if (e) {
17
+ Object.keys(e).forEach(function (k) {
18
+ if (k !== 'default') {
19
+ var d = Object.getOwnPropertyDescriptor(e, k);
20
+ Object.defineProperty(n, k, d.get ? d : {
21
+ enumerable: true,
22
+ get: function () { return e[k]; }
23
+ });
24
+ }
25
+ });
26
+ }
27
+ n["default"] = e;
28
+ return Object.freeze(n);
29
+ }
30
+
31
+ var Hammer__default = /*#__PURE__*/_interopDefaultLegacy(Hammer);
32
+ var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
33
+ var TWEEN__default = /*#__PURE__*/_interopDefaultLegacy(TWEEN);
34
+
35
+ /** 交换数组元素 */
36
+ function exchange(array, index1, index2) {
37
+ const value = array[index1];
38
+ array[index1] = array[index2];
39
+ array[index2] = value;
40
+ }
41
+ /** 翻转 ArrayBuffer(RGBA像素) 的 Y 轴 */
42
+ function flipPixelsY(pixels, width, height) {
43
+ const flipYLength = height / 2;
44
+ for (let currentHeight = 1; currentHeight <= flipYLength; currentHeight++) {
45
+ const targetHeight = height - (currentHeight - 1);
46
+ for (let currentWidth = 1; currentWidth <= width; currentWidth++) {
47
+ const pixelIndex = (currentHeight - 1) * width + currentWidth - 1;
48
+ const targetPixelIndex = (targetHeight - 1) * width + currentWidth - 1;
49
+ exchange(pixels, pixelIndex * 4 + 0, targetPixelIndex * 4 + 0);
50
+ exchange(pixels, pixelIndex * 4 + 1, targetPixelIndex * 4 + 1);
51
+ exchange(pixels, pixelIndex * 4 + 2, targetPixelIndex * 4 + 2);
52
+ exchange(pixels, pixelIndex * 4 + 3, targetPixelIndex * 4 + 3);
53
+ }
54
+ }
55
+ }
56
+ class Magnifier {
57
+ constructor(five$1, options) {
58
+ var _a, _b, _c;
59
+ Object.defineProperty(this, "width", {
60
+ enumerable: true,
61
+ configurable: true,
62
+ writable: true,
63
+ value: void 0
64
+ });
65
+ Object.defineProperty(this, "height", {
66
+ enumerable: true,
67
+ configurable: true,
68
+ writable: true,
69
+ value: void 0
70
+ });
71
+ Object.defineProperty(this, "visible", {
72
+ enumerable: true,
73
+ configurable: true,
74
+ writable: true,
75
+ value: false
76
+ });
77
+ Object.defineProperty(this, "hooks", {
78
+ enumerable: true,
79
+ configurable: true,
80
+ writable: true,
81
+ value: new five.Subscribe()
82
+ });
83
+ Object.defineProperty(this, "contentDom", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: document.createElement('canvas')
88
+ });
89
+ Object.defineProperty(this, "five", {
90
+ enumerable: true,
91
+ configurable: true,
92
+ writable: true,
93
+ value: void 0
94
+ });
95
+ Object.defineProperty(this, "scale", {
96
+ enumerable: true,
97
+ configurable: true,
98
+ writable: true,
99
+ value: void 0
100
+ });
101
+ Object.defineProperty(this, "wrapper", {
102
+ enumerable: true,
103
+ configurable: true,
104
+ writable: true,
105
+ value: void 0
106
+ });
107
+ Object.defineProperty(this, "config", {
108
+ enumerable: true,
109
+ configurable: true,
110
+ writable: true,
111
+ value: void 0
112
+ });
113
+ Object.defineProperty(this, "offset", {
114
+ enumerable: true,
115
+ configurable: true,
116
+ writable: true,
117
+ value: { x: 0, y: 0 }
118
+ });
119
+ Object.defineProperty(this, "canvas", {
120
+ enumerable: true,
121
+ configurable: true,
122
+ writable: true,
123
+ value: this.contentDom
124
+ });
125
+ Object.defineProperty(this, "context", {
126
+ enumerable: true,
127
+ configurable: true,
128
+ writable: true,
129
+ value: void 0
130
+ });
131
+ Object.defineProperty(this, "renderCenter", {
132
+ enumerable: true,
133
+ configurable: true,
134
+ writable: true,
135
+ value: new THREE__namespace.Vector3()
136
+ });
137
+ Object.defineProperty(this, "lastPanEvent", {
138
+ enumerable: true,
139
+ configurable: true,
140
+ writable: true,
141
+ value: void 0
142
+ });
143
+ Object.defineProperty(this, "hammer", {
144
+ enumerable: true,
145
+ configurable: true,
146
+ writable: true,
147
+ value: void 0
148
+ });
149
+ Object.defineProperty(this, "onPan", {
150
+ enumerable: true,
151
+ configurable: true,
152
+ writable: true,
153
+ value: (event) => {
154
+ var _a, _b, _c, _d;
155
+ if (!this.wrapper)
156
+ return;
157
+ const lastDeltaX = (_b = (_a = this.lastPanEvent) === null || _a === void 0 ? void 0 : _a.deltaX) !== null && _b !== void 0 ? _b : 0;
158
+ const lastDeltaY = (_d = (_c = this.lastPanEvent) === null || _c === void 0 ? void 0 : _c.deltaY) !== null && _d !== void 0 ? _d : 0;
159
+ const deltaX = event.deltaX - lastDeltaX;
160
+ const deltaY = event.deltaY - lastDeltaY;
161
+ this.lastPanEvent = event;
162
+ const prevented = this.hooks.emit('wantsPanGesture', { srcEvent: event, deltaX, deltaY });
163
+ if (prevented)
164
+ return;
165
+ const translateX = this.offset.x + deltaX;
166
+ const translateY = this.offset.y + deltaY;
167
+ this.contentDom.style.boxShadow = '0 2px 30px 0 rgba(0,0,0,0.20)';
168
+ this.canvas.style.transform = `translate3d(${translateX}px, ${translateY}px, 100px)`;
169
+ this.offset = { x: translateX, y: translateY };
170
+ }
171
+ });
172
+ Object.defineProperty(this, "onPanEnd", {
173
+ enumerable: true,
174
+ configurable: true,
175
+ writable: true,
176
+ value: (event) => {
177
+ this.lastPanEvent = undefined;
178
+ this.contentDom.style.boxShadow = 'none';
179
+ }
180
+ });
181
+ if (!five$1.renderer)
182
+ throw new Error('Five Render 未初始化');
183
+ this.five = five$1;
184
+ this.scale = (_a = options === null || options === void 0 ? void 0 : options.scale) !== null && _a !== void 0 ? _a : 2;
185
+ this.width = (_b = options === null || options === void 0 ? void 0 : options.width) !== null && _b !== void 0 ? _b : 190;
186
+ this.height = (_c = options === null || options === void 0 ? void 0 : options.height) !== null && _c !== void 0 ? _c : 190;
187
+ this.config = {
188
+ dragEnabled: (options === null || options === void 0 ? void 0 : options.dragEnabled) || false,
189
+ autoFixPCPosition: (options === null || options === void 0 ? void 0 : options.autoFixPCPosition) || false,
190
+ initialPosition: (options === null || options === void 0 ? void 0 : options.initialPosition) || { left: '0', top: '0' },
191
+ };
192
+ const context = this.canvas.getContext('2d');
193
+ if (!context)
194
+ throw new Error('CANNOT CREATE CONTEXT2D');
195
+ this.context = context;
196
+ if (this.config.dragEnabled) {
197
+ this.hammer = new Hammer__default["default"](this.canvas);
198
+ this.hammer.on('pan', this.onPan);
199
+ this.hammer.on('panend', this.onPanEnd);
200
+ // this.hooks.on('wantsPanGesture', this.onMagnifierWantsPanGesture)
201
+ }
202
+ }
203
+ dispose() {
204
+ var _a;
205
+ this.clear();
206
+ this.remove();
207
+ (_a = this.hammer) === null || _a === void 0 ? void 0 : _a.destroy();
208
+ }
209
+ /** 移除放大镜 DOM */
210
+ remove() {
211
+ this.canvas.remove();
212
+ this.visible = false;
213
+ }
214
+ /** 清除放大镜渲染内容 */
215
+ clear() {
216
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
217
+ }
218
+ /** 把放大镜放到某一个容器中 */
219
+ appendTo(element) {
220
+ this.wrapper = element;
221
+ this.initStyle();
222
+ element.append(this.canvas);
223
+ this.visible = true;
224
+ }
225
+ /** 放大传入点位周围的内容 */
226
+ renderWithPoint(point) {
227
+ if (!this.wrapper)
228
+ return;
229
+ this.renderCenter = point;
230
+ this.render();
231
+ if (this.config.autoFixPCPosition)
232
+ this.autoFixPCPosition();
233
+ }
234
+ autoFixPCPosition() {
235
+ if (!this.wrapper)
236
+ return;
237
+ const { width, height } = this;
238
+ const position2d = this.renderCenter.clone().project(this.five.camera);
239
+ const left = ((position2d.x + 1) / 2) * this.wrapper.clientWidth;
240
+ const right = (-(position2d.x - 1) / 2) * this.wrapper.clientWidth;
241
+ const top = (-(position2d.y - 1) / 2) * this.wrapper.clientHeight;
242
+ if (left < 183) {
243
+ this.canvas.style.top = -height / 2 + 'px';
244
+ this.canvas.style.left = 90 + 'px';
245
+ }
246
+ else if (top < 183) {
247
+ this.canvas.style.top = 90 + 'px';
248
+ this.canvas.style.left = -width / 2 + 'px';
249
+ }
250
+ else if (right < 183) {
251
+ this.canvas.style.top = -height / 2 + 'px';
252
+ this.canvas.style.left = -width - 90 + 'px';
253
+ }
254
+ else {
255
+ this.canvas.style.left = -width / 2 + 'px';
256
+ this.canvas.style.top = -height - 90 + 'px';
257
+ }
258
+ this.canvas.style.transform = `translate3d(${left}px, ${top}px, 10px)`;
259
+ this.offset = { x: left, y: top };
260
+ }
261
+ render() {
262
+ if (!this.five.renderer || !this.wrapper)
263
+ return;
264
+ const { scale, context, width, height } = this;
265
+ const position2d = this.renderCenter.clone().project(this.five.camera);
266
+ const renderSize = this.five.renderer.getSize(new THREE__namespace.Vector2());
267
+ // const pixelRatio = this.five.renderer.getPixelRatio()
268
+ // 安卓机型和ios部分机型在app里读不到像素,固定为1降低清晰度可以读到
269
+ const pixelRatio = 1;
270
+ // 从 renderTarget 读取区域的大小
271
+ const readPixelsWidth = width / scale;
272
+ const readPixelsHeight = height / scale;
273
+ // 一个像素重复多少倍,pixelRatio 是兼容屏幕像素比,scale 是真实重复倍数
274
+ const readPixelsRadio = pixelRatio * scale;
275
+ const x = ((position2d.x + 1) / 2) * renderSize.x;
276
+ const y = ((position2d.y + 1) / 2) * renderSize.y;
277
+ const pixels = this.five.getPixels(x - readPixelsWidth / 2, y - readPixelsWidth / 2, readPixelsWidth, readPixelsHeight, readPixelsRadio);
278
+ // 最后生成的图像大小是 [width * pixelRatio, height * pixelRatio]
279
+ // 绘制在[width, height]的区域上
280
+ const imageWidth = Math.floor(width * pixelRatio);
281
+ const imageHeight = Math.floor(height * pixelRatio);
282
+ // 因为 Canvas 与 THREE Renderer Y 坐标相反,所以需要 Y 轴翻转
283
+ flipPixelsY(pixels, imageWidth, imageHeight);
284
+ const imageData = new ImageData(imageWidth, imageHeight);
285
+ imageData.data.set(pixels);
286
+ context.putImageData(imageData, 0, 0);
287
+ }
288
+ initStyle() {
289
+ const canvas = this.canvas;
290
+ canvas.classList.add('five-plugin__magnifier');
291
+ canvas.style.position = 'absolute';
292
+ canvas.style.pointerEvents = 'all';
293
+ canvas.style.borderRadius = '50%';
294
+ canvas.style.zIndex = '99';
295
+ const pixelRatio = 1;
296
+ canvas.setAttribute('width', (this.width * pixelRatio).toString());
297
+ canvas.setAttribute('height', (this.height * pixelRatio).toString());
298
+ canvas.style.border = '2px solid rgba(255,255,255,0.20)';
299
+ canvas.style.width = this.width + 'px';
300
+ canvas.style.height = this.height + 'px';
301
+ canvas.style.top = this.config.initialPosition.top;
302
+ canvas.style.left = this.config.initialPosition.left;
303
+ canvas.style.transform = 'translate(0,0,100px)';
304
+ if (this.config.dragEnabled) {
305
+ this.canvas.style.cursor = 'pointer';
306
+ }
307
+ }
308
+ }
309
+
310
+ class FiveHelper {
311
+ constructor(five) {
312
+ Object.defineProperty(this, "edges", {
313
+ enumerable: true,
314
+ configurable: true,
315
+ writable: true,
316
+ value: []
317
+ });
318
+ Object.defineProperty(this, "five", {
319
+ enumerable: true,
320
+ configurable: true,
321
+ writable: true,
322
+ value: void 0
323
+ });
324
+ /** 模型加载后获取折线 */
325
+ Object.defineProperty(this, "onModelLoaded", {
326
+ enumerable: true,
327
+ configurable: true,
328
+ writable: true,
329
+ value: () => {
330
+ if (!this.five.model)
331
+ return;
332
+ this.edges = this.five.model.getEdges();
333
+ }
334
+ });
335
+ this.five = five;
336
+ this.five.model.loaded ? this.onModelLoaded() : this.five.on('modelLoaded', this.onModelLoaded);
337
+ }
338
+ dispose() { }
339
+ getAdsorbentPoint(intersection) {
340
+ if (this.edges.length === 0)
341
+ return null;
342
+ let distance = Infinity;
343
+ let closestPoint;
344
+ this.edges.forEach((line) => {
345
+ const _closestPoint = line.closestPointToPoint(intersection.point, true, new THREE.Vector3());
346
+ const _distance = _closestPoint.distanceTo(intersection.point);
347
+ if (_distance < distance) {
348
+ closestPoint = _closestPoint;
349
+ distance = _distance;
350
+ }
351
+ });
352
+ if (distance > 0.1)
353
+ return null;
354
+ return closestPoint || null;
355
+ }
356
+ }
357
+
358
+ // uuid
359
+ function S4() {
360
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
361
+ }
362
+ /**
363
+ * 随机生成一个uuid值
364
+ */
365
+ function uuid() {
366
+ // then to call it, plus stitch in '4' in the third group
367
+ return (S4() + S4() + '-' + S4() + '-4' + S4().substr(0, 3) + '-' + S4() + '-' + S4() + S4() + S4()).toLowerCase();
368
+ }
369
+
370
+ class Polyline {
371
+ constructor() {
372
+ Object.defineProperty(this, "id", {
373
+ enumerable: true,
374
+ configurable: true,
375
+ writable: true,
376
+ value: uuid()
377
+ });
378
+ Object.defineProperty(this, "points", {
379
+ enumerable: true,
380
+ configurable: true,
381
+ writable: true,
382
+ value: []
383
+ });
384
+ Object.defineProperty(this, "lines", {
385
+ enumerable: true,
386
+ configurable: true,
387
+ writable: true,
388
+ value: []
389
+ });
390
+ }
391
+ push(line) {
392
+ const next = this.getNext(line);
393
+ if (!next)
394
+ throw new Error('当前线段于上一条线段无法构成折线');
395
+ this.lines.push(next.line);
396
+ this.points.push(...next.points);
397
+ return this.lines.length;
398
+ }
399
+ pop() {
400
+ const lastPoint = this.lines.pop();
401
+ const polylineLength = this.lines.length;
402
+ if (polylineLength === 0)
403
+ this.points.slice(0, this.points.length);
404
+ else
405
+ this.points.pop();
406
+ return lastPoint;
407
+ }
408
+ getNext(line) {
409
+ const lastPoint = this.points.slice(-1)[0];
410
+ if (!lastPoint)
411
+ return { line: line, points: line.points };
412
+ if (!line.points.includes(lastPoint))
413
+ return null;
414
+ const nextPoint = line.points.find((point) => point !== lastPoint);
415
+ if (!nextPoint)
416
+ return null;
417
+ return { line: line, points: [nextPoint] };
418
+ }
419
+ toJson() {
420
+ return {
421
+ id: this.id,
422
+ lines: this.lines.map((line) => line.id),
423
+ points: this.points.map((point) => point.id),
424
+ };
425
+ }
426
+ toCompletelyJson() {
427
+ return {
428
+ id: this.id,
429
+ points: this.points.map((point) => point.toJson()),
430
+ lines: this.lines.map((line) => line.toCompletelyJson()),
431
+ };
432
+ }
433
+ }
434
+
435
+ const lineWidth = 1;
436
+ const lightLineWidth = 3;
437
+ const lineColor = new THREE.Color(0xffffff);
438
+ const lightLineColor = new THREE.Color(0x6386ff);
439
+ const pointColor = new THREE.Color(0xffffff);
440
+ const lightPointColor = new THREE.Color(0x6386ff);
441
+ const pointSize = 6;
442
+ const lightPointSize = 8;
443
+ const pointImage = 'data:image/png;base64,' +
444
+ 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAIVBMVEUAAAD////////////////////////////////////////PIev5AAAACnRSTlMAG/Py2baba05un7UgfgAAAHJJREFUKM9joBpgLHVSCRdA4metAoJlCJHmVWBgAeNzroKCCVCBLpjACqgJVjCBxRBT2FbBQQJYQAohsBAsUIUQWA4WiEIILAULeCEEloAFtBACizAEMLRgGIphLabDMJ2O6TlM72MGECIIMQIZIxqoBQCPvpJ/e9FaAAAAAABJRU5ErkJggg==';
445
+ const pointTexture = new THREE.TextureLoader().load(pointImage);
446
+ const normalLineOpts = {
447
+ pointTexture,
448
+ pointSize,
449
+ lineWidth,
450
+ lineColor,
451
+ pointColor,
452
+ lineRenderOrder: 20,
453
+ pointsRenderOrder: 20,
454
+ };
455
+ Object.assign(Object.assign({}, normalLineOpts), { dashed: true });
456
+ const lightLineOpts = {
457
+ pointTexture,
458
+ pointSize: lightPointSize,
459
+ lineWidth: lightLineWidth,
460
+ lineColor: lightLineColor,
461
+ pointColor: lightPointColor,
462
+ lineRenderOrder: 10,
463
+ pointsRenderOrder: 10,
464
+ };
465
+
466
+ function creatLine(start, end, opts) {
467
+ var _a, _b, _c, _d, _e;
468
+ const lineWidth = (_a = opts === null || opts === void 0 ? void 0 : opts.lineWidth) !== null && _a !== void 0 ? _a : 2;
469
+ const lineColor = (_b = opts === null || opts === void 0 ? void 0 : opts.lineColor) !== null && _b !== void 0 ? _b : new THREE.Color(0xffffff);
470
+ const pointSize = (_c = opts === null || opts === void 0 ? void 0 : opts.pointSize) !== null && _c !== void 0 ? _c : 5;
471
+ const lineRenderOrder = (_d = opts === null || opts === void 0 ? void 0 : opts.lineRenderOrder) !== null && _d !== void 0 ? _d : 10;
472
+ const pointsRenderOrder = (_e = opts === null || opts === void 0 ? void 0 : opts.lineRenderOrder) !== null && _e !== void 0 ? _e : 20;
473
+ const line$1 = new line.Line(start, end);
474
+ // set line
475
+ line$1.setMaterial({ linewidth: lineWidth, color: lineColor });
476
+ line$1.line.material.depthTest = false;
477
+ line$1.line.material.transparent = true;
478
+ line$1.line.renderOrder = lineRenderOrder;
479
+ // set point
480
+ line$1.points.renderOrder = pointsRenderOrder;
481
+ const pointMaterial = line$1.points.material;
482
+ pointMaterial.depthTest = false;
483
+ pointMaterial.size = pointSize;
484
+ (opts === null || opts === void 0 ? void 0 : opts.pointColor) && pointMaterial.color.set(opts.pointColor).convertSRGBToLinear();
485
+ if (opts === null || opts === void 0 ? void 0 : opts.pointTexture)
486
+ pointMaterial.map = opts.pointTexture;
487
+ return line$1;
488
+ }
489
+ function creatLineMesh(line, type) {
490
+ const [point, anotherPoint] = line.points;
491
+ const opts = type === 'light' ? lightLineOpts : normalLineOpts;
492
+ const fiveLine = creatLine(point.position, anotherPoint.position, opts);
493
+ fiveLine.name = 'normalLine_' + line.id;
494
+ return fiveLine;
495
+ }
496
+
497
+ function isNDCPointInScreen(ndcPoint) {
498
+ const { x, y, z } = ndcPoint;
499
+ if (Math.abs(x) > 1 || Math.abs(y) > 1 || Math.abs(z) > 1)
500
+ return false;
501
+ return true;
502
+ }
503
+
504
+ function creatContentDom() {
505
+ const contentDom = document.createElement('div');
506
+ contentDom.setAttribute('style', `backdrop-filter: blur(4px);-webkit-backdrop-filter: blur(4px);`);
507
+ contentDom.style.padding = '3px 6px';
508
+ contentDom.style.lineHeight = '1';
509
+ contentDom.style.textAlign = 'center';
510
+ contentDom.style.transform = 'translate(-50%, -50%)';
511
+ contentDom.style.borderRadius = '100px';
512
+ contentDom.style.fontSize = '14px';
513
+ contentDom.style.color = '#fff';
514
+ contentDom.style.background = 'rgba(195,195,195,0.70)';
515
+ contentDom.style.border = '0.5px solid rgba(255,255,255,0.6)';
516
+ contentDom.style.pointerEvents = 'all';
517
+ contentDom.style.cursor = 'pointer';
518
+ return contentDom;
519
+ }
520
+ function createContainerDom(line) {
521
+ const containerDom = document.createElement('div');
522
+ containerDom.id = 'distance_' + line.id;
523
+ containerDom.classList.add('five-plugin-measure__distance');
524
+ containerDom.style.opacity = '0';
525
+ containerDom.style.position = 'absolute';
526
+ containerDom.style.left = '0';
527
+ containerDom.style.top = '0';
528
+ containerDom.style.transform = 'translate3d(0, 0, 0)';
529
+ containerDom.style.transformOrigin = 'left top';
530
+ return containerDom;
531
+ }
532
+ function creatDistanceItem(props) {
533
+ function handleClick() {
534
+ var _a;
535
+ // 线被选中时才高亮,外部手动触发高亮
536
+ // highlight()
537
+ (_a = props.clickCallback) === null || _a === void 0 ? void 0 : _a.call(props, distanceItem);
538
+ }
539
+ function highlight() {
540
+ if (userDistanceItem)
541
+ return userDistanceItem.highlight();
542
+ contentDom.style.border = '0.5px solid #95AEFF';
543
+ contentDom.style.background = 'linear-gradient(90deg, #95AEFF 0%, #6386FF 100%)';
544
+ }
545
+ function unHighlight() {
546
+ if (userDistanceItem)
547
+ return userDistanceItem.unHighlight();
548
+ contentDom.style.border = '0.5px solid rgba(255,255,255,0.6)';
549
+ contentDom.style.background = 'rgba(195,195,195,0.70)';
550
+ }
551
+ function update(five) {
552
+ const fiveElement = five.getElement();
553
+ if (!fiveElement)
554
+ return;
555
+ const screenWidth = fiveElement.clientWidth;
556
+ const screenHeight = fiveElement.clientHeight;
557
+ if (line.points.length < 2)
558
+ return;
559
+ const [startPoint, endPoint] = line.points;
560
+ const ndcStartPosition = startPoint.position.clone().project(five.camera);
561
+ const ndcEndPosition = endPoint.position.clone().project(five.camera);
562
+ const ndcDomPosition = ndcStartPosition.clone().lerp(ndcEndPosition, 0.5);
563
+ const screenStartPosition = new THREE.Vector2(ndcStartPosition.x * screenWidth, ndcStartPosition.y * screenHeight);
564
+ const screenEndPosition = new THREE.Vector2(ndcEndPosition.x * screenWidth, ndcEndPosition.y * screenHeight);
565
+ const visible = (() => {
566
+ // 对于超过近平面和远平面的点,计算会有问题
567
+ if (Math.abs(ndcStartPosition.z) > 1 || Math.abs(ndcEndPosition.z) > 1)
568
+ return false;
569
+ if (!isNDCPointInScreen(ndcStartPosition) && !isNDCPointInScreen(ndcEndPosition))
570
+ return false;
571
+ if (!isNDCPointInScreen(ndcDomPosition))
572
+ return false;
573
+ if (screenStartPosition.distanceTo(screenEndPosition) < 20)
574
+ return false;
575
+ return true;
576
+ })();
577
+ if (visible === false) {
578
+ containerDom.style.opacity = '0';
579
+ containerDom.style.pointerEvents = 'none';
580
+ return;
581
+ }
582
+ // 更新 UI
583
+ const left = ((ndcDomPosition.x + 1) / 2) * screenWidth;
584
+ const top = (-(ndcDomPosition.y - 1) / 2) * screenHeight;
585
+ const rad = Math.atan((screenStartPosition.y - screenEndPosition.y) / (screenStartPosition.x - screenEndPosition.x));
586
+ const deg = -(rad * 180) / Math.PI;
587
+ containerDom.style.transform = `translate(${left}px, ${top}px) rotate(${deg}deg)`;
588
+ containerDom.style.opacity = '1';
589
+ containerDom.style.pointerEvents = 'all';
590
+ if (userDistanceItem) {
591
+ userDistanceItem.update({ line: line.toCompletelyJson(), polyline: line.getPolyline().toCompletelyJson() });
592
+ }
593
+ const distanceString = startPoint.position.clone().distanceTo(endPoint.position).toFixed(2) + 'm';
594
+ contentDom.innerText !== distanceString && (contentDom.innerText = distanceString);
595
+ }
596
+ function appendTo(container) {
597
+ container.appendChild(containerDom);
598
+ containerDom.addEventListener('click', handleClick);
599
+ }
600
+ function remove() {
601
+ contentDom.removeEventListener('click', handleClick);
602
+ containerDom.remove();
603
+ }
604
+ const { line } = props;
605
+ const lineID = line.id;
606
+ const contentDom = creatContentDom();
607
+ const containerDom = createContainerDom(line);
608
+ const userDistanceItem = props.userDistanceItem;
609
+ const ndcPosition = new THREE.Vector3(0, 0, 0);
610
+ const distanceItem = {
611
+ lineID,
612
+ ndcPosition,
613
+ update,
614
+ appendTo,
615
+ remove,
616
+ highlight: highlight,
617
+ unHighlight: unHighlight,
618
+ };
619
+ (userDistanceItem === null || userDistanceItem === void 0 ? void 0 : userDistanceItem.element) ? containerDom.appendChild(userDistanceItem.element) : containerDom.appendChild(contentDom);
620
+ return distanceItem;
621
+ }
622
+
623
+ class Line {
624
+ constructor(point, anotherPoint, model) {
625
+ Object.defineProperty(this, "id", {
626
+ enumerable: true,
627
+ configurable: true,
628
+ writable: true,
629
+ value: void 0
630
+ });
631
+ Object.defineProperty(this, "selected", {
632
+ enumerable: true,
633
+ configurable: true,
634
+ writable: true,
635
+ value: false
636
+ });
637
+ Object.defineProperty(this, "type", {
638
+ enumerable: true,
639
+ configurable: true,
640
+ writable: true,
641
+ value: 'line'
642
+ });
643
+ Object.defineProperty(this, "model", {
644
+ enumerable: true,
645
+ configurable: true,
646
+ writable: true,
647
+ value: void 0
648
+ });
649
+ Object.defineProperty(this, "mesh", {
650
+ enumerable: true,
651
+ configurable: true,
652
+ writable: true,
653
+ value: void 0
654
+ });
655
+ Object.defineProperty(this, "points", {
656
+ enumerable: true,
657
+ configurable: true,
658
+ writable: true,
659
+ value: void 0
660
+ });
661
+ Object.defineProperty(this, "lightMesh", {
662
+ enumerable: true,
663
+ configurable: true,
664
+ writable: true,
665
+ value: void 0
666
+ });
667
+ Object.defineProperty(this, "hook", {
668
+ enumerable: true,
669
+ configurable: true,
670
+ writable: true,
671
+ value: void 0
672
+ });
673
+ Object.defineProperty(this, "distanceItem", {
674
+ enumerable: true,
675
+ configurable: true,
676
+ writable: true,
677
+ value: void 0
678
+ });
679
+ Object.defineProperty(this, "polyline", {
680
+ enumerable: true,
681
+ configurable: true,
682
+ writable: true,
683
+ value: void 0
684
+ });
685
+ this.id = uuid();
686
+ this.model = model;
687
+ if (point.id === anotherPoint.id)
688
+ throw new Error('无效的线段, 一个点无法构成线段');
689
+ this.hook = new five.Subscribe();
690
+ this.points = [point, anotherPoint];
691
+ this.mesh = creatLineMesh(this, 'normal');
692
+ this.lightMesh = creatLineMesh(this, 'light');
693
+ this.distanceItem = creatDistanceItem({
694
+ line: this,
695
+ clickCallback: () => this.hook.emit('selected', this),
696
+ userDistanceItem: this.model.params.userDistanceItemCreator
697
+ ? this.model.params.userDistanceItemCreator()
698
+ : undefined,
699
+ });
700
+ point.lines.push(this);
701
+ anotherPoint.lines.push(this);
702
+ }
703
+ clear() {
704
+ this.selected = false;
705
+ this.polyline = undefined;
706
+ }
707
+ getPolyline() {
708
+ if (this.polyline)
709
+ return this.polyline;
710
+ const modelPolyline = this.model.polylines.find((polyline) => polyline.lines.includes(this));
711
+ this.polyline = modelPolyline;
712
+ if (modelPolyline)
713
+ return modelPolyline;
714
+ const polyline = new Polyline();
715
+ polyline.push(this);
716
+ return polyline;
717
+ }
718
+ findAnotherPoint(point) {
719
+ return this.points.find(({ id }) => id !== point.id);
720
+ }
721
+ toJson() {
722
+ return { id: this.id, points: this.points.map(({ id }) => id) };
723
+ }
724
+ toCompletelyJson() {
725
+ return { id: this.id, points: this.points.map((point) => point.toJson()) };
726
+ }
727
+ clone() {
728
+ const line = new Line(this.points[0].clone(), this.points[1].clone(), this.model);
729
+ return line;
730
+ }
731
+ }
732
+
733
+ /**
734
+ * 从数组中删除
735
+ * @param item
736
+ * @param array
737
+ * @return 如果删除返回 item
738
+ */
739
+ function removeArrayItem(item, array) {
740
+ for (let index = 0, len = array.length; index < len; index++) {
741
+ if (item === array[index])
742
+ return array.splice(index, 1)[0];
743
+ }
744
+ }
745
+
746
+ class Point {
747
+ constructor(position) {
748
+ Object.defineProperty(this, "id", {
749
+ enumerable: true,
750
+ configurable: true,
751
+ writable: true,
752
+ value: void 0
753
+ });
754
+ Object.defineProperty(this, "lines", {
755
+ enumerable: true,
756
+ configurable: true,
757
+ writable: true,
758
+ value: void 0
759
+ });
760
+ Object.defineProperty(this, "position", {
761
+ enumerable: true,
762
+ configurable: true,
763
+ writable: true,
764
+ value: void 0
765
+ });
766
+ Object.defineProperty(this, "type", {
767
+ enumerable: true,
768
+ configurable: true,
769
+ writable: true,
770
+ value: 'point'
771
+ });
772
+ this.id = uuid();
773
+ this.lines = [];
774
+ this.position = new THREE.Vector3();
775
+ position instanceof THREE.Vector3 ? this.position.copy(position) : this.position.fromArray(position);
776
+ }
777
+ toJson() {
778
+ return { id: this.id, lines: this.lines.map(({ id }) => id), position: this.position.toArray() };
779
+ }
780
+ addLine(line) {
781
+ this.lines.push(line);
782
+ }
783
+ removeLine(line) {
784
+ removeArrayItem(line, this.lines);
785
+ }
786
+ clone() {
787
+ const point = new Point(this.position);
788
+ return point;
789
+ }
790
+ }
791
+
792
+ class Model {
793
+ constructor(params) {
794
+ Object.defineProperty(this, "lines", {
795
+ enumerable: true,
796
+ configurable: true,
797
+ writable: true,
798
+ value: []
799
+ });
800
+ Object.defineProperty(this, "points", {
801
+ enumerable: true,
802
+ configurable: true,
803
+ writable: true,
804
+ value: []
805
+ });
806
+ Object.defineProperty(this, "params", {
807
+ enumerable: true,
808
+ configurable: true,
809
+ writable: true,
810
+ value: void 0
811
+ });
812
+ Object.defineProperty(this, "polylines", {
813
+ enumerable: true,
814
+ configurable: true,
815
+ writable: true,
816
+ value: []
817
+ });
818
+ Object.defineProperty(this, "hook", {
819
+ enumerable: true,
820
+ configurable: true,
821
+ writable: true,
822
+ value: new five.Subscribe()
823
+ });
824
+ this.params = params;
825
+ }
826
+ addLine(line) {
827
+ const [startPoint, endPoint] = line.points;
828
+ if (!startPoint || !endPoint)
829
+ return this;
830
+ if (!this.includes(startPoint))
831
+ this.points.push(startPoint);
832
+ if (!this.includes(endPoint))
833
+ this.points.push(endPoint);
834
+ this.lines.push(line);
835
+ const lastPolyline = this.polylines.find((polyline) => !!polyline.getNext(line));
836
+ if (lastPolyline) {
837
+ lastPolyline.push(line);
838
+ }
839
+ else {
840
+ const polyline = new Polyline();
841
+ polyline.push(line);
842
+ this.polylines.push(polyline);
843
+ }
844
+ this.hook.emit('lineAdded', line);
845
+ }
846
+ removeLineByID(lineID) {
847
+ const line = this.getLineByID(lineID);
848
+ if (line)
849
+ this.removeLine(line);
850
+ }
851
+ removeLine(line) {
852
+ // handle polyline
853
+ const polyline = this.polylines.find((polyline) => polyline.lines.includes(line));
854
+ if (polyline) {
855
+ if (polyline.lines.slice(-1)[0] !== line)
856
+ throw new Error('不能从中间删除线段');
857
+ polyline.pop();
858
+ if (polyline.lines.length === 0)
859
+ removeArrayItem(polyline, this.polylines);
860
+ }
861
+ const [point, anotherPoint] = line.points;
862
+ if (point.lines.length === 0)
863
+ removeArrayItem(point, this.points);
864
+ if (anotherPoint.lines.length === 0)
865
+ removeArrayItem(anotherPoint, this.points);
866
+ removeArrayItem(line, this.lines);
867
+ line.clear();
868
+ this.hook.emit('lineRemoved', line);
869
+ return this;
870
+ }
871
+ mergeModel(model) {
872
+ model.lines.forEach((line) => this.addLine(line));
873
+ }
874
+ includes(item) {
875
+ if (item.type === 'point') {
876
+ return this.points.find(({ id }) => id === item.id) !== undefined;
877
+ }
878
+ else if (item.type === 'line') {
879
+ return this.lines.find(({ id }) => id === item.id) !== undefined;
880
+ }
881
+ }
882
+ getPointByID(id) {
883
+ return this.points.find(({ id: _id }) => _id === id);
884
+ }
885
+ getLineByID(id) {
886
+ return this.lines.find(({ id: _id }) => _id === id);
887
+ }
888
+ getClosestPoint() { }
889
+ parse(data) {
890
+ const points = data.points.map(({ id, position }) => {
891
+ const point = new Point(position);
892
+ point.id = id;
893
+ return point;
894
+ });
895
+ const lines = data.lines.map((data) => {
896
+ const [pointID, anotherPointID] = data.points;
897
+ const point = this.getPointByID.call({ points }, pointID);
898
+ const anotherPoint = this.getPointByID.call({ points }, anotherPointID);
899
+ if (!point || !anotherPoint)
900
+ throw new Error('线上的点不存在');
901
+ const line = new Line(point, anotherPoint, this);
902
+ line.id = data.id;
903
+ return line;
904
+ });
905
+ const polylines = data.polylines.map((polylineJson) => {
906
+ const polyline = new Polyline();
907
+ polylineJson.lines.forEach((lineID) => {
908
+ const line = lines.find(({ id }) => id === lineID);
909
+ line && polyline.push(line);
910
+ });
911
+ return polyline;
912
+ });
913
+ this.points.splice(0, this.points.length, ...points);
914
+ this.lines.splice(0, this.lines.length, ...lines);
915
+ this.polylines.splice(0, this.polylines.length, ...polylines);
916
+ return this;
917
+ }
918
+ toJson() {
919
+ return {
920
+ points: this.points.map((point) => point.toJson()),
921
+ lines: this.lines.map((line) => line.toJson()),
922
+ polylines: this.polylines.map((polyline) => polyline.toJson()).filter((polylines) => polylines.lines.length > 0),
923
+ };
924
+ }
925
+ }
926
+
927
+ /**
928
+ * 创建一个防抖动函数,该函数在高频调用时会每隔 wait 毫秒后调用 func 方法
929
+ * `throttle` 会在第一次调用时立刻调用一次
930
+ * @param func - 要防抖动的函数
931
+ * @param wait - 需要延迟的毫秒数
932
+ */
933
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
934
+ function throttle(func, wait = 200) {
935
+ let last;
936
+ return function (...args) {
937
+ if (last)
938
+ return;
939
+ func(...args);
940
+ last = setTimeout(function () {
941
+ last = null;
942
+ }, wait);
943
+ };
944
+ }
945
+
946
+ const preventDefault = (e) => e.preventDefault();
947
+
948
+ class BaseController {
949
+ constructor(params) {
950
+ var _a, _b;
951
+ Object.defineProperty(this, "five", {
952
+ enumerable: true,
953
+ configurable: true,
954
+ writable: true,
955
+ value: void 0
956
+ });
957
+ Object.defineProperty(this, "group", {
958
+ enumerable: true,
959
+ configurable: true,
960
+ writable: true,
961
+ value: void 0
962
+ });
963
+ Object.defineProperty(this, "model", {
964
+ enumerable: true,
965
+ configurable: true,
966
+ writable: true,
967
+ value: void 0
968
+ });
969
+ Object.defineProperty(this, "disposed", {
970
+ enumerable: true,
971
+ configurable: true,
972
+ writable: true,
973
+ value: false
974
+ });
975
+ Object.defineProperty(this, "isMobile", {
976
+ enumerable: true,
977
+ configurable: true,
978
+ writable: true,
979
+ value: void 0
980
+ });
981
+ Object.defineProperty(this, "mouseGroup", {
982
+ enumerable: true,
983
+ configurable: true,
984
+ writable: true,
985
+ value: void 0
986
+ });
987
+ Object.defineProperty(this, "container", {
988
+ enumerable: true,
989
+ configurable: true,
990
+ writable: true,
991
+ value: void 0
992
+ });
993
+ Object.defineProperty(this, "fiveHelper", {
994
+ enumerable: true,
995
+ configurable: true,
996
+ writable: true,
997
+ value: void 0
998
+ });
999
+ Object.defineProperty(this, "hook", {
1000
+ enumerable: true,
1001
+ configurable: true,
1002
+ writable: true,
1003
+ value: void 0
1004
+ });
1005
+ Object.defineProperty(this, "magnifier", {
1006
+ enumerable: true,
1007
+ configurable: true,
1008
+ writable: true,
1009
+ value: void 0
1010
+ });
1011
+ Object.defineProperty(this, "userDistanceItemCreator", {
1012
+ enumerable: true,
1013
+ configurable: true,
1014
+ writable: true,
1015
+ value: void 0
1016
+ });
1017
+ Object.defineProperty(this, "updateDistanceUI", {
1018
+ enumerable: true,
1019
+ configurable: true,
1020
+ writable: true,
1021
+ value: () => {
1022
+ this.model.lines.forEach((line) => line.distanceItem.update(this.five));
1023
+ }
1024
+ });
1025
+ // ==================== Params ====================
1026
+ this.five = params.five;
1027
+ this.hook = params.hook;
1028
+ this.model = params.model;
1029
+ this.magnifier = params.magnifier;
1030
+ this.container = params.container;
1031
+ this.fiveHelper = params.fiveHelper;
1032
+ this.isMobile = (_b = (_a = params.openParams) === null || _a === void 0 ? void 0 : _a.isMobile) !== null && _b !== void 0 ? _b : false;
1033
+ this.userDistanceItemCreator = params.userDistanceItemCreator;
1034
+ // ==================== Groups ====================
1035
+ this.group = params.group;
1036
+ this.mouseGroup = params.mouseGroup;
1037
+ const fiveElement = this.five.getElement();
1038
+ if (fiveElement) {
1039
+ fiveElement.addEventListener('touchstart', preventDefault);
1040
+ fiveElement.addEventListener('contextmenu', preventDefault);
1041
+ }
1042
+ }
1043
+ removeLine(line) {
1044
+ this.group.remove(line.mesh, line.lightMesh);
1045
+ line.distanceItem.remove();
1046
+ this.five.needsRender = true;
1047
+ }
1048
+ updateMouseGroup(intersection, mesh) {
1049
+ if (!intersection)
1050
+ return this.mouseGroup;
1051
+ // ============ update mouseGroup position ============
1052
+ const adsorbentPoint = this.fiveHelper.getAdsorbentPoint(intersection);
1053
+ const viewPosition = adsorbentPoint ? adsorbentPoint : intersection.point;
1054
+ this.mouseGroup.position.copy(viewPosition);
1055
+ // ============ update mouseGroup quaternion ============
1056
+ if (mesh) {
1057
+ this.mouseGroup.quaternion.copy(mesh.quaternion);
1058
+ }
1059
+ else if (intersection.face) {
1060
+ const normal = intersection.face.normal;
1061
+ const positionVector = normal.clone().multiplyScalar(0.05);
1062
+ const position = intersection.point.clone().add(positionVector);
1063
+ const lookAtVector = position.clone().add(positionVector);
1064
+ this.mouseGroup.lookAt(lookAtVector);
1065
+ }
1066
+ return this.mouseGroup;
1067
+ }
1068
+ dispose() {
1069
+ this.disposed = true;
1070
+ this.magnifier.remove();
1071
+ this.model.lines.forEach((line) => this.removeLine(line));
1072
+ const fiveElement = this.five.getElement();
1073
+ if (fiveElement) {
1074
+ fiveElement.removeEventListener('touchstart', preventDefault);
1075
+ fiveElement.removeEventListener('contextmenu', preventDefault);
1076
+ }
1077
+ }
1078
+ }
1079
+
1080
+ /**
1081
+ * 从 Hammer 事件中获取操作的点在交互 DOM 中的位置
1082
+ * @ignore TODO: make a suitable name
1083
+ */
1084
+ function getPointFromHammerEvent(event) {
1085
+ // clientX 与 clientY 是相对 document 的,需要转换成相对于 target 的坐标
1086
+ const { x: clientX, y: clientY } = event.center;
1087
+ const { clientWidth, clientHeight } = event.target;
1088
+ const clientRect = event.target.getBoundingClientRect();
1089
+ const position = new THREE.Vector2(clientX, clientY).sub(new THREE.Vector2(clientRect.left, clientRect.top));
1090
+ const mouse = new THREE.Vector2((position.x / clientWidth) * 2 - 1, -(position.y / clientHeight) * 2 + 1);
1091
+ return { point: position, ndcPoint: mouse };
1092
+ }
1093
+
1094
+ /** 通过鼠标事件或者触摸事件,获取当前点击屏幕关联的射线与模型的交点 */
1095
+ function getIntersectionFromEvent(five, event) {
1096
+ const mouse = getPointFromHammerEvent(event).ndcPoint;
1097
+ const raycaster = new THREE.Raycaster();
1098
+ raycaster.setFromCamera(mouse, five.camera);
1099
+ return five.model.intersectRaycaster(raycaster);
1100
+ }
1101
+
1102
+ class EditController extends BaseController {
1103
+ constructor(params) {
1104
+ var _a;
1105
+ super(params);
1106
+ Object.defineProperty(this, "type", {
1107
+ enumerable: true,
1108
+ configurable: true,
1109
+ writable: true,
1110
+ value: 'edit'
1111
+ });
1112
+ Object.defineProperty(this, "model", {
1113
+ enumerable: true,
1114
+ configurable: true,
1115
+ writable: true,
1116
+ value: new Model({ userDistanceItemCreator: this.userDistanceItemCreator })
1117
+ });
1118
+ Object.defineProperty(this, "pressPoint", {
1119
+ enumerable: true,
1120
+ configurable: true,
1121
+ writable: true,
1122
+ value: void 0
1123
+ });
1124
+ Object.defineProperty(this, "hasAppendDashed", {
1125
+ enumerable: true,
1126
+ configurable: true,
1127
+ writable: true,
1128
+ value: false
1129
+ });
1130
+ Object.defineProperty(this, "hasAppendMouseGroup", {
1131
+ enumerable: true,
1132
+ configurable: true,
1133
+ writable: true,
1134
+ value: false
1135
+ });
1136
+ Object.defineProperty(this, "fiveElement", {
1137
+ enumerable: true,
1138
+ configurable: true,
1139
+ writable: true,
1140
+ value: void 0
1141
+ });
1142
+ /** 上一个端点位置 */
1143
+ Object.defineProperty(this, "lastPoint", {
1144
+ enumerable: true,
1145
+ configurable: true,
1146
+ writable: true,
1147
+ value: null
1148
+ });
1149
+ /** 鼠标点到上一个端点连接的虚线 */
1150
+ Object.defineProperty(this, "dashed", {
1151
+ enumerable: true,
1152
+ configurable: true,
1153
+ writable: true,
1154
+ value: void 0
1155
+ });
1156
+ Object.defineProperty(this, "hammer", {
1157
+ enumerable: true,
1158
+ configurable: true,
1159
+ writable: true,
1160
+ value: void 0
1161
+ });
1162
+ /** 根据 intersection 更新放大镜和吸附点 */
1163
+ Object.defineProperty(this, "onIntersectionUpdate", {
1164
+ enumerable: true,
1165
+ configurable: true,
1166
+ writable: true,
1167
+ value: throttle((intersection, mesh) => {
1168
+ var _a;
1169
+ if (this.hasAppendMouseGroup === false) {
1170
+ this.group.add(this.mouseGroup);
1171
+ this.magnifier.appendTo(this.container);
1172
+ this.hasAppendMouseGroup = true;
1173
+ }
1174
+ const position = this.updateMouseGroup(intersection, mesh).position;
1175
+ (_a = this.pressPoint) === null || _a === void 0 ? void 0 : _a.position.copy(position);
1176
+ this.updateDashed();
1177
+ requestAnimationFrame(() => this.magnifier.renderWithPoint(this.mouseGroup.position));
1178
+ this.five.needsRender = true;
1179
+ }, 20)
1180
+ });
1181
+ /** 撤销编辑 */
1182
+ Object.defineProperty(this, "revoke", {
1183
+ enumerable: true,
1184
+ configurable: true,
1185
+ writable: true,
1186
+ value: () => {
1187
+ // ============ revoke points ============
1188
+ // 如果当前没有虚线,只有起始点,需要删除起始点,重置起始状态。并删除虚线实例
1189
+ if (this.model.lines.length === 0 && this.lastPoint) {
1190
+ this.lastPoint = null;
1191
+ this.hasAppendDashed = false;
1192
+ this.dashed.distanceItem.remove();
1193
+ this.group.remove(this.dashed.mesh);
1194
+ this.hook.emit('anchorChange', null);
1195
+ this.five.needsRender = true;
1196
+ return;
1197
+ }
1198
+ if (this.model.lines.length === 0 && !this.lastPoint)
1199
+ return;
1200
+ if (!this.lastPoint)
1201
+ return;
1202
+ const revokedLine = this.model.lines[this.model.lines.length - 1];
1203
+ const lastPoint = revokedLine.findAnotherPoint(this.lastPoint);
1204
+ if (!lastPoint)
1205
+ return;
1206
+ this.lastPoint = lastPoint;
1207
+ this.hook.emit('anchorChange', lastPoint.position);
1208
+ // ============ revoke lines ============
1209
+ this.group.remove(revokedLine.mesh);
1210
+ this.model.removeLine(revokedLine);
1211
+ // ============ revoke mouse group ============
1212
+ this.hasAppendMouseGroup = false;
1213
+ this.mouseGroup.position.copy(this.lastPoint.position);
1214
+ this.group.remove(this.mouseGroup);
1215
+ // ============ revoke lineDistance ============
1216
+ revokedLine.distanceItem.remove();
1217
+ // ============ revoke dashed ============
1218
+ this.updateDashed();
1219
+ // ============ revoke magnifier ============
1220
+ this.magnifier.remove();
1221
+ this.five.needsRender = true;
1222
+ }
1223
+ });
1224
+ Object.defineProperty(this, "onMouseLeave", {
1225
+ enumerable: true,
1226
+ configurable: true,
1227
+ writable: true,
1228
+ value: () => {
1229
+ this.magnifier.remove();
1230
+ this.group.remove(this.mouseGroup);
1231
+ this.hasAppendMouseGroup = false;
1232
+ if (this.lastPoint) {
1233
+ this.mouseGroup.position.copy(this.lastPoint.position);
1234
+ this.updateDashed();
1235
+ }
1236
+ }
1237
+ });
1238
+ /** 编辑线条发生改变时通知外部 */
1239
+ Object.defineProperty(this, "onLineChanged", {
1240
+ enumerable: true,
1241
+ configurable: true,
1242
+ writable: true,
1243
+ value: () => {
1244
+ this.hook.emit('editedLineChange', this.model.lines.map((line) => line.toCompletelyJson()));
1245
+ }
1246
+ });
1247
+ Object.defineProperty(this, "onPress", {
1248
+ enumerable: true,
1249
+ configurable: true,
1250
+ writable: true,
1251
+ value: (e) => {
1252
+ const [intersection] = getIntersectionFromEvent(this.five, e);
1253
+ if (!intersection || !intersection.face)
1254
+ return;
1255
+ const nowPoint = new Point(intersection.point);
1256
+ this.pressPoint = nowPoint;
1257
+ this.onIntersectionUpdate(intersection);
1258
+ }
1259
+ });
1260
+ /**
1261
+ * 1. 如果之前没有长按行为「即没有长按点时」-> 滑动全景
1262
+ * 2. 如果有长按点,把长按点位置更新为当前位置
1263
+ */
1264
+ Object.defineProperty(this, "onPan", {
1265
+ enumerable: true,
1266
+ configurable: true,
1267
+ writable: true,
1268
+ value: (e) => {
1269
+ if (!this.pressPoint)
1270
+ return;
1271
+ const [intersection] = getIntersectionFromEvent(this.five, e);
1272
+ if (!intersection || !intersection.face)
1273
+ return;
1274
+ this.onIntersectionUpdate(intersection);
1275
+ }
1276
+ });
1277
+ Object.defineProperty(this, "onPanEnd", {
1278
+ enumerable: true,
1279
+ configurable: true,
1280
+ writable: true,
1281
+ value: (e) => {
1282
+ if (!this.pressPoint)
1283
+ return;
1284
+ this.onTap(e);
1285
+ }
1286
+ });
1287
+ /**
1288
+ * 1. 如果存在上一个点,需要绘制当前点到上一个点的连线
1289
+ * 2. 把上一个点的位置更新为当前点的位置
1290
+ * 3. 清除 mouseGroup 和 magnifier
1291
+ */
1292
+ Object.defineProperty(this, "onTap", {
1293
+ enumerable: true,
1294
+ configurable: true,
1295
+ writable: true,
1296
+ value: (e) => {
1297
+ if (!this.hasAppendDashed) {
1298
+ this.dashed.distanceItem.appendTo(this.container);
1299
+ this.group.add(this.dashed.mesh);
1300
+ }
1301
+ this.hasAppendDashed = true;
1302
+ const [intersection] = getIntersectionFromEvent(this.five, e);
1303
+ this.updateMouseGroup(intersection);
1304
+ const nowPoint = new Point(this.mouseGroup.position);
1305
+ const lastPoint = this.lastPoint;
1306
+ if (nowPoint)
1307
+ this.lastPoint = nowPoint;
1308
+ if (nowPoint && lastPoint) {
1309
+ const line = new Line(lastPoint, nowPoint, this.model);
1310
+ line.distanceItem.appendTo(this.container);
1311
+ this.model.addLine(line);
1312
+ this.group.add(line.mesh);
1313
+ line.distanceItem.update(this.five);
1314
+ }
1315
+ this.pressPoint = undefined;
1316
+ this.hasAppendMouseGroup = false;
1317
+ this.magnifier.remove();
1318
+ this.group.remove(this.mouseGroup);
1319
+ this.updateDashed();
1320
+ this.five.needsRender = true;
1321
+ this.hook.emit('anchorChange', nowPoint.position);
1322
+ }
1323
+ });
1324
+ Object.defineProperty(this, "onWantsTapGesture", {
1325
+ enumerable: true,
1326
+ configurable: true,
1327
+ writable: true,
1328
+ value: () => false
1329
+ });
1330
+ /** 编辑时取消走点 */
1331
+ Object.defineProperty(this, "onWantsToMoveToPano", {
1332
+ enumerable: true,
1333
+ configurable: true,
1334
+ writable: true,
1335
+ value: () => false
1336
+ });
1337
+ /** 存在长按点时不能移动全景 */
1338
+ Object.defineProperty(this, "onWantsPanGesture", {
1339
+ enumerable: true,
1340
+ configurable: true,
1341
+ writable: true,
1342
+ value: () => (this.pressPoint ? false : undefined)
1343
+ });
1344
+ /** 移动全景时更新 distanceItem 在屏幕上的位置 */
1345
+ Object.defineProperty(this, "onCameraUpdate", {
1346
+ enumerable: true,
1347
+ configurable: true,
1348
+ writable: true,
1349
+ value: () => {
1350
+ this.updateDistanceUI();
1351
+ this.dashed.distanceItem.update(this.five);
1352
+ }
1353
+ });
1354
+ /** 更新虚线 */
1355
+ Object.defineProperty(this, "updateDashed", {
1356
+ enumerable: true,
1357
+ configurable: true,
1358
+ writable: true,
1359
+ value: () => {
1360
+ if (!this.lastPoint)
1361
+ return;
1362
+ this.dashed.points[0].position.copy(this.lastPoint.position);
1363
+ this.dashed.points[1].position.copy(this.mouseGroup.position);
1364
+ this.dashed.mesh.setPoints(this.lastPoint.position, this.mouseGroup.position);
1365
+ this.dashed.distanceItem.update(this.five);
1366
+ }
1367
+ });
1368
+ // ==================== 虚线 ====================
1369
+ this.dashed = new Line(new Point([0, 0, 0]), new Point([0, 0, 0]), this.model);
1370
+ this.dashed.mesh.setMaterial({ dashed: true, dashScale: 100 });
1371
+ // ==================== 事件监听 ====================
1372
+ // five
1373
+ this.five.on('cameraUpdate', this.onCameraUpdate);
1374
+ this.five.on('wantsPanGesture', this.onWantsPanGesture);
1375
+ this.five.on('wantsTapGesture', this.onWantsTapGesture);
1376
+ this.five.on('wantsToMoveToPano', this.onWantsToMoveToPano);
1377
+ this.five.on('intersectionOnModelUpdate', this.onIntersectionUpdate);
1378
+ // model
1379
+ this.model.hook.on('lineAdded', this.onLineChanged);
1380
+ this.model.hook.on('lineRemoved', this.onLineChanged);
1381
+ // hammer
1382
+ const fiveElement = this.five.getElement();
1383
+ if (fiveElement) {
1384
+ this.fiveElement = fiveElement;
1385
+ const hammer = new Hammer__default["default"](fiveElement);
1386
+ this.hammer = hammer;
1387
+ hammer.on('tap', this.onTap);
1388
+ hammer.on('pan', this.onPan);
1389
+ hammer.on('press', this.onPress);
1390
+ hammer.on('panend', this.onPanEnd);
1391
+ }
1392
+ // fiveElement
1393
+ (_a = this.fiveElement) === null || _a === void 0 ? void 0 : _a.addEventListener('mouseleave', this.onMouseLeave);
1394
+ // ==================== 其他 ====================
1395
+ this.hook.emit('anchorChange', null);
1396
+ this.five.refresh();
1397
+ }
1398
+ dispose() {
1399
+ var _a, _b;
1400
+ super.dispose();
1401
+ this.group.remove(this.mouseGroup, this.dashed.mesh);
1402
+ // ==================== 解除事件监听 ====================
1403
+ // five
1404
+ this.five.off('cameraUpdate', this.onCameraUpdate);
1405
+ this.five.off('wantsPanGesture', this.onWantsPanGesture);
1406
+ this.five.off('wantsTapGesture', this.onWantsTapGesture);
1407
+ this.five.off('wantsToMoveToPano', this.onWantsToMoveToPano);
1408
+ this.five.off('intersectionOnModelUpdate', this.onIntersectionUpdate);
1409
+ // model
1410
+ this.model.hook.off('lineAdded', this.onLineChanged);
1411
+ this.model.hook.off('lineRemoved', this.onLineChanged);
1412
+ // hammer
1413
+ (_a = this.hammer) === null || _a === void 0 ? void 0 : _a.destroy();
1414
+ // fiveElement
1415
+ (_b = this.fiveElement) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseleave', this.onMouseLeave);
1416
+ this.magnifier.dispose();
1417
+ this.dashed.distanceItem.remove();
1418
+ this.five.needsRender = true;
1419
+ }
1420
+ getEditingLines() {
1421
+ return this.model.lines;
1422
+ }
1423
+ }
1424
+
1425
+ const svg = `
1426
+ <svg class="fpm__delete-icon" width="16px" height="17px" viewBox="0 0 16 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
1427
+ <defs>
1428
+ <linearGradient x1="22.185491%" y1="100%" x2="66.8316686%" y2="6.67239121%" id="linearGradient-1">
1429
+ <stop stop-color="#FFFCFC" stop-opacity="0.6" offset="0%"></stop>
1430
+ <stop stop-color="#FFFFFF" offset="100%"></stop>
1431
+ </linearGradient>
1432
+ </defs>
1433
+ <path fill="url(#linearGradient-1)" fill-rule="nonzero" transform="translate(2.16 2.16)" d="M11.2979686,2.71818182 C11.611378,2.71818182 11.8654465,2.97561809 11.8654465,3.29318182 C11.8654465,3.58428191 11.6519584,3.82485822 11.374972,3.86293275 L11.2979686,3.86818182 L10.464,3.868 L9.7236795,10.6246222 C9.64153248,11.3737453 9.04854423,11.9512142 8.32013277,12.0165596 L8.18206028,12.0227273 L3.68338622,12.0227273 C2.89302127,12.0227273 2.22904821,11.4205655 2.141767,10.6246222 L2.141767,10.6246222 L1.4,3.868 L0.567477876,3.86818182 C0.254068499,3.86818182 0,3.61074555 0,3.29318182 C0,3.00208173 0.213488114,2.76150541 0.49047449,2.72343089 L0.567477876,2.71818182 L11.2979686,2.71818182 Z M9.322,3.868 L2.542,3.868 L3.26978106,10.4976259 C3.28762252,10.6603274 3.39528004,10.7928487 3.53932022,10.8467307 L3.61412483,10.866894 L3.68338622,10.8727273 L8.18206028,10.8727273 C8.39410941,10.8727273 8.57224853,10.7111717 8.59566544,10.4976259 L8.59566544,10.4976259 L9.322,3.868 Z M8.16824216,0 C8.48165153,0 8.73572003,0.257436269 8.73572003,0.575 C8.73572003,0.866100087 8.52223192,1.1066764 8.24524554,1.14475093 L8.16824216,1.15 L3.69720434,1.15 C3.38379497,1.15 3.12972647,0.892563731 3.12972647,0.575 C3.12972647,0.283899913 3.34321458,0.0433235966 3.62020096,0.00524907226 L3.69720434,0 L8.16824216,0 Z"></path>
1434
+ </svg>
1435
+ `;
1436
+
1437
+ const image$1 = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTciIGhlaWdodD0iMjUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IHgxPSIxMC43MDYlIiB5MT0iNDIuNzQ0JSIgeDI9Ijg5LjA2NCUiIHkyPSI1Ny4yMDglIiBpZD0icHJlZml4X19hIj48c3RvcCBzdG9wLWNvbG9yPSIjRkZGIiBzdG9wLW9wYWNpdHk9IjAiIG9mZnNldD0iMCUiLz48c3RvcCBzdG9wLWNvbG9yPSIjRkZGIiBzdG9wLW9wYWNpdHk9Ii4zMDgiIG9mZnNldD0iNDkuNTY5JSIvPjxzdG9wIHN0b3AtY29sb3I9IiNGRkYiIHN0b3Atb3BhY2l0eT0iMCIgb2Zmc2V0PSIxMDAlIi8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iLS4yNSIgeT0iLS4yNSIgd2lkdGg9IjU3LjUiIGhlaWdodD0iMjMuNSIgcng9IjExLjI1IiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDEpIiBmaWxsPSIjMkMyQzJDIiBzdHJva2U9InVybCgjcHJlZml4X19hKSIgc3Ryb2tlLXdpZHRoPSIuNSIgZmlsbC1ydWxlPSJldmVub2RkIiBmaWxsLW9wYWNpdHk9Ii4zMDMiLz48L3N2Zz4=`;
1438
+
1439
+ const image = `data:image/png;base64,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`;
1440
+
1441
+ class DeleteDom {
1442
+ constructor(five, opts) {
1443
+ Object.defineProperty(this, "visible", {
1444
+ enumerable: true,
1445
+ configurable: true,
1446
+ writable: true,
1447
+ value: false
1448
+ });
1449
+ Object.defineProperty(this, "five", {
1450
+ enumerable: true,
1451
+ configurable: true,
1452
+ writable: true,
1453
+ value: void 0
1454
+ });
1455
+ Object.defineProperty(this, "lines", {
1456
+ enumerable: true,
1457
+ configurable: true,
1458
+ writable: true,
1459
+ value: []
1460
+ });
1461
+ Object.defineProperty(this, "points", {
1462
+ enumerable: true,
1463
+ configurable: true,
1464
+ writable: true,
1465
+ value: []
1466
+ });
1467
+ Object.defineProperty(this, "onClick", {
1468
+ enumerable: true,
1469
+ configurable: true,
1470
+ writable: true,
1471
+ value: void 0
1472
+ });
1473
+ Object.defineProperty(this, "cancelDelete", {
1474
+ enumerable: true,
1475
+ configurable: true,
1476
+ writable: true,
1477
+ value: void 0
1478
+ });
1479
+ Object.defineProperty(this, "content", {
1480
+ enumerable: true,
1481
+ configurable: true,
1482
+ writable: true,
1483
+ value: document.createElement('div')
1484
+ });
1485
+ Object.defineProperty(this, "container", {
1486
+ enumerable: true,
1487
+ configurable: true,
1488
+ writable: true,
1489
+ value: document.createElement('div')
1490
+ });
1491
+ Object.defineProperty(this, "masking", {
1492
+ enumerable: true,
1493
+ configurable: true,
1494
+ writable: true,
1495
+ value: document.createElement('div')
1496
+ });
1497
+ Object.defineProperty(this, "onMouseEnter", {
1498
+ enumerable: true,
1499
+ configurable: true,
1500
+ writable: true,
1501
+ value: () => {
1502
+ this.content.style.backgroundImage = `url(${image})`;
1503
+ }
1504
+ });
1505
+ Object.defineProperty(this, "onMouseLeave", {
1506
+ enumerable: true,
1507
+ configurable: true,
1508
+ writable: true,
1509
+ value: () => {
1510
+ this.content.style.backgroundImage = `url(${image$1})`;
1511
+ }
1512
+ });
1513
+ this.five = five;
1514
+ this.onClick = (opts === null || opts === void 0 ? void 0 : opts.onClick) || (() => void 0);
1515
+ this.cancelDelete = (opts === null || opts === void 0 ? void 0 : opts.cancelDelete) || (() => void 0);
1516
+ // container
1517
+ this.container.classList.add('fpm__delete');
1518
+ this.container.style.opacity = '0';
1519
+ this.container.style.position = 'absolute';
1520
+ this.container.style.left = '0';
1521
+ this.container.style.top = '10px';
1522
+ this.container.style.transform = `translate3d(0, 0, 10px)`;
1523
+ this.container.style.pointerEvents = `none`;
1524
+ this.container.style.transition = 'top 200ms ease, opacity 200ms ease';
1525
+ this.container.style.zIndex = '99';
1526
+ // content
1527
+ this.content.classList.add('fpm__delete-content');
1528
+ this.content.style.width = '62px';
1529
+ this.content.style.height = '26px';
1530
+ this.content.style.display = 'flex';
1531
+ this.content.style.alignItems = 'center';
1532
+ this.content.style.justifyContent = 'center';
1533
+ this.content.style.transform = 'translate(-50%, -50%)';
1534
+ this.content.style.color = '#fff';
1535
+ this.content.style.fontSize = '12px';
1536
+ this.content.style.lineHeight = '17px';
1537
+ this.content.style.borderRadius = '11px';
1538
+ this.content.style.backgroundSize = '100% 100%';
1539
+ this.content.style.cursor = 'pointer';
1540
+ this.content.style.userSelect = 'none';
1541
+ this.content.style.backgroundImage = `url(${image$1})`;
1542
+ this.content.innerHTML = `
1543
+ ${svg}
1544
+ <span>删除</span>
1545
+ `;
1546
+ this.container.append(this.content);
1547
+ const deleteSvgDom = this.content.querySelector('.fpm__delete-icon');
1548
+ if (deleteSvgDom) {
1549
+ deleteSvgDom.style.width = '16px';
1550
+ deleteSvgDom.style.height = '17px';
1551
+ deleteSvgDom.style.marginRight = '1px';
1552
+ }
1553
+ this.content.addEventListener('click', this.onClick);
1554
+ this.content.addEventListener('mouseenter', this.onMouseEnter);
1555
+ this.content.addEventListener('mouseleave', this.onMouseLeave);
1556
+ // masking
1557
+ this.masking.setAttribute('style', 'position: absolute;top: 0;left: 0;bottom: 0;right: 0;pointer-events: none;');
1558
+ this.masking.addEventListener('click', this.cancelDelete);
1559
+ this.masking.addEventListener('touchstart', this.cancelDelete);
1560
+ }
1561
+ dispose() {
1562
+ this.content.removeEventListener('click', this.onClick);
1563
+ this.content.removeEventListener('mouseenter', this.onMouseEnter);
1564
+ this.content.removeEventListener('mouseleave', this.onMouseLeave);
1565
+ this.container.remove();
1566
+ this.masking.removeEventListener('click', this.cancelDelete);
1567
+ this.masking.removeEventListener('touchstart', this.cancelDelete);
1568
+ this.masking.remove();
1569
+ }
1570
+ appendTo(element) {
1571
+ element.append(this.container);
1572
+ element.append(this.masking);
1573
+ return this;
1574
+ }
1575
+ setLines(lines) {
1576
+ this.lines = lines;
1577
+ this.points = Array.from(new Set(this.lines.map((line) => [line.points[0], line.points[1]]).flat(1)));
1578
+ return this;
1579
+ }
1580
+ updatePosition() {
1581
+ if (this.lines.length === 0)
1582
+ return this;
1583
+ const points = this.points.map((point) => point.position);
1584
+ const ndcPoints = points.map((point) => point.clone().project(this.five.camera));
1585
+ if (ndcPoints.some((ndcPoint) => Math.abs(ndcPoint.z) > 1))
1586
+ return this.hide();
1587
+ const xArray = ndcPoints.map((point) => point.x);
1588
+ const yArray = ndcPoints.map((point) => point.y);
1589
+ const centerX = (Math.min(...xArray) + Math.max(...xArray)) / 2;
1590
+ const maxY = Math.max(...yArray);
1591
+ const wrapper = this.container.parentElement;
1592
+ if (!wrapper)
1593
+ return this;
1594
+ const centerScreenX = ((centerX + 1) / 2) * wrapper.clientWidth;
1595
+ const maxScreenY = (-(maxY - 1) / 2) * wrapper.clientHeight;
1596
+ let x = centerScreenX;
1597
+ let y = maxScreenY - 34;
1598
+ // 只有一条线时且斜率大时删除按钮位于右侧
1599
+ if (this.lines.length === 1 && points.length === 2) {
1600
+ const k = (yArray[1] - yArray[0]) / (xArray[1] - xArray[0]);
1601
+ const centerY = (yArray[1] + yArray[0]) / 2;
1602
+ const centerScreenY = (-(centerY - 1) / 2) * wrapper.clientHeight;
1603
+ if (Math.abs(k) > 0.4) {
1604
+ x = centerScreenX + 57;
1605
+ y = centerScreenY;
1606
+ }
1607
+ }
1608
+ this.container.style.transform = `translate3d(${x}px, ${y}px, 10px)`;
1609
+ return this.show();
1610
+ }
1611
+ hide() {
1612
+ this.visible = false;
1613
+ this.masking.style.pointerEvents = 'none';
1614
+ this.container.style.opacity = '0';
1615
+ this.container.style.top = '10px';
1616
+ this.container.style.pointerEvents = 'none';
1617
+ return this;
1618
+ }
1619
+ show() {
1620
+ this.visible = true;
1621
+ this.masking.style.pointerEvents = 'auto';
1622
+ this.container.style.opacity = '1';
1623
+ this.container.style.top = '0';
1624
+ this.container.style.pointerEvents = 'auto';
1625
+ return this;
1626
+ }
1627
+ }
1628
+
1629
+ /**
1630
+ * 获取一点对于线段上最近的一点,
1631
+ * 如果可以是过直线垂线的垂足,不行的话取线段的两端
1632
+ * @param point
1633
+ * @param linePoints
1634
+ * @return
1635
+ */
1636
+ function closestPointOnLine(point, linePoints) {
1637
+ const tA = point.x - linePoints[0].x;
1638
+ const tB = point.y - linePoints[0].y;
1639
+ const tC = linePoints[1].x - linePoints[0].x;
1640
+ const tD = linePoints[1].y - linePoints[0].y;
1641
+ // 设线段为 AB 线段,线段外一点为 P
1642
+ // tDot = AP 向量与 AB 向量乘积,tLenSq 为 |AB|平方。
1643
+ // tParam 是 AP 向量在 AB 向量投影向量 AC 与 AB 向量的比。
1644
+ const tDot = tA * tC + tB * tD;
1645
+ const tLenSq = tC * tC + tD * tD;
1646
+ const tParam = tDot / tLenSq;
1647
+ let tXx, tYy;
1648
+ if (tParam < 0 || samePointAt(linePoints[0], linePoints[1])) {
1649
+ tXx = linePoints[0].x;
1650
+ tYy = linePoints[0].y;
1651
+ }
1652
+ else if (tParam > 1) {
1653
+ tXx = linePoints[1].x;
1654
+ tYy = linePoints[1].y;
1655
+ }
1656
+ else {
1657
+ tXx = linePoints[0].x + tParam * tC;
1658
+ tYy = linePoints[0].y + tParam * tD;
1659
+ }
1660
+ return new THREE.Vector2(tXx, tYy);
1661
+ }
1662
+ /**
1663
+ * 检查两个点是否位置相同
1664
+ * point: { x: number, y: number }
1665
+ * @param point1
1666
+ * @param point2
1667
+ * @return
1668
+ */
1669
+ function samePointAt(point1, point2) {
1670
+ return point1.x === point2.x && point1.y === point2.y;
1671
+ }
1672
+
1673
+ function ndc2Screen(ndcPosition, containerSize) {
1674
+ const left = ((ndcPosition.x + 1) / 2) * containerSize.width;
1675
+ const top = (-(ndcPosition.y - 1) / 2) * containerSize.height;
1676
+ return new THREE.Vector2(left, top);
1677
+ }
1678
+
1679
+ /**
1680
+ * @param tapPoint 注意这里的坐标是相对于 FiveElement 的
1681
+ */
1682
+ // eslint-disable-next-line max-params
1683
+ function findClosestPoint(five, points, tapPoint, maxDistance) {
1684
+ const container = five.getElement();
1685
+ if (!container)
1686
+ return null;
1687
+ if (points.length === 0)
1688
+ return null;
1689
+ const containerSize = { width: container.clientWidth, height: container.clientHeight };
1690
+ const ndcPoints = points
1691
+ .map((point) => {
1692
+ const ndcPosition = point.position.clone().project(five.camera);
1693
+ if (!isNDCPointInScreen(ndcPosition))
1694
+ return { distance: Infinity, point };
1695
+ const screenPosition = ndc2Screen(ndcPosition, containerSize);
1696
+ const distance = screenPosition.distanceTo(tapPoint);
1697
+ return { distance, point };
1698
+ })
1699
+ .sort((a, b) => a.distance - b.distance);
1700
+ if (typeof maxDistance === 'number' && ndcPoints[0].distance > maxDistance)
1701
+ return null;
1702
+ return ndcPoints[0];
1703
+ }
1704
+
1705
+ function findAssociatedLines(line) {
1706
+ // 找跟这个线段相邻的线
1707
+ const mergeNextLine = (point, nextIndex, target) => {
1708
+ const nextLine = point.lines.find((line) => {
1709
+ const pointIndex = line.points.findIndex(({ id }) => id === point.id);
1710
+ if (pointIndex === nextIndex)
1711
+ return false;
1712
+ return true;
1713
+ });
1714
+ if (!nextLine)
1715
+ return target;
1716
+ const nextPoint = nextLine.points[nextIndex];
1717
+ if (!nextPoint)
1718
+ return target;
1719
+ return mergeNextLine(nextPoint, nextIndex, target.concat(nextLine));
1720
+ };
1721
+ const rightLines = mergeNextLine(line.points[0], 1, []);
1722
+ const leftLines = mergeNextLine(line.points[0], 0, []);
1723
+ const lines = rightLines.concat(leftLines);
1724
+ return lines;
1725
+ }
1726
+
1727
+ class WatchController extends BaseController {
1728
+ constructor(params) {
1729
+ super(params);
1730
+ Object.defineProperty(this, "type", {
1731
+ enumerable: true,
1732
+ configurable: true,
1733
+ writable: true,
1734
+ value: 'watch'
1735
+ });
1736
+ Object.defineProperty(this, "deleteDom", {
1737
+ enumerable: true,
1738
+ configurable: true,
1739
+ writable: true,
1740
+ value: void 0
1741
+ });
1742
+ Object.defineProperty(this, "highlightedLines", {
1743
+ enumerable: true,
1744
+ configurable: true,
1745
+ writable: true,
1746
+ value: []
1747
+ });
1748
+ Object.defineProperty(this, "fiveElement", {
1749
+ enumerable: true,
1750
+ configurable: true,
1751
+ writable: true,
1752
+ value: void 0
1753
+ });
1754
+ Object.defineProperty(this, "editPointState", {
1755
+ enumerable: true,
1756
+ configurable: true,
1757
+ writable: true,
1758
+ value: void 0
1759
+ });
1760
+ Object.defineProperty(this, "hammer", {
1761
+ enumerable: true,
1762
+ configurable: true,
1763
+ writable: true,
1764
+ value: void 0
1765
+ });
1766
+ Object.defineProperty(this, "onPanStart", {
1767
+ enumerable: true,
1768
+ configurable: true,
1769
+ writable: true,
1770
+ value: (e) => {
1771
+ var _a;
1772
+ if (this.model.points.length === 0 || !this.fiveElement)
1773
+ return;
1774
+ const mouse = getPointFromHammerEvent(e).point;
1775
+ const closestPoint = (_a = findClosestPoint(this.five, this.model.points, mouse, 20)) === null || _a === void 0 ? void 0 : _a.point;
1776
+ if (!closestPoint) {
1777
+ this.editPointState = undefined;
1778
+ return;
1779
+ }
1780
+ const editPointState = {
1781
+ point: closestPoint,
1782
+ associatedLines: findAssociatedLines(closestPoint.lines[0]),
1783
+ };
1784
+ const cancelDragLine = this.hook.emit('wantsDragLine', {
1785
+ point: closestPoint.id,
1786
+ lines: editPointState.associatedLines.map(({ id }) => id),
1787
+ });
1788
+ if (cancelDragLine)
1789
+ return;
1790
+ this.editPointState = editPointState;
1791
+ this.magnifier.appendTo(this.container);
1792
+ this.group.add(this.mouseGroup);
1793
+ }
1794
+ });
1795
+ Object.defineProperty(this, "onPanEnd", {
1796
+ enumerable: true,
1797
+ configurable: true,
1798
+ writable: true,
1799
+ value: () => {
1800
+ if (!this.editPointState)
1801
+ return;
1802
+ // 把拖动的线从虚线转换为实线
1803
+ this.editPointState.point.lines.forEach((line) => line.mesh.setMaterial({ dashed: false }));
1804
+ // 还原选中态
1805
+ this.highlightLines(this.editPointState.associatedLines);
1806
+ this.editPointState = undefined;
1807
+ this.magnifier.remove();
1808
+ this.group.remove(this.mouseGroup);
1809
+ }
1810
+ });
1811
+ Object.defineProperty(this, "onPan", {
1812
+ enumerable: true,
1813
+ configurable: true,
1814
+ writable: true,
1815
+ value: (e) => {
1816
+ if (!this.editPointState || !this.fiveElement)
1817
+ return;
1818
+ const mouse = getPointFromHammerEvent(e).ndcPoint;
1819
+ const raycaster = new THREE.Raycaster();
1820
+ raycaster.setFromCamera(mouse, this.five.camera);
1821
+ const [intersection] = this.five.model.intersectRaycaster(raycaster);
1822
+ if (!intersection)
1823
+ return;
1824
+ this.onIntersectionUpdate(intersection);
1825
+ }
1826
+ });
1827
+ Object.defineProperty(this, "onIntersectionUpdate", {
1828
+ enumerable: true,
1829
+ configurable: true,
1830
+ writable: true,
1831
+ value: (intersection, mesh) => {
1832
+ if (!this.editPointState)
1833
+ return;
1834
+ // 拖动过程中清除选中态
1835
+ this.clearHighlightLines();
1836
+ // 把拖动点相关的线变成虚线 & 改变相关线的位置
1837
+ this.editPointState.point.position.copy(intersection.point);
1838
+ this.editPointState.point.lines.forEach((line) => {
1839
+ line.mesh.setPoints(line.points[0].position.clone(), line.points[1].position.clone());
1840
+ line.lightMesh.setPoints(line.points[0].position.clone(), line.points[1].position.clone());
1841
+ line.mesh.setMaterial({ dashed: true });
1842
+ });
1843
+ this.updateDistanceUI();
1844
+ this.magnifier.renderWithPoint(intersection.point);
1845
+ this.mouseGroup.position.copy(intersection.point);
1846
+ if (mesh) {
1847
+ this.mouseGroup.quaternion.copy(mesh.quaternion);
1848
+ }
1849
+ else if (intersection.face) {
1850
+ const face = intersection.face.normal;
1851
+ const positionVector = face.clone().multiplyScalar(0.05);
1852
+ const position = intersection.point.clone().add(positionVector);
1853
+ const lookAtVector = position.clone().add(positionVector);
1854
+ this.mouseGroup.lookAt(lookAtVector);
1855
+ }
1856
+ this.five.needsRender = true;
1857
+ this.hook.emit('selectedChange', this.editPointState.associatedLines.map((line) => line.toCompletelyJson()));
1858
+ }
1859
+ });
1860
+ Object.defineProperty(this, "wantsPanGesture", {
1861
+ enumerable: true,
1862
+ configurable: true,
1863
+ writable: true,
1864
+ value: () => {
1865
+ if (this.editPointState)
1866
+ return false;
1867
+ }
1868
+ });
1869
+ Object.defineProperty(this, "wantsTapGesture", {
1870
+ enumerable: true,
1871
+ configurable: true,
1872
+ writable: true,
1873
+ value: (raycaster) => {
1874
+ const [target] = this.five.model.intersectRaycaster(raycaster);
1875
+ if (!target)
1876
+ return;
1877
+ const camera = this.five.camera;
1878
+ const ndcTarget = target.point.clone().project(camera);
1879
+ const screenWidth = this.container.clientWidth;
1880
+ const screenHeight = this.container.clientHeight;
1881
+ const targetScreenPosition = new THREE.Vector2(ndcTarget.x * screenWidth, ndcTarget.y * screenHeight);
1882
+ // 把线的端点全部映射到屏幕上,过滤掉不在视野内的线,同时乘以屏幕宽 & 高
1883
+ const screenLines = this.model.lines
1884
+ .map((line) => {
1885
+ const [startPoint, endPoint] = line.points;
1886
+ const ndcStartPoint = startPoint.position.clone().project(camera);
1887
+ const ndcEndPoint = endPoint.position.clone().project(camera);
1888
+ if (!isNDCPointInScreen(ndcStartPoint) && !isNDCPointInScreen(ndcEndPoint))
1889
+ return null;
1890
+ const startScreenPosition = new THREE.Vector2(ndcStartPoint.x * screenWidth, ndcStartPoint.y * screenHeight);
1891
+ const endScreenPosition = new THREE.Vector2(ndcEndPoint.x * screenWidth, ndcEndPoint.y * screenHeight);
1892
+ return { id: line.id, points: [startScreenPosition, endScreenPosition] };
1893
+ })
1894
+ .filter((line) => !!line);
1895
+ if (screenLines.length === 0)
1896
+ return;
1897
+ // 找这些线距离鼠标点击位置最近的线
1898
+ const distanceLines = screenLines
1899
+ .map((line) => {
1900
+ const closestPoint = closestPointOnLine(targetScreenPosition, line.points);
1901
+ return { id: line.id, distance: closestPoint.distanceTo(targetScreenPosition) };
1902
+ })
1903
+ .sort((a, b) => a.distance - b.distance);
1904
+ const closestScreenLine = distanceLines[0];
1905
+ if (closestScreenLine.distance > 20)
1906
+ return;
1907
+ const closestLine = this.model.lines.find(({ id }) => id === closestScreenLine.id);
1908
+ if (!closestLine)
1909
+ return;
1910
+ this.chooseLine(closestLine);
1911
+ return false;
1912
+ }
1913
+ });
1914
+ Object.defineProperty(this, "chooseLine", {
1915
+ enumerable: true,
1916
+ configurable: true,
1917
+ writable: true,
1918
+ value: (line) => {
1919
+ const highlightLines = findAssociatedLines(line);
1920
+ this.highlightLines(highlightLines);
1921
+ this.five.needsRender = true;
1922
+ this.hook.emit('selectedChange', highlightLines.map((line) => line.toCompletelyJson()));
1923
+ }
1924
+ });
1925
+ Object.defineProperty(this, "lineRemoved", {
1926
+ enumerable: true,
1927
+ configurable: true,
1928
+ writable: true,
1929
+ value: (line) => {
1930
+ this.removeLine(line);
1931
+ // TODO: 这个逻辑不太好,改进一下
1932
+ this.hook.emit('selectedChange', this.model.lines.filter((line) => line.selected).map((line) => line.toCompletelyJson()));
1933
+ }
1934
+ });
1935
+ Object.defineProperty(this, "onCameraUpdate", {
1936
+ enumerable: true,
1937
+ configurable: true,
1938
+ writable: true,
1939
+ value: () => {
1940
+ this.updateDistanceUI();
1941
+ this.highlightedLines.length > 0 && this.deleteDom.updatePosition();
1942
+ }
1943
+ });
1944
+ Object.defineProperty(this, "deleteDomClickCallback", {
1945
+ enumerable: true,
1946
+ configurable: true,
1947
+ writable: true,
1948
+ value: () => {
1949
+ const firstLine = this.highlightedLines[0];
1950
+ // TODO: 优化折线的删除逻辑
1951
+ firstLine
1952
+ .getPolyline()
1953
+ .lines.slice()
1954
+ .reverse()
1955
+ .forEach((line) => this.model.removeLine(line));
1956
+ this.highlightedLines = [];
1957
+ // this.clearHighlightLines()
1958
+ // this.highlightedLines.forEach((line) => this.model.removeLine(line))
1959
+ this.deleteDom.setLines([]).hide();
1960
+ }
1961
+ });
1962
+ Object.defineProperty(this, "cancelDeleteClickCallback", {
1963
+ enumerable: true,
1964
+ configurable: true,
1965
+ writable: true,
1966
+ value: () => {
1967
+ this.clearHighlightLines();
1968
+ }
1969
+ });
1970
+ this.deleteDom = new DeleteDom(this.five, {
1971
+ onClick: this.deleteDomClickCallback,
1972
+ cancelDelete: this.cancelDeleteClickCallback,
1973
+ }).appendTo(this.container);
1974
+ this.model.lines.forEach((line) => {
1975
+ line.distanceItem.appendTo(this.container);
1976
+ line.distanceItem.update(this.five);
1977
+ line.hook.on('selected', this.chooseLine);
1978
+ this.group.add(line.mesh);
1979
+ });
1980
+ const fiveElement = this.five.getElement();
1981
+ if (fiveElement) {
1982
+ this.fiveElement = fiveElement;
1983
+ const hammer = new Hammer__default["default"](fiveElement);
1984
+ this.hammer = hammer;
1985
+ hammer.on('pan', this.onPan);
1986
+ hammer.on('panstart', this.onPanStart);
1987
+ hammer.on('panend', this.onPanEnd);
1988
+ }
1989
+ this.model.hook.on('lineRemoved', this.lineRemoved);
1990
+ this.five.on('cameraUpdate', this.onCameraUpdate);
1991
+ this.five.on('wantsTapGesture', this.wantsTapGesture);
1992
+ this.five.on('wantsPanGesture', this.wantsPanGesture);
1993
+ this.five.needsRender = true;
1994
+ }
1995
+ dispose() {
1996
+ var _a;
1997
+ super.dispose();
1998
+ this.deleteDom.dispose();
1999
+ this.model.hook.off('lineRemoved', this.lineRemoved);
2000
+ this.five.off('cameraUpdate', this.onCameraUpdate);
2001
+ this.five.off('wantsPanGesture', this.wantsPanGesture);
2002
+ this.five.off('wantsTapGesture', this.wantsTapGesture);
2003
+ this.five.needsRender = true;
2004
+ this.hook.emit('selectedChange', []);
2005
+ (_a = this.hammer) === null || _a === void 0 ? void 0 : _a.destroy();
2006
+ }
2007
+ highlightLine(line) {
2008
+ if (line.selected)
2009
+ return;
2010
+ line.selected = true;
2011
+ this.group.add(line.lightMesh);
2012
+ line.distanceItem.highlight();
2013
+ this.five.needsRender = true;
2014
+ }
2015
+ clearHighlightLines() {
2016
+ if (this.group.children.length === 0)
2017
+ return;
2018
+ this.deleteDom.setLines([]).hide();
2019
+ this.model.lines.forEach((line) => {
2020
+ line.selected = false;
2021
+ line.distanceItem.unHighlight();
2022
+ this.group.remove(line.lightMesh);
2023
+ });
2024
+ this.highlightedLines = [];
2025
+ this.five.needsRender = true;
2026
+ }
2027
+ highlightLines(lines) {
2028
+ this.clearHighlightLines();
2029
+ this.highlightedLines = lines;
2030
+ this.deleteDom.setLines(lines).updatePosition().show();
2031
+ lines.forEach((line) => this.highlightLine(line));
2032
+ }
2033
+ }
2034
+
2035
+ class MixedController extends BaseController {
2036
+ constructor(params) {
2037
+ super(params);
2038
+ Object.defineProperty(this, "state", {
2039
+ enumerable: true,
2040
+ configurable: true,
2041
+ writable: true,
2042
+ value: 'watching'
2043
+ });
2044
+ Object.defineProperty(this, "model", {
2045
+ enumerable: true,
2046
+ configurable: true,
2047
+ writable: true,
2048
+ value: new Model({ userDistanceItemCreator: this.userDistanceItemCreator })
2049
+ });
2050
+ Object.defineProperty(this, "hasAppendDashed", {
2051
+ enumerable: true,
2052
+ configurable: true,
2053
+ writable: true,
2054
+ value: false
2055
+ });
2056
+ Object.defineProperty(this, "fiveElement", {
2057
+ enumerable: true,
2058
+ configurable: true,
2059
+ writable: true,
2060
+ value: void 0
2061
+ });
2062
+ Object.defineProperty(this, "mobileStartPoint", {
2063
+ enumerable: true,
2064
+ configurable: true,
2065
+ writable: true,
2066
+ value: null
2067
+ });
2068
+ Object.defineProperty(this, "mobileNowPoint", {
2069
+ enumerable: true,
2070
+ configurable: true,
2071
+ writable: true,
2072
+ value: null
2073
+ });
2074
+ Object.defineProperty(this, "highlightedLines", {
2075
+ enumerable: true,
2076
+ configurable: true,
2077
+ writable: true,
2078
+ value: []
2079
+ });
2080
+ Object.defineProperty(this, "deleteDom", {
2081
+ enumerable: true,
2082
+ configurable: true,
2083
+ writable: true,
2084
+ value: void 0
2085
+ });
2086
+ /** 圆环点到上一个端点连接的虚线 */
2087
+ Object.defineProperty(this, "dashed", {
2088
+ enumerable: true,
2089
+ configurable: true,
2090
+ writable: true,
2091
+ value: void 0
2092
+ });
2093
+ /** 编辑线条发生改变时通知外部 */
2094
+ Object.defineProperty(this, "onLineChanged", {
2095
+ enumerable: true,
2096
+ configurable: true,
2097
+ writable: true,
2098
+ value: () => {
2099
+ this.hook.emit('editedLineChange', this.model.lines.map((line) => line.toCompletelyJson()));
2100
+ }
2101
+ });
2102
+ Object.defineProperty(this, "onWantsTapGesture", {
2103
+ enumerable: true,
2104
+ configurable: true,
2105
+ writable: true,
2106
+ value: (raycaster) => {
2107
+ if (this.state === 'editing')
2108
+ return false;
2109
+ const [target] = this.five.model.intersectRaycaster(raycaster);
2110
+ if (!target)
2111
+ return;
2112
+ const camera = this.five.camera;
2113
+ const ndcTarget = target.point.clone().project(camera);
2114
+ const screenWidth = this.container.clientWidth;
2115
+ const screenHeight = this.container.clientHeight;
2116
+ const targetScreenPosition = new THREE.Vector2(ndcTarget.x * screenWidth, ndcTarget.y * screenHeight);
2117
+ // 把线的端点全部映射到屏幕上,过滤掉不在视野内的线,同时乘以屏幕宽 & 高
2118
+ const screenLines = this.model.lines
2119
+ .map((line) => {
2120
+ const [startPoint, endPoint] = line.points;
2121
+ const ndcStartPoint = startPoint.position.clone().project(camera);
2122
+ const ndcEndPoint = endPoint.position.clone().project(camera);
2123
+ if (!isNDCPointInScreen(ndcStartPoint) && !isNDCPointInScreen(ndcEndPoint))
2124
+ return null;
2125
+ const startScreenPosition = new THREE.Vector2(ndcStartPoint.x * screenWidth, ndcStartPoint.y * screenHeight);
2126
+ const endScreenPosition = new THREE.Vector2(ndcEndPoint.x * screenWidth, ndcEndPoint.y * screenHeight);
2127
+ return { id: line.id, points: [startScreenPosition, endScreenPosition] };
2128
+ })
2129
+ .filter((line) => !!line);
2130
+ if (screenLines.length === 0)
2131
+ return;
2132
+ // 找这些线距离鼠标点击位置最近的线
2133
+ const distanceLines = screenLines
2134
+ .map((line) => {
2135
+ const closestPoint = closestPointOnLine(targetScreenPosition, line.points);
2136
+ return { id: line.id, distance: closestPoint.distanceTo(targetScreenPosition) };
2137
+ })
2138
+ .sort((a, b) => a.distance - b.distance);
2139
+ const closestScreenLine = distanceLines[0];
2140
+ if (closestScreenLine.distance > 20)
2141
+ return;
2142
+ const closestLine = this.model.lines.find(({ id }) => id === closestScreenLine.id);
2143
+ if (!closestLine)
2144
+ return;
2145
+ this.chooseLine(closestLine);
2146
+ return false;
2147
+ }
2148
+ });
2149
+ /** 编辑时取消走点,watch时可以走 */
2150
+ Object.defineProperty(this, "onWantsToMoveToPano", {
2151
+ enumerable: true,
2152
+ configurable: true,
2153
+ writable: true,
2154
+ value: () => this.state === 'watching'
2155
+ });
2156
+ /** 移动全景时更新 distanceItem 在屏幕上的位置 */
2157
+ Object.defineProperty(this, "onCameraUpdate", {
2158
+ enumerable: true,
2159
+ configurable: true,
2160
+ writable: true,
2161
+ value: () => {
2162
+ this.updateDistanceUI();
2163
+ this.dashed.distanceItem.update(this.five);
2164
+ }
2165
+ });
2166
+ /** mobile态时更新虚线 */
2167
+ Object.defineProperty(this, "updateMobileDashed", {
2168
+ enumerable: true,
2169
+ configurable: true,
2170
+ writable: true,
2171
+ value: () => {
2172
+ if (!this.mobileStartPoint || !this.mobileNowPoint)
2173
+ return;
2174
+ this.dashed.points[0].position.copy(this.mobileStartPoint.position);
2175
+ this.dashed.points[1].position.copy(this.mobileNowPoint.position);
2176
+ this.dashed.mesh.setPoints(this.mobileStartPoint.position, this.mobileNowPoint.position);
2177
+ this.dashed.distanceItem.update(this.five);
2178
+ }
2179
+ });
2180
+ /** mobile态时更新放大镜 */
2181
+ Object.defineProperty(this, "updateMagnifier", {
2182
+ enumerable: true,
2183
+ configurable: true,
2184
+ writable: true,
2185
+ value: (point) => {
2186
+ if (this.magnifier.visible === false) {
2187
+ this.magnifier.appendTo(this.container);
2188
+ }
2189
+ requestAnimationFrame(() => this.magnifier.renderWithPoint(point.position));
2190
+ this.five.needsRender = true;
2191
+ }
2192
+ });
2193
+ Object.defineProperty(this, "onGetStartPoint", {
2194
+ enumerable: true,
2195
+ configurable: true,
2196
+ writable: true,
2197
+ value: (point) => {
2198
+ this.mobileStartPoint = point;
2199
+ }
2200
+ });
2201
+ Object.defineProperty(this, "onGetEndPoint", {
2202
+ enumerable: true,
2203
+ configurable: true,
2204
+ writable: true,
2205
+ value: (point) => {
2206
+ const endPoint = this.mobileNowPoint;
2207
+ this.removeLine(this.dashed);
2208
+ this.hasAppendDashed = false;
2209
+ if (this.mobileStartPoint && endPoint) {
2210
+ const line = new Line(this.mobileStartPoint, endPoint, this.model);
2211
+ line.distanceItem.appendTo(this.container);
2212
+ line.distanceItem.update(this.five);
2213
+ line.hook.on('selected', this.chooseLine);
2214
+ this.group.add(line.mesh);
2215
+ this.model.addLine(line);
2216
+ }
2217
+ this.mobileStartPoint = null;
2218
+ this.mobileNowPoint = null;
2219
+ this.five.needsRender = true;
2220
+ }
2221
+ });
2222
+ Object.defineProperty(this, "onNowPointChange", {
2223
+ enumerable: true,
2224
+ configurable: true,
2225
+ writable: true,
2226
+ value: (point) => {
2227
+ if (this.state === 'watching') {
2228
+ this.mobileNowPoint = point;
2229
+ this.updateMagnifier(point);
2230
+ return;
2231
+ }
2232
+ if (!this.hasAppendDashed) {
2233
+ this.dashed.distanceItem.appendTo(this.container);
2234
+ this.group.add(this.dashed.mesh);
2235
+ this.hasAppendDashed = true;
2236
+ }
2237
+ this.five.needsRender = true;
2238
+ this.mobileNowPoint = point;
2239
+ this.updateMobileDashed();
2240
+ this.updateMagnifier(point);
2241
+ this.five.needsRender = true;
2242
+ }
2243
+ });
2244
+ Object.defineProperty(this, "onWillChangeState", {
2245
+ enumerable: true,
2246
+ configurable: true,
2247
+ writable: true,
2248
+ value: (state, newState) => {
2249
+ this.state = newState;
2250
+ if (this.state === 'watching') {
2251
+ this.five.helperVisible = true;
2252
+ }
2253
+ else {
2254
+ // 隐藏点位和鼠标聚焦环
2255
+ this.five.helperVisible = false;
2256
+ }
2257
+ }
2258
+ });
2259
+ Object.defineProperty(this, "chooseLine", {
2260
+ enumerable: true,
2261
+ configurable: true,
2262
+ writable: true,
2263
+ value: (line) => {
2264
+ const highlightLines = findAssociatedLines(line);
2265
+ this.highlightLines(highlightLines);
2266
+ this.five.needsRender = true;
2267
+ this.hook.emit('selectedChange', highlightLines.map((line) => line.toCompletelyJson()));
2268
+ }
2269
+ });
2270
+ Object.defineProperty(this, "deleteDomClickCallback", {
2271
+ enumerable: true,
2272
+ configurable: true,
2273
+ writable: true,
2274
+ value: () => {
2275
+ this.highlightedLines.forEach((line) => {
2276
+ this.removeLine(line);
2277
+ this.model.removeLine(line);
2278
+ });
2279
+ this.highlightedLines = [];
2280
+ this.deleteDom.setLines([]).hide();
2281
+ }
2282
+ });
2283
+ Object.defineProperty(this, "cancelDeleteClickCallback", {
2284
+ enumerable: true,
2285
+ configurable: true,
2286
+ writable: true,
2287
+ value: () => {
2288
+ this.clearHighlightLines();
2289
+ }
2290
+ });
2291
+ this.deleteDom = new DeleteDom(this.five, {
2292
+ onClick: this.deleteDomClickCallback,
2293
+ cancelDelete: this.cancelDeleteClickCallback,
2294
+ }).appendTo(this.container);
2295
+ // ==================== 虚线 ====================
2296
+ this.dashed = new Line(new Point([0, 0, 0]), new Point([0, 0, 0]), this.model);
2297
+ this.dashed.mesh.setMaterial({ dashed: true, dashScale: 100 });
2298
+ this.dashed.mesh.name = 'dashLine';
2299
+ // ==================== 事件监听 ====================
2300
+ // five
2301
+ this.five.on('cameraUpdate', this.onCameraUpdate);
2302
+ this.five.on('wantsTapGesture', this.onWantsTapGesture);
2303
+ this.five.on('wantsToMoveToPano', this.onWantsToMoveToPano);
2304
+ // model
2305
+ this.model.hook.on('lineAdded', this.onLineChanged);
2306
+ this.model.hook.on('lineRemoved', this.onLineChanged);
2307
+ // ==================== 其他 ====================
2308
+ this.hook.on('getStartPoint', this.onGetStartPoint);
2309
+ this.hook.on('getEndPoint', this.onGetEndPoint);
2310
+ this.hook.on('nowPointChange', this.onNowPointChange);
2311
+ this.hook.on('willChangeState', this.onWillChangeState);
2312
+ this.five.refresh();
2313
+ }
2314
+ dispose() {
2315
+ super.dispose();
2316
+ this.group.remove(this.mouseGroup, this.dashed.mesh);
2317
+ // ==================== 解除事件监听 ====================
2318
+ // five
2319
+ this.five.off('cameraUpdate', this.onCameraUpdate);
2320
+ this.five.off('wantsTapGesture', this.onWantsTapGesture);
2321
+ this.five.off('wantsToMoveToPano', this.onWantsToMoveToPano);
2322
+ // model
2323
+ this.model.hook.off('lineAdded', this.onLineChanged);
2324
+ this.model.hook.off('lineRemoved', this.onLineChanged);
2325
+ this.hook.off('getStartPoint', this.onGetStartPoint);
2326
+ this.hook.off('getEndPoint', this.onGetEndPoint);
2327
+ this.hook.off('nowPointChange', this.onNowPointChange);
2328
+ this.hook.off('willChangeState', this.onWillChangeState);
2329
+ this.hook.emit('selectedChange', []);
2330
+ this.dashed.distanceItem.remove();
2331
+ this.five.needsRender = true;
2332
+ }
2333
+ highlightLine(line) {
2334
+ if (line.selected)
2335
+ return;
2336
+ line.selected = true;
2337
+ this.group.add(line.lightMesh);
2338
+ line.distanceItem.highlight();
2339
+ this.five.needsRender = true;
2340
+ }
2341
+ clearHighlightLines() {
2342
+ if (this.group.children.length === 0)
2343
+ return;
2344
+ this.deleteDom.setLines([]).hide();
2345
+ this.model.lines.forEach((line) => {
2346
+ line.selected = false;
2347
+ line.distanceItem.unHighlight();
2348
+ this.group.remove(line.lightMesh);
2349
+ });
2350
+ this.highlightedLines = [];
2351
+ this.five.needsRender = true;
2352
+ }
2353
+ getEditingLines() {
2354
+ return this.model.lines;
2355
+ }
2356
+ highlightLines(lines) {
2357
+ this.clearHighlightLines();
2358
+ this.highlightedLines = lines;
2359
+ this.deleteDom.setLines(lines).updatePosition().show();
2360
+ lines.forEach((line) => this.highlightLine(line));
2361
+ }
2362
+ }
2363
+
2364
+ const planTextureUrl = `data:image/png;base64,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`;
2365
+ function getMouseGroup() {
2366
+ const group = new THREE.Group();
2367
+ const planGeometry = new THREE.PlaneGeometry(0.3, 0.3);
2368
+ const planTexture = new THREE.TextureLoader().load(planTextureUrl);
2369
+ planTexture.encoding = THREE.sRGBEncoding;
2370
+ const planMaterial = new THREE.MeshBasicMaterial({ map: planTexture, transparent: true, depthTest: false });
2371
+ const planMesh = new THREE.Mesh(planGeometry, planMaterial);
2372
+ const zPath = new THREE.CurvePath();
2373
+ zPath.add(new THREE.LineCurve3(new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, 0.1)));
2374
+ const zGeometry = new THREE.TubeGeometry(zPath, 8, 0.004);
2375
+ const zMaterial = new THREE.MeshBasicMaterial({ color: 0x33f1ef, depthTest: false, transparent: true, side: THREE.DoubleSide });
2376
+ new THREE.Mesh(zGeometry, zMaterial);
2377
+ const ballGeometry = new THREE.SphereGeometry(0.01, 20, 20);
2378
+ const ballMesh = new THREE.Mesh(ballGeometry, zMaterial);
2379
+ ballMesh.position.set(0, 0, 0.1);
2380
+ group.name = 'mouse-current';
2381
+ group.add(planMesh);
2382
+ return group;
2383
+ }
2384
+
2385
+ const MAIN_NORMAL_PATH = 'M31.379 15.466a1.045 1.045 0 0 1-.92 1.076l-11.276.607a1.6 1.6 0 0 0-1.512 1.511l-.599 11.113a1.045 1.045 0 0 1-.92 1.075l-.164.008a1.183 1.183 0 0 1-1.123-.975l-.016-.164-.221-10.768a1.6 1.6 0 0 0-1.567-1.567l-11.3-.231-.165-.016a1.187 1.187 0 0 1-.964-.996l-.01-.127.007-.164c.061-.496.455-.876.958-.917l.118-.003 11.112-.599a1.6 1.6 0 0 0 1.498-1.37l.014-.142.607-11.276a1.045 1.045 0 0 1 1.076-.92c.573.015 1.055.46 1.13 1.019l.009.121.221 10.766a1.6 1.6 0 0 0 1.567 1.566l11.3.234a1.181 1.181 0 0 1 1.14 1.139z';
2386
+ const MAIN_DONE_PATH = 'M27.1772552,8.15828895 C27.8664561,7.48070421 28.5574369,7.81156875 28.8336646,8.04968716 C29.1098924,8.28780557 29.3990219,9.110014 28.8256559,9.79263351 L28.7110903,9.9165024 L13.9697229,25.1399531 C13.3288458,25.7700285 12.3239388,25.8070917 11.6402346,25.2511429 L11.5159715,25.1399531 L3.7056151,18.0063788 C3.01641417,17.3287941 3.00699739,16.2207954 3.68458213,15.5315945 C4.32230894,14.8829348 5.3413021,14.8364368 6.03356826,15.3981178 L6.15936649,15.5105615 L12.6856594,21.9049888 L27.1772552,8.15828895 Z';
2387
+ const MAIN_MOUSE_ENTER_FILL = 'url(#fpm__main-b)';
2388
+ const MAIN_MOUSE_LEAVE_FILL = 'url(#fpm__main-c)';
2389
+ const revokeSvg = `
2390
+ <svg class="fpm__revoke-icon" width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
2391
+ <defs>
2392
+ <linearGradient x1="47.631%" y1="55.183%" x2="2.967%" y2="86.323%" id="fpm__revoke-a">
2393
+ <stop stop-color="#FFF" offset="0%" />
2394
+ <stop stop-color="#FFF" stop-opacity=".5" offset="100%" />
2395
+ </linearGradient>
2396
+ <linearGradient x1="5.297%" y1="43.016%" x2="38.238%" y2="79.932%" id="fpm__revoke-b">
2397
+ <stop stop-color="#FFF" offset="0%" />
2398
+ <stop stop-color="#FFF" stop-opacity="0" offset="100%" />
2399
+ </linearGradient>
2400
+ </defs>
2401
+ <path
2402
+ d="M13.388 7.108c.552 0 1.005.42 1.06.957l.006.11v1.224c0 .921.745 1.667 1.666 1.667h7.184c5.804 0 10.509 4.616 10.509 10.309 0 5.595-4.544 10.15-10.21 10.305l-.3.004H8.924c-.917 0-1.66-.729-1.66-1.628 0-.846.658-1.541 1.5-1.62l.16-.008h14.38c3.972 0 7.191-3.158 7.191-7.053 0-3.81-3.08-6.916-6.933-7.049l-.257-.004H10.029l-.109-.005H8.212c-.245 0-.482-.085-.67-.237l-.09-.082a1.066 1.066 0 0 1-.065-1.422l.079-.086 5.175-5.077c.2-.195.468-.305.747-.305z"
2403
+ fill="url(#fpm__revoke-a)"
2404
+ fill-rule="nonzero"
2405
+ stroke="url(#fpm__revoke-b)"
2406
+ stroke-width=".5"
2407
+ />
2408
+ </svg>
2409
+ `;
2410
+ const exitSvg = `
2411
+ <svg class="fpm__exit-icon width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
2412
+ <defs>
2413
+ <linearGradient x1="36.288%" y1="73.736%" x2="54.242%" y2="97.166%" id="fpm__exit-a">
2414
+ <stop stop-color="#FFF" offset="0%" />
2415
+ <stop stop-color="#FFF" stop-opacity=".5" offset="100%" />
2416
+ </linearGradient>
2417
+ <linearGradient x1="100%" y1="47.234%" x2="24.047%" y2="47.234%" id="fpm__exit-b">
2418
+ <stop stop-color="#FFF" offset="0%" />
2419
+ <stop stop-color="#FFF" stop-opacity=".005" offset="99.535%" />
2420
+ <stop stop-color="#FFF" stop-opacity="0" offset="100%" />
2421
+ </linearGradient>
2422
+ </defs>
2423
+ <path
2424
+ d="M22 7a1.5 1.5 0 0 1 .144 2.993L22 10h-9a1.5 1.5 0 0 0-1.493 1.356l-.007.144v17a1.5 1.5 0 0 0 1.356 1.493L13 30h9a1.5 1.5 0 0 1 .144 2.993L22 33h-9a4.5 4.5 0 0 1-4.495-4.288L8.5 28.5v-17a4.5 4.5 0 0 1 4.288-4.495L13 7h9zm6.317 7.755a1 1 0 0 1 .7.286l4.856 4.764a1 1 0 0 1-.7 1.713h-5.856V21.5h-8.032a1.5 1.5 0 1 1 0-3h6.365c.92 0 1.666-.746 1.667-1.667v-1.078a1 1 0 0 1 1-1z"
2425
+ fill="url(#fpm__exit-a)"
2426
+ fill-rule="nonzero"
2427
+ stroke="url(#fpm__exit-b)"
2428
+ stroke-width=".5"
2429
+ />
2430
+ </svg>
2431
+ `;
2432
+ const mainSvg = `
2433
+ <svg class="fpm__main-icon" width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
2434
+ <defs>
2435
+ <mask id="fpm__main-icon-mask">
2436
+ <rect id="fpm__main-icon-mask-black" x="0" y="0" width="30" height="30" fill="black"></rect>
2437
+ <rect id="fpm__main-icon-mask-white" x="0" y="0" width="0" height="30" fill="white"></rect>
2438
+ </mask>
2439
+ <linearGradient id="fpm__main-a" x1="25.371%" y1="0%" x2="109.587%" y2="172.268%">
2440
+ <stop stop-color="#FFF" offset="0%" />
2441
+ <stop stop-color="#FFF" stop-opacity=".77" offset="44.051%" />
2442
+ <stop stop-color="#FFF" stop-opacity=".201" offset="100%" />
2443
+ </linearGradient>
2444
+ <radialGradient id="fpm__main-b" fx="50%" fy="50%" r="50.864%" gradientTransform="matrix(-.98302 0 0 -1 .992 1)">
2445
+ <stop stop-color="#2D7CFF" offset="0%" />
2446
+ <stop stop-color="#2D7CFF" stop-opacity=".3" offset="100%" />
2447
+ </radialGradient>
2448
+ <radialGradient id="fpm__main-c" fx="50%" fy="50%" r="50.864%" gradientTransform="matrix(-.98302 0 0 -1 .992 1)">
2449
+ <stop stop-opacity=".4" offset="0%" />
2450
+ <stop stop-opacity=".12" offset="100%" />
2451
+ </radialGradient>
2452
+ </defs>
2453
+ <g fill="none" fill-rule="evenodd">
2454
+ <circle fill="url(#fpm__main-a)" cx="30" cy="30" r="30" />
2455
+ <path
2456
+ class="fpm__main-icon-path"
2457
+ d="${MAIN_NORMAL_PATH}"
2458
+ fill="${MAIN_MOUSE_LEAVE_FILL}"
2459
+ fill-rule="nonzero"
2460
+ transform="translate(14 14)"
2461
+ />
2462
+ </g>
2463
+ </svg>
2464
+ `;
2465
+ var htmlString$1 = `
2466
+ <style>
2467
+ .fpm__revoke {
2468
+ opacity: 0.3;
2469
+ }
2470
+
2471
+ .fpm__revoke.enabled {
2472
+ opacity: 0.7;
2473
+ }
2474
+
2475
+ .fpm__revoke.enabled:hover {
2476
+ opacity: 1;
2477
+ }
2478
+
2479
+ .fpm__revoke-icon {
2480
+ width: 40px;
2481
+ height: 40px;
2482
+ margin-top: 10px;
2483
+ cursor: pointer;
2484
+ }
2485
+ </style>
2486
+ <div class="fpm_ui-bg"></div>
2487
+ <div class="fpm_operating-space">
2488
+ <div class="fpm__ui-item fpm__revoke">
2489
+ ${revokeSvg}
2490
+ <span class="fpm__text fpm__revoke-text">撤销</span>
2491
+ </div>
2492
+ <div class="fpm__ui-item fpm__main">
2493
+ ${mainSvg}
2494
+ <span class="fpm__text fpm__main-text">添加</span>
2495
+ </div>
2496
+ <div class="fpm__ui-item fpm__exit">
2497
+ ${exitSvg}
2498
+ <span class="fpm__text fpm__exit-text">退出</span>
2499
+ </div>
2500
+ </div>
2501
+ `;
2502
+
2503
+ const startIconImage = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzIiIGhlaWdodD0iNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxmaWx0ZXIgeD0iLTUuMyUiIHk9Ii01LjMlIiB3aWR0aD0iMTEwLjUlIiBoZWlnaHQ9IjExMC41JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0icHJlZml4X19hIj48ZmVPZmZzZXQgaW49IlNvdXJjZUFscGhhIiByZXN1bHQ9InNoYWRvd09mZnNldE91dGVyMSIvPjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjEiIGluPSJzaGFkb3dPZmZzZXRPdXRlcjEiIHJlc3VsdD0ic2hhZG93Qmx1ck91dGVyMSIvPjxmZUNvbXBvc2l0ZSBpbj0ic2hhZG93Qmx1ck91dGVyMSIgaW4yPSJTb3VyY2VBbHBoYSIgb3BlcmF0b3I9Im91dCIgcmVzdWx0PSJzaGFkb3dCbHVyT3V0ZXIxIi8+PGZlQ29sb3JNYXRyaXggdmFsdWVzPSIwIDAgMCAwIDEgMCAwIDAgMCAxIDAgMCAwIDAgMSAwIDAgMCAwLjUgMCIgaW49InNoYWRvd0JsdXJPdXRlcjEiLz48L2ZpbHRlcj48ZmlsdGVyIHg9Ii0xMS40JSIgeT0iLTExLjQlIiB3aWR0aD0iMTIyLjklIiBoZWlnaHQ9IjEyMi45JSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94IiBpZD0icHJlZml4X19jIj48ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSI0LjUiIGluPSJTb3VyY2VBbHBoYSIgcmVzdWx0PSJzaGFkb3dCbHVySW5uZXIxIi8+PGZlT2Zmc2V0IGluPSJzaGFkb3dCbHVySW5uZXIxIiByZXN1bHQ9InNoYWRvd09mZnNldElubmVyMSIvPjxmZUNvbXBvc2l0ZSBpbj0ic2hhZG93T2Zmc2V0SW5uZXIxIiBpbjI9IlNvdXJjZUFscGhhIiBvcGVyYXRvcj0iYXJpdGhtZXRpYyIgazI9Ii0xIiBrMz0iMSIgcmVzdWx0PSJzaGFkb3dJbm5lcklubmVyMSIvPjxmZUNvbG9yTWF0cml4IHZhbHVlcz0iMCAwIDAgMCAxIDAgMCAwIDAgMSAwIDAgMCAwIDEgMCAwIDAgMC4zIDAiIGluPSJzaGFkb3dJbm5lcklubmVyMSIvPjwvZmlsdGVyPjxmaWx0ZXIgeD0iLTEyNi42JSIgeT0iLTMzNy41JSIgd2lkdGg9IjM1My4xJSIgaGVpZ2h0PSI3NzUlIiBmaWx0ZXJVbml0cz0ib2JqZWN0Qm91bmRpbmdCb3giIGlkPSJwcmVmaXhfX2UiPjxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjE2IiBpbj0iU291cmNlR3JhcGhpYyIvPjwvZmlsdGVyPjxsaW5lYXJHcmFkaWVudCB4MT0iNTAlIiB5MT0iMTAwJSIgeDI9IjUwJSIgeTI9IjAlIiBpZD0icHJlZml4X19kIj48c3RvcCBzdG9wLWNvbG9yPSIjRkZGIiBzdG9wLW9wYWNpdHk9Ii43IiBvZmZzZXQ9IjAlIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0ZGRiIgc3RvcC1vcGFjaXR5PSIwIiBvZmZzZXQ9IjI2LjQzMiUiLz48c3RvcCBzdG9wLWNvbG9yPSIjRkZGIiBzdG9wLW9wYWNpdHk9IjAiIG9mZnNldD0iODIuMzA1JSIvPjxzdG9wIHN0b3AtY29sb3I9IiNGRkYiIHN0b3Atb3BhY2l0eT0iLjQiIG9mZnNldD0iMTAwJSIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IHgxPSI1MCUiIHkxPSIwJSIgeDI9IjUwJSIgeTI9IjEwMCUiIGlkPSJwcmVmaXhfX2YiPjxzdG9wIHN0b3AtY29sb3I9IiNGRkYiIHN0b3Atb3BhY2l0eT0iLjA1IiBvZmZzZXQ9IjAlIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0ZGRiIgc3RvcC1vcGFjaXR5PSIuMiIgb2Zmc2V0PSIxMDAlIi8+PC9saW5lYXJHcmFkaWVudD48Y2lyY2xlIGlkPSJwcmVmaXhfX2IiIGN4PSIzNiIgY3k9IjM2IiByPSIyOC40NDQiLz48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNwcmVmaXhfX2EpIiB4bGluazpocmVmPSIjcHJlZml4X19iIi8+PHVzZSBmaWxsPSIjMDAwIiBmaWx0ZXI9InVybCgjcHJlZml4X19jKSIgeGxpbms6aHJlZj0iI3ByZWZpeF9fYiIvPjxjaXJjbGUgc3Ryb2tlPSJ1cmwoI3ByZWZpeF9fZCkiIHN0cm9rZS13aWR0aD0iLjQiIGZpbGwtb3BhY2l0eT0iLjI0MSIgZmlsbD0iI0ZGRiIgc3Ryb2tlLWxpbmVqb2luPSJzcXVhcmUiIGN4PSIzNiIgY3k9IjM2IiByPSIyOC4yNDQiLz48ZWxsaXBzZSBmaWxsPSIjRkZGIiBvcGFjaXR5PSIuNTk2IiBmaWx0ZXI9InVybCgjcHJlZml4X19lKSIgY3g9IjM2IiBjeT0iMzYiIHJ4PSIxOC45NjMiIHJ5PSI3LjExMSIvPjxwYXRoIGQ9Ik0zNiAwQzE2LjExOCAwIDAgMTYuMTE4IDAgMzZzMTYuMTE4IDM2IDM2IDM2IDM2LTE2LjExOCAzNi0zNlM1NS44ODIgMCAzNiAwem0wIDQuNDQ0YzE3LjQyOCAwIDMxLjU1NiAxNC4xMjggMzEuNTU2IDMxLjU1NlM1My40MjggNjcuNTU2IDM2IDY3LjU1NiA0LjQ0NCA1My40MjggNC40NDQgMzYgMTguNTcyIDQuNDQ0IDM2IDQuNDQ0eiIgZmlsbD0idXJsKCNwcmVmaXhfX2YpIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L2c+PC9zdmc+`;
2504
+ const endIconImage = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzIiIGhlaWdodD0iNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IHgxPSIxNS41MSUiIHkxPSIxMi40OTclIiB4Mj0iODUuMjY1JSIgeTI9Ijg2LjE0MyUiIGlkPSJwcmVmaXhfX2IiPjxzdG9wIHN0b3AtY29sb3I9IiM5NUFFRkYiIG9mZnNldD0iMCUiLz48c3RvcCBzdG9wLWNvbG9yPSIjNjM4NkZGIiBvZmZzZXQ9IjEwMCUiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCB4MT0iNTAlIiB5MT0iMTAwJSIgeDI9IjUwJSIgeTI9IjAlIiBpZD0icHJlZml4X19hIj48c3RvcCBzdG9wLWNvbG9yPSIjOTlBRUZGIiBvZmZzZXQ9IjAlIi8+PHN0b3Agc3RvcC1jb2xvcj0iI0ZGRiIgc3RvcC1vcGFjaXR5PSIwIiBvZmZzZXQ9IjI2LjQzMiUiLz48c3RvcCBzdG9wLWNvbG9yPSIjRkZGIiBzdG9wLW9wYWNpdHk9IjAiIG9mZnNldD0iODIuMzA1JSIvPjxzdG9wIHN0b3AtY29sb3I9IiM5OUFFRkYiIHN0b3Atb3BhY2l0eT0iLjQiIG9mZnNldD0iMTAwJSIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IHgxPSI1MCUiIHkxPSIwJSIgeDI9IjUwJSIgeTI9IjEwMCUiIGlkPSJwcmVmaXhfX2QiPjxzdG9wIHN0b3AtY29sb3I9IiM4Nzk3RDIiIHN0b3Atb3BhY2l0eT0iLjA1IiBvZmZzZXQ9IjAlIi8+PHN0b3Agc3RvcC1jb2xvcj0iIzYyNzdDNyIgc3RvcC1vcGFjaXR5PSIuMiIgb2Zmc2V0PSIxMDAlIi8+PC9saW5lYXJHcmFkaWVudD48ZmlsdGVyIHg9Ii02My4zJSIgeT0iLTE2OC44JSIgd2lkdGg9IjIyNi42JSIgaGVpZ2h0PSI0MzcuNSUiIGZpbHRlclVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgaWQ9InByZWZpeF9fYyI+PGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iOCIgaW49IlNvdXJjZUdyYXBoaWMiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48Y2lyY2xlIHN0cm9rZT0idXJsKCNwcmVmaXhfX2EpIiBzdHJva2Utd2lkdGg9Ii40IiBmaWxsPSJ1cmwoI3ByZWZpeF9fYikiIG9wYWNpdHk9Ii43IiBjeD0iMzYiIGN5PSIzNiIgcj0iMjguMjQ0Ii8+PGVsbGlwc2UgZmlsbD0iIzdDOTBEQSIgb3BhY2l0eT0iLjU5NiIgZmlsdGVyPSJ1cmwoI3ByZWZpeF9fYykiIGN4PSIzNiIgY3k9IjM2IiByeD0iMTguOTYzIiByeT0iNy4xMTEiLz48cGF0aCBkPSJNMzYgMEMxNi4xMTggMCAwIDE2LjExOCAwIDM2czE2LjExOCAzNiAzNiAzNiAzNi0xNi4xMTggMzYtMzZTNTUuODgyIDAgMzYgMHptMCA0LjQ0NGMxNy40MjggMCAzMS41NTYgMTQuMTI4IDMxLjU1NiAzMS41NTZTNTMuNDI4IDY3LjU1NiAzNiA2Ny41NTYgNC40NDQgNTMuNDI4IDQuNDQ0IDM2IDE4LjU3MiA0LjQ0NCAzNiA0LjQ0NHoiIGZpbGw9InVybCgjcHJlZml4X19kKSIgZmlsbC1ydWxlPSJub256ZXJvIi8+PC9nPjwvc3ZnPg==`;
2505
+ const exitIconSvg = `
2506
+ <svg class="fpm__exit-icon width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
2507
+ <defs>
2508
+ <radialGradient cx="50%" cy="50%" fx="50%" fy="50%" r="86.3016741%" id="radialGradient-1">
2509
+ <stop stop-color="#FFFFFF" offset="0%"></stop>
2510
+ <stop stop-color="#FFFFFF" stop-opacity="0.3" offset="100%"></stop>
2511
+ </radialGradient>
2512
+ <radialGradient cx="50%" cy="50%" fx="50%" fy="50%" r="70.7106781%" id="radialGradient-2">
2513
+ <stop stop-color="#FFFFFF" offset="0%"></stop>
2514
+ <stop stop-color="#FFFFFF" stop-opacity="0" offset="100%"></stop>
2515
+ </radialGradient>
2516
+ </defs>
2517
+ <g fill="url(#radialGradient-1)" fill-rule="nonzero" stroke="url(#radialGradient-2)" stroke-width="0.2">
2518
+ <path d="M19.1859205,4.10000004 C19.3691554,4.09993923 19.5526088,4.16602323 19.6925352,4.29904206 C19.8171021,4.41745965 19.8858582,4.56899486 19.8980316,4.7239943 C19.9103475,4.88080848 19.8647874,5.04088037 19.7661957,5.16777131 L19.7661957,5.16777131 L14.3769795,11.1697063 C14.1649599,11.4058657 14.0589501,11.7029328 14.0589501,12 C14.0589501,12.2970672 14.1649599,12.5941343 14.3769795,12.8302937 L14.3769795,12.8302937 L19.6928862,18.7509889 C19.8173649,18.8694879 19.8860087,19.0210672 19.8980683,19.1760728 C19.9102693,19.3328965 19.8645908,19.4929392 19.7701664,19.6153111 C19.6099275,19.772809 19.4324896,19.8610254 19.2586274,19.8856752 C19.0810547,19.910851 18.9081905,19.8692156 18.765363,19.7704965 L18.765363,19.7704965 L11.9999322,13.2904645 L5.32508998,19.6962598 C5.16077108,19.8156635 4.99335965,19.8785989 4.83451361,19.8898888 C4.67442082,19.9012674 4.52389835,19.8596921 4.3968979,19.7731206 C4.23619359,19.588506 4.14871527,19.4164558 4.12392544,19.2589757 C4.09801173,19.094356 4.14341261,18.9485987 4.23380428,18.8322287 L4.23380428,18.8322287 L9.62302046,12.8302937 C9.81773049,12.6134147 9.92302682,12.3451662 9.93892926,12.0727274 C9.95499717,11.7974536 9.87975312,11.5179151 9.70614397,11.2737767 L9.70614397,11.2737767 L4.31595492,5.25860214 C4.17860663,5.08857057 4.11166276,4.9104714 4.11172409,4.7432513 C4.11178577,4.57506821 4.18051603,4.41972395 4.30746483,4.29904206 C4.43371817,4.17902131 4.59543385,4.11349344 4.76041858,4.10187732 L4.76041858,4.10187732 L12.0000677,10.7085251 L18.6794563,4.29937602 C18.8192839,4.16626546 19.0026873,4.10006086 19.1859205,4.10000004 Z" id="形状结合"></path>
2519
+ </g>
2520
+ </svg>
2521
+ `;
2522
+ var mobileHTMLString = `
2523
+ <style>
2524
+ .mobile .fpm__exit {
2525
+ position: absolute;
2526
+ top: 53px;
2527
+ left: 16px;
2528
+ width: 24px;
2529
+ height: 24px;
2530
+ z-index: 10;
2531
+ pointer-events: all;
2532
+ }
2533
+ .mobile .fpm__exit-icon {
2534
+ width: 100%;
2535
+ height: 100%;
2536
+ cursor: pointer;
2537
+ }
2538
+ .fpm_operating--mobile {
2539
+ padding-bottom: 23px;
2540
+ }
2541
+ .fpm__main-btn {
2542
+ display: flex;
2543
+ justify-content: center;
2544
+ align-items: center;
2545
+ margin: 0 !important;
2546
+ }
2547
+ .fpm__main-btn-text {
2548
+ position: absolute;
2549
+ font-weight: 500;
2550
+ font-size: 14px;
2551
+ color: #FFFFFF;
2552
+ text-align: center;
2553
+ text-shadow: 0 2px 8px rgba(0,0,0,0.50);
2554
+ transition: all 200ms ease-in-out;
2555
+ }
2556
+ .fpm__main-text__hide {
2557
+ transform: scale(0.8) translateY(4px);
2558
+ opacity: 0;
2559
+ }
2560
+ .fpm__main-text__show {
2561
+ transform: scale(1) translateY(0);
2562
+ opacity: 1;
2563
+ }
2564
+ .fpm__main__start {
2565
+ background-image: url(${startIconImage});
2566
+ }
2567
+ .fpm__main__end {
2568
+ background-image: url(${endIconImage});
2569
+ }
2570
+
2571
+ </style>
2572
+ <div class="fpm__exit">
2573
+ ${exitIconSvg}
2574
+ </div>
2575
+ <div class="fpm_ui-bg"></div>
2576
+ <div class="fpm_operating-space fpm_operating--mobile">
2577
+ <div class="fpm__main fpm__main-btn">
2578
+ <div class="fpm__main-icon fpm__main__start"></div>
2579
+ <div class="fpm__main-text fpm__main-btn-text">开始</div>
2580
+ </div>
2581
+ </div>
2582
+ `;
2583
+
2584
+ const uiWrapperStyle = {
2585
+ display: 'none',
2586
+ position: 'absolute',
2587
+ top: '0',
2588
+ left: '0',
2589
+ width: '100%',
2590
+ height: '100%',
2591
+ opacity: '0',
2592
+ transform: 'translate(0, 10px)',
2593
+ transition: 'opacity 500ms ease-in-out, transform 500ms ease-in-out',
2594
+ };
2595
+ const operatingSpaceStyle = {
2596
+ position: 'absolute',
2597
+ left: '50%',
2598
+ bottom: '32px',
2599
+ transform: 'translateX(-50%)',
2600
+ height: '89px',
2601
+ display: 'flex',
2602
+ justifyContent: 'space-between',
2603
+ fontSize: '16px',
2604
+ pointerEvents: 'all',
2605
+ color: '#fff',
2606
+ zIndex: '10',
2607
+ };
2608
+ const buttonGroupStyle = {
2609
+ height: '100%',
2610
+ width: 'max-content',
2611
+ display: 'flex',
2612
+ flexDirection: 'column',
2613
+ justifyContent: 'space-between',
2614
+ alignItems: 'center',
2615
+ };
2616
+ // 操作区下方的背景
2617
+ const controllerBackgroundStyle = {
2618
+ position: 'absolute',
2619
+ bottom: '0',
2620
+ left: '0',
2621
+ opacity: '0.5',
2622
+ width: '100%',
2623
+ height: '184px',
2624
+ background: `linear-gradient(180deg, rgba(0,0,0,0.00) 0%, #000000 100%)`,
2625
+ zIndex: '0',
2626
+ };
2627
+ // item
2628
+ const mainItemStyle = {
2629
+ margin: '0 80px',
2630
+ opacity: '0.7',
2631
+ };
2632
+ const newMainItemStyle = {
2633
+ margin: '0 80px',
2634
+ };
2635
+ const exitItemStyle = {
2636
+ opacity: '0.7',
2637
+ };
2638
+ // icon
2639
+ const mainIconStyle = {
2640
+ width: '60px',
2641
+ height: '60px',
2642
+ backgroundSize: '100%',
2643
+ cursor: 'pointer',
2644
+ };
2645
+ const newMainIconStyle = {
2646
+ width: '72px',
2647
+ height: '72px',
2648
+ backgroundSize: '100%',
2649
+ cursor: 'pointer',
2650
+ transition: 'all 200ms ease-in-out',
2651
+ };
2652
+ const exitIconStyle = {
2653
+ width: '40px',
2654
+ height: '40px',
2655
+ marginTop: '10px',
2656
+ backgroundSize: '100%',
2657
+ cursor: 'pointer',
2658
+ };
2659
+ // text
2660
+ const textStyle = {
2661
+ cursor: 'default',
2662
+ userSelect: 'none',
2663
+ };
2664
+
2665
+ const _requestAnimationFrame = window.requestAnimationFrame || ((fn) => setTimeout(fn, 16));
2666
+ const _cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
2667
+ /**
2668
+ * 在每个 AnimationFrame 中调用传入的函数
2669
+ * @param callback 每次 AnimationFrame 中调用的函数
2670
+ * @param frame 每秒运行多少次
2671
+ * @returns 返回一个函数,调用可以停止 AnimationFrameLoop
2672
+ */
2673
+ function requestAnimationFrameInterval(callback, frame = 60) {
2674
+ let index = -1;
2675
+ let oldTime = 0;
2676
+ let startTime = -1;
2677
+ const minDeltaTime = 1000 / frame;
2678
+ function loop(time) {
2679
+ startTime === -1 && (startTime = time);
2680
+ index = _requestAnimationFrame(loop);
2681
+ const deltaTime = time - oldTime;
2682
+ if (deltaTime < minDeltaTime)
2683
+ return;
2684
+ oldTime = time;
2685
+ callback && callback(time - startTime);
2686
+ }
2687
+ index = _requestAnimationFrame(loop);
2688
+ return function stop() {
2689
+ _cancelAnimationFrame(index);
2690
+ };
2691
+ }
2692
+ // export { Easing } from './tween'
2693
+ // export { default as tween } from './tween'
2694
+
2695
+ class BetterTween extends TWEEN__default["default"].Tween {
2696
+ constructor() {
2697
+ super(...arguments);
2698
+ Object.defineProperty(this, "disposeMethods", {
2699
+ enumerable: true,
2700
+ configurable: true,
2701
+ writable: true,
2702
+ value: []
2703
+ });
2704
+ Object.defineProperty(this, "animationFrameDisposer", {
2705
+ enumerable: true,
2706
+ configurable: true,
2707
+ writable: true,
2708
+ value: void 0
2709
+ });
2710
+ Object.defineProperty(this, "onDispose", {
2711
+ enumerable: true,
2712
+ configurable: true,
2713
+ writable: true,
2714
+ value: (callback) => {
2715
+ this.disposeMethods.push(callback);
2716
+ return this;
2717
+ }
2718
+ });
2719
+ Object.defineProperty(this, "play", {
2720
+ enumerable: true,
2721
+ configurable: true,
2722
+ writable: true,
2723
+ value: () => {
2724
+ this.start(0);
2725
+ this.animationFrameDisposer = requestAnimationFrameInterval((time) => this.update(time));
2726
+ return this;
2727
+ }
2728
+ });
2729
+ Object.defineProperty(this, "dispose", {
2730
+ enumerable: true,
2731
+ configurable: true,
2732
+ writable: true,
2733
+ value: () => {
2734
+ var _a;
2735
+ this.stop();
2736
+ (_a = this.animationFrameDisposer) === null || _a === void 0 ? void 0 : _a.call(this);
2737
+ this.disposeMethods.forEach((fn) => fn());
2738
+ this.disposeMethods = [];
2739
+ TWEEN__default["default"].remove(this);
2740
+ }
2741
+ });
2742
+ }
2743
+ }
2744
+ function tweenProgress(duration, easing = TWEEN__default["default"].Easing.Linear.None) {
2745
+ const tween = new BetterTween({ progress: 0 }).to({ progress: 1 });
2746
+ if (duration !== undefined)
2747
+ tween.duration(duration);
2748
+ if (easing !== undefined)
2749
+ tween.easing(easing);
2750
+ return tween;
2751
+ }
2752
+
2753
+ class MainBtnController {
2754
+ constructor(measureController, container) {
2755
+ Object.defineProperty(this, "container", {
2756
+ enumerable: true,
2757
+ configurable: true,
2758
+ writable: true,
2759
+ value: void 0
2760
+ });
2761
+ Object.defineProperty(this, "measureController", {
2762
+ enumerable: true,
2763
+ configurable: true,
2764
+ writable: true,
2765
+ value: void 0
2766
+ });
2767
+ Object.defineProperty(this, "mainIconMaskTween", {
2768
+ enumerable: true,
2769
+ configurable: true,
2770
+ writable: true,
2771
+ value: void 0
2772
+ });
2773
+ Object.defineProperty(this, "mainElement", {
2774
+ enumerable: true,
2775
+ configurable: true,
2776
+ writable: true,
2777
+ value: void 0
2778
+ });
2779
+ /* 鼠标移入时变成蓝色 */
2780
+ Object.defineProperty(this, "onMouseEnter", {
2781
+ enumerable: true,
2782
+ configurable: true,
2783
+ writable: true,
2784
+ value: () => {
2785
+ const { mainItem, pathDom } = this.mainElement;
2786
+ mainItem.style.opacity = '1';
2787
+ pathDom.setAttribute('fill', MAIN_MOUSE_ENTER_FILL);
2788
+ }
2789
+ });
2790
+ /* 鼠标移出时变成灰色 */
2791
+ Object.defineProperty(this, "onMouseLeave", {
2792
+ enumerable: true,
2793
+ configurable: true,
2794
+ writable: true,
2795
+ value: () => {
2796
+ const { mainItem, pathDom } = this.mainElement;
2797
+ mainItem.style.opacity = '0.7';
2798
+ pathDom.setAttribute('fill', MAIN_MOUSE_LEAVE_FILL);
2799
+ }
2800
+ });
2801
+ Object.defineProperty(this, "onClick", {
2802
+ enumerable: true,
2803
+ configurable: true,
2804
+ writable: true,
2805
+ value: () => {
2806
+ const mode = this.measureController.getCurrentMode();
2807
+ mode === 'Watch' ? this.measureController.changeMode('Edit') : this.measureController.save().changeMode('Watch');
2808
+ }
2809
+ });
2810
+ Object.defineProperty(this, "editedLineChangeHandler", {
2811
+ enumerable: true,
2812
+ configurable: true,
2813
+ writable: true,
2814
+ value: (lines) => {
2815
+ // 线的数量大于 1 时,没有状态的变化
2816
+ if (lines.length > 1)
2817
+ return;
2818
+ // 因为撤销导致的状态变更 -> 取消
2819
+ if (lines.length === 0)
2820
+ return this.change2Cancel(false);
2821
+ this.change2Done();
2822
+ }
2823
+ });
2824
+ Object.defineProperty(this, "modeChangeHandler", {
2825
+ enumerable: true,
2826
+ configurable: true,
2827
+ writable: true,
2828
+ value: (mode) => {
2829
+ mode === 'Watch' ? this.change2Add() : this.change2Cancel();
2830
+ }
2831
+ });
2832
+ this.measureController = measureController;
2833
+ this.container = container;
2834
+ this.mainElement = this.getMainElement();
2835
+ Object.assign(this.mainElement.mainIcon.style, mainIconStyle);
2836
+ Object.assign(this.mainElement.mainItem.style, mainItemStyle);
2837
+ this.change2Add();
2838
+ this.measureController.hook.on('modeChange', this.modeChangeHandler);
2839
+ this.mainElement.mainIcon.addEventListener('click', this.onClick);
2840
+ this.mainElement.mainIcon.addEventListener('mouseenter', this.onMouseEnter);
2841
+ this.mainElement.mainIcon.addEventListener('mouseleave', this.onMouseLeave);
2842
+ }
2843
+ dispose() {
2844
+ this.measureController.hook.off('modeChange', this.modeChangeHandler);
2845
+ this.measureController.hook.off('editedLineChange', this.editedLineChangeHandler);
2846
+ this.mainElement.mainIcon.removeEventListener('click', this.onClick);
2847
+ this.mainElement.mainIcon.removeEventListener('mouseenter', this.onMouseEnter);
2848
+ this.mainElement.mainIcon.removeEventListener('mouseleave', this.onMouseLeave);
2849
+ }
2850
+ getMainElement() {
2851
+ const mainTextDom = this.container.querySelector('.fpm__main-text');
2852
+ const mainItem = this.container.querySelector('.fpm__main');
2853
+ const mainIcon = this.container.querySelector('.fpm__main-icon');
2854
+ const pathDom = mainItem === null || mainItem === void 0 ? void 0 : mainItem.querySelector('.fpm__main-icon-path');
2855
+ const maskWhiteRect = mainIcon === null || mainIcon === void 0 ? void 0 : mainIcon.querySelector('#fpm__main-icon-mask-white');
2856
+ if (!mainItem || !mainTextDom || !mainIcon || !pathDom || !maskWhiteRect)
2857
+ throw new Error('cannot find dom');
2858
+ return { mainTextDom, mainItem, mainIcon, pathDom, maskWhiteRect };
2859
+ }
2860
+ change2Add() {
2861
+ this.measureController.hook.off('editedLineChange', this.editedLineChangeHandler);
2862
+ const { mainIcon, mainTextDom, pathDom } = this.mainElement;
2863
+ mainIcon.style.transition = mainTextDom.innerText === '完成' ? 'none' : 'transform 300ms ease-in-out';
2864
+ mainIcon.style.transform = 'rotate(0deg)';
2865
+ mainTextDom.innerText = '添加';
2866
+ pathDom === null || pathDom === void 0 ? void 0 : pathDom.setAttribute('d', MAIN_NORMAL_PATH);
2867
+ }
2868
+ change2Cancel(withAnime = true) {
2869
+ const { mainIcon, mainTextDom, pathDom } = this.mainElement;
2870
+ pathDom.setAttribute('d', MAIN_NORMAL_PATH);
2871
+ pathDom.setAttribute('mask', '');
2872
+ mainIcon.style.transition = withAnime ? 'transform 300ms ease-in-out' : 'none';
2873
+ mainIcon.style.transform = 'rotate(45deg)';
2874
+ mainTextDom && (mainTextDom.innerText = '取消');
2875
+ this.measureController.hook.on('editedLineChange', this.editedLineChangeHandler);
2876
+ }
2877
+ change2Done() {
2878
+ var _a;
2879
+ const { mainTextDom, mainIcon, pathDom, maskWhiteRect } = this.getMainElement();
2880
+ if (mainTextDom.innerText === '完成')
2881
+ return;
2882
+ mainIcon.style.transition = 'none';
2883
+ mainIcon.style.transform = 'rotate(0deg)';
2884
+ mainTextDom.innerText = '完成';
2885
+ pathDom.setAttribute('d', MAIN_DONE_PATH);
2886
+ pathDom.setAttribute('mask', `url(#fpm__main-icon-mask)`);
2887
+ (_a = this.mainIconMaskTween) === null || _a === void 0 ? void 0 : _a.dispose();
2888
+ this.mainIconMaskTween = tweenProgress()
2889
+ .easing(TWEEN__default["default"].Easing.Quartic.InOut)
2890
+ .onUpdate(({ progress }) => {
2891
+ maskWhiteRect.setAttribute('width', (progress * 30).toString());
2892
+ })
2893
+ .onComplete(() => { var _a; return (_a = this.mainIconMaskTween) === null || _a === void 0 ? void 0 : _a.dispose(); })
2894
+ .play();
2895
+ }
2896
+ }
2897
+
2898
+ class NewMainBtnController {
2899
+ constructor(measureController, container) {
2900
+ Object.defineProperty(this, "container", {
2901
+ enumerable: true,
2902
+ configurable: true,
2903
+ writable: true,
2904
+ value: void 0
2905
+ });
2906
+ Object.defineProperty(this, "measureController", {
2907
+ enumerable: true,
2908
+ configurable: true,
2909
+ writable: true,
2910
+ value: void 0
2911
+ });
2912
+ Object.defineProperty(this, "mainElement", {
2913
+ enumerable: true,
2914
+ configurable: true,
2915
+ writable: true,
2916
+ value: void 0
2917
+ });
2918
+ Object.defineProperty(this, "onClick", {
2919
+ enumerable: true,
2920
+ configurable: true,
2921
+ writable: true,
2922
+ value: () => {
2923
+ if (this.mainElement.mainTextDom.innerText === '开始') {
2924
+ this.measureController.hook.emit('willChangeState', 'watching', 'editing');
2925
+ this.change2Done();
2926
+ }
2927
+ else {
2928
+ this.measureController.hook.emit('willChangeState', 'editing', 'watching');
2929
+ this.change2Add();
2930
+ }
2931
+ }
2932
+ });
2933
+ this.measureController = measureController;
2934
+ this.container = container;
2935
+ this.mainElement = this.getMainElement();
2936
+ Object.assign(this.mainElement.mainIcon.style, newMainIconStyle);
2937
+ Object.assign(this.mainElement.mainItem.style, newMainItemStyle);
2938
+ this.change2Add();
2939
+ this.mainElement.mainItem.addEventListener('click', this.onClick);
2940
+ }
2941
+ dispose() {
2942
+ this.mainElement.mainItem.removeEventListener('click', this.onClick);
2943
+ }
2944
+ getMainElement() {
2945
+ const mainTextDom = this.container.querySelector('.fpm__main-text');
2946
+ const mainItem = this.container.querySelector('.fpm__main');
2947
+ const mainIcon = this.container.querySelector('.fpm__main-icon');
2948
+ if (!mainItem || !mainTextDom || !mainIcon)
2949
+ throw new Error('cannot find dom');
2950
+ return { mainTextDom, mainItem, mainIcon };
2951
+ }
2952
+ change2Add() {
2953
+ const { mainIcon, mainTextDom } = this.mainElement;
2954
+ if (mainIcon.className.includes('fpm__main__start'))
2955
+ return;
2956
+ if (mainIcon.className.includes('fpm__main__end')) {
2957
+ mainIcon.style.transform = `scale(0.8)`;
2958
+ if (mainTextDom.className.includes('fpm__main-text__show')) {
2959
+ mainTextDom.classList.replace('fpm__main-text__show', 'fpm__main-text__hide');
2960
+ }
2961
+ else {
2962
+ mainTextDom.classList.add('fpm__main-text__hide');
2963
+ }
2964
+ setTimeout(() => {
2965
+ mainIcon.classList.replace('fpm__main__end', 'fpm__main__start');
2966
+ mainIcon.style.transform = 'scale(1)';
2967
+ mainTextDom.innerText = '开始';
2968
+ mainTextDom.classList.replace('fpm__main-text__hide', 'fpm__main-text__show');
2969
+ }, 200);
2970
+ }
2971
+ }
2972
+ change2Done() {
2973
+ const { mainTextDom, mainIcon } = this.mainElement;
2974
+ if (mainTextDom.innerText === '结束')
2975
+ return;
2976
+ if (mainIcon.className.includes('fpm__main__end'))
2977
+ return;
2978
+ if (mainIcon.className.includes('fpm__main__start')) {
2979
+ mainIcon.style.transform = `scale(0.8)`;
2980
+ if (mainTextDom.className.includes('fpm__main-text__show')) {
2981
+ mainTextDom.classList.replace('fpm__main-text__show', 'fpm__main-text__hide');
2982
+ }
2983
+ else {
2984
+ mainTextDom.classList.add('fpm__main-text__hide');
2985
+ }
2986
+ setTimeout(() => {
2987
+ mainIcon.classList.replace('fpm__main__start', 'fpm__main__end');
2988
+ mainIcon.style.transform = 'scale(1)';
2989
+ mainTextDom.innerText = '结束';
2990
+ mainTextDom.classList.replace('fpm__main-text__hide', 'fpm__main-text__show');
2991
+ }, 200);
2992
+ }
2993
+ }
2994
+ }
2995
+
2996
+ class Revoke {
2997
+ constructor(measureController, container) {
2998
+ Object.defineProperty(this, "container", {
2999
+ enumerable: true,
3000
+ configurable: true,
3001
+ writable: true,
3002
+ value: void 0
3003
+ });
3004
+ Object.defineProperty(this, "revokeIcon", {
3005
+ enumerable: true,
3006
+ configurable: true,
3007
+ writable: true,
3008
+ value: void 0
3009
+ });
3010
+ Object.defineProperty(this, "revokeItem", {
3011
+ enumerable: true,
3012
+ configurable: true,
3013
+ writable: true,
3014
+ value: void 0
3015
+ });
3016
+ Object.defineProperty(this, "measureController", {
3017
+ enumerable: true,
3018
+ configurable: true,
3019
+ writable: true,
3020
+ value: void 0
3021
+ });
3022
+ Object.defineProperty(this, "onClick", {
3023
+ enumerable: true,
3024
+ configurable: true,
3025
+ writable: true,
3026
+ value: () => {
3027
+ this.measureController.revoke();
3028
+ }
3029
+ });
3030
+ Object.defineProperty(this, "onModeChange", {
3031
+ enumerable: true,
3032
+ configurable: true,
3033
+ writable: true,
3034
+ value: (mode) => {
3035
+ if (mode !== 'Edit') {
3036
+ this.revokeItem.classList.remove('enabled');
3037
+ return;
3038
+ }
3039
+ this.revokeItem.classList.add('enabled');
3040
+ }
3041
+ });
3042
+ Object.defineProperty(this, "handleRevoke", {
3043
+ enumerable: true,
3044
+ configurable: true,
3045
+ writable: true,
3046
+ value: () => {
3047
+ return () => { };
3048
+ }
3049
+ });
3050
+ this.measureController = measureController;
3051
+ this.container = container;
3052
+ const revokeIcon = this.container.querySelector('.fpm__revoke-icon');
3053
+ const revokeItem = this.container.querySelector('.fpm__revoke');
3054
+ if (!revokeIcon || !revokeItem)
3055
+ throw new Error('不正确的选择器');
3056
+ this.revokeIcon = revokeIcon;
3057
+ this.revokeItem = revokeItem;
3058
+ this.revokeIcon.addEventListener('click', this.onClick);
3059
+ measureController.hook.on('modeChange', this.onModeChange);
3060
+ }
3061
+ dispose() {
3062
+ this.revokeIcon.removeEventListener('click', this.onClick);
3063
+ this.measureController.hook.off('modeChange', this.onModeChange);
3064
+ }
3065
+ }
3066
+
3067
+ class UIController {
3068
+ constructor(measureController, params) {
3069
+ var _a, _b;
3070
+ Object.defineProperty(this, "revoke", {
3071
+ enumerable: true,
3072
+ configurable: true,
3073
+ writable: true,
3074
+ value: void 0
3075
+ });
3076
+ Object.defineProperty(this, "container", {
3077
+ enumerable: true,
3078
+ configurable: true,
3079
+ writable: true,
3080
+ value: void 0
3081
+ });
3082
+ Object.defineProperty(this, "mainController", {
3083
+ enumerable: true,
3084
+ configurable: true,
3085
+ writable: true,
3086
+ value: void 0
3087
+ });
3088
+ Object.defineProperty(this, "disposers", {
3089
+ enumerable: true,
3090
+ configurable: true,
3091
+ writable: true,
3092
+ value: []
3093
+ });
3094
+ Object.defineProperty(this, "measureController", {
3095
+ enumerable: true,
3096
+ configurable: true,
3097
+ writable: true,
3098
+ value: void 0
3099
+ });
3100
+ Object.defineProperty(this, "mode", {
3101
+ enumerable: true,
3102
+ configurable: true,
3103
+ writable: true,
3104
+ value: void 0
3105
+ });
3106
+ Object.defineProperty(this, "handleExit", {
3107
+ enumerable: true,
3108
+ configurable: true,
3109
+ writable: true,
3110
+ value: () => {
3111
+ const exitIcon = this.container.querySelector('.fpm__exit-icon');
3112
+ const exitItem = this.container.querySelector('.fpm__exit');
3113
+ if (!exitItem || !exitIcon)
3114
+ throw new Error('cannot find dom');
3115
+ if (this.mode === 'pc') {
3116
+ Object.assign(exitItem.style, exitItemStyle);
3117
+ Object.assign(exitIcon === null || exitIcon === void 0 ? void 0 : exitIcon.style, exitIconStyle);
3118
+ }
3119
+ const onMouseEnter = () => (exitItem.style.opacity = '1');
3120
+ const onMouseLeave = () => (exitItem.style.opacity = '0.7');
3121
+ const handleClick = () => {
3122
+ this.measureController.disable();
3123
+ };
3124
+ exitIcon.addEventListener('click', handleClick);
3125
+ exitIcon.addEventListener('mouseenter', onMouseEnter);
3126
+ exitIcon.addEventListener('mouseleave', onMouseLeave);
3127
+ return () => {
3128
+ exitIcon.removeEventListener('click', handleClick);
3129
+ exitIcon.removeEventListener('mouseenter', onMouseEnter);
3130
+ exitIcon.removeEventListener('mouseleave', onMouseLeave);
3131
+ };
3132
+ }
3133
+ });
3134
+ this.measureController = measureController;
3135
+ this.mode = ((_a = params.openParams) === null || _a === void 0 ? void 0 : _a.isMobile) ? 'mobile' : 'pc';
3136
+ this.container = document.createElement('div');
3137
+ this.container.innerHTML = ((_b = params.openParams) === null || _b === void 0 ? void 0 : _b.isMobile) ? mobileHTMLString : htmlString$1;
3138
+ this.container.classList.add('fpm__ui-controller', this.mode);
3139
+ params.container.appendChild(this.container);
3140
+ const textDoms = this.container.querySelectorAll('.fpm__text');
3141
+ const UIItems = this.container.querySelectorAll('.fpm__ui-item');
3142
+ const bgDom = this.container.querySelector('.fpm_ui-bg');
3143
+ const operatingSpaceDom = this.container.querySelector('.fpm_operating-space');
3144
+ Object.assign(bgDom === null || bgDom === void 0 ? void 0 : bgDom.style, controllerBackgroundStyle);
3145
+ Object.assign(operatingSpaceDom === null || operatingSpaceDom === void 0 ? void 0 : operatingSpaceDom.style, operatingSpaceStyle);
3146
+ Object.assign(this.container.style, uiWrapperStyle);
3147
+ UIItems.forEach((item) => Object.assign(item.style, buttonGroupStyle));
3148
+ textDoms.forEach((item) => Object.assign(item.style, textStyle));
3149
+ }
3150
+ dispose() {
3151
+ this.hide();
3152
+ this.container.remove();
3153
+ }
3154
+ show() {
3155
+ this.container.style.display = 'block';
3156
+ this.container.style.opacity = '1';
3157
+ this.container.style.transform = 'translate(0, 0)';
3158
+ if (this.mode === 'pc') {
3159
+ this.revoke = new Revoke(this.measureController, this.container);
3160
+ this.mainController = new MainBtnController(this.measureController, this.container);
3161
+ }
3162
+ else {
3163
+ this.mainController = new NewMainBtnController(this.measureController, this.container);
3164
+ }
3165
+ this.disposers.push(this.handleExit());
3166
+ return this;
3167
+ }
3168
+ hide() {
3169
+ var _a, _b;
3170
+ this.container.style.display = 'none';
3171
+ this.container.style.opacity = '0';
3172
+ this.container.style.transform = 'translate(0, 10px)';
3173
+ this.mode === 'pc' && ((_a = this.revoke) === null || _a === void 0 ? void 0 : _a.dispose());
3174
+ (_b = this.mainController) === null || _b === void 0 ? void 0 : _b.dispose();
3175
+ this.disposers.forEach((disposer) => disposer());
3176
+ this.disposers = [];
3177
+ return this;
3178
+ }
3179
+ }
3180
+
3181
+ class GuideController {
3182
+ constructor(measureController, params) {
3183
+ Object.defineProperty(this, "measureController", {
3184
+ enumerable: true,
3185
+ configurable: true,
3186
+ writable: true,
3187
+ value: void 0
3188
+ });
3189
+ Object.defineProperty(this, "textDom", {
3190
+ enumerable: true,
3191
+ configurable: true,
3192
+ writable: true,
3193
+ value: document.createElement('span')
3194
+ });
3195
+ Object.defineProperty(this, "container", {
3196
+ enumerable: true,
3197
+ configurable: true,
3198
+ writable: true,
3199
+ value: document.createElement('div')
3200
+ });
3201
+ Object.defineProperty(this, "hasAnchor", {
3202
+ enumerable: true,
3203
+ configurable: true,
3204
+ writable: true,
3205
+ value: false
3206
+ });
3207
+ Object.defineProperty(this, "onModelChange", {
3208
+ enumerable: true,
3209
+ configurable: true,
3210
+ writable: true,
3211
+ value: (mode) => {
3212
+ if (mode === 'Watch') {
3213
+ this.textDom.innerText = ``;
3214
+ return;
3215
+ }
3216
+ this.textDom.innerText = `请选择第一个测量点,Esc或单击鼠标右键可取消选择`;
3217
+ }
3218
+ });
3219
+ Object.defineProperty(this, "anchorChange", {
3220
+ enumerable: true,
3221
+ configurable: true,
3222
+ writable: true,
3223
+ value: (anchor) => {
3224
+ if (!this.hasAnchor && !!anchor) {
3225
+ this.hasAnchor = true;
3226
+ this.textDom.innerText = `选择下一个测量点,Esc或单击鼠标右键取消选择`;
3227
+ }
3228
+ else if (!anchor) {
3229
+ this.hasAnchor = false;
3230
+ this.textDom.innerText = `请选择第一个测量点,Esc或单击鼠标右键可取消选择`;
3231
+ }
3232
+ }
3233
+ });
3234
+ Object.defineProperty(this, "onEditedLineChange", {
3235
+ enumerable: true,
3236
+ configurable: true,
3237
+ writable: true,
3238
+ value: (lines) => {
3239
+ if (lines.length === 1) {
3240
+ this.textDom.innerText = `可以连续选择测量点,或点击下方“完成”结束测量(Esc取消,Command+S保存)`;
3241
+ }
3242
+ }
3243
+ });
3244
+ this.initDom();
3245
+ params.container.append(this.container);
3246
+ this.measureController = measureController;
3247
+ measureController.hook.on('modeChange', this.onModelChange);
3248
+ measureController.hook.on('anchorChange', this.anchorChange);
3249
+ measureController.hook.on('editedLineChange', this.onEditedLineChange);
3250
+ }
3251
+ dispose() {
3252
+ this.hide();
3253
+ this.container.remove();
3254
+ }
3255
+ show() {
3256
+ this.container.style.opacity = '1';
3257
+ this.container.style.transform = 'translate(0, 0)';
3258
+ return this;
3259
+ }
3260
+ hide() {
3261
+ this.container.style.opacity = '0';
3262
+ this.container.style.transform = 'translate(0, -10px)';
3263
+ this.measureController.hook.off('modeChange', this.onModelChange);
3264
+ this.measureController.hook.off('anchorChange', this.anchorChange);
3265
+ this.measureController.hook.off('editedLineChange', this.onEditedLineChange);
3266
+ return this;
3267
+ }
3268
+ initDom() {
3269
+ const container = this.container;
3270
+ const textDom = this.textDom;
3271
+ container.classList.add('fpm__guide-container');
3272
+ container.style.position = 'absolute';
3273
+ container.style.top = '0px';
3274
+ container.style.left = '0px';
3275
+ container.style.width = '100%';
3276
+ container.style.height = '110px';
3277
+ container.style.display = 'flex';
3278
+ container.style.alignItems = 'center';
3279
+ container.style.justifyContent = 'center';
3280
+ container.style.transform = 'translate(0, -10px)';
3281
+ container.style.background = `linear-gradient(180deg, rgba(0,0,0,0.40) 0%, rgba(0,0,0,0.00) 100%)`;
3282
+ container.style.transition = 'opacity 500ms ease-in-out, transform 500ms ease-in-out';
3283
+ container.style.opacity = '0';
3284
+ textDom.classList.add('fpm__guide-text');
3285
+ textDom.style.color = '#fff';
3286
+ textDom.style.fontSize = '20px';
3287
+ textDom.innerText = `点击下方“添加”开始测距`;
3288
+ container.appendChild(textDom);
3289
+ }
3290
+ }
3291
+
3292
+ /** 快捷键控制器 */
3293
+ class ShortcutKeyController {
3294
+ constructor(measureController, five) {
3295
+ Object.defineProperty(this, "five", {
3296
+ enumerable: true,
3297
+ configurable: true,
3298
+ writable: true,
3299
+ value: void 0
3300
+ });
3301
+ Object.defineProperty(this, "measureController", {
3302
+ enumerable: true,
3303
+ configurable: true,
3304
+ writable: true,
3305
+ value: void 0
3306
+ });
3307
+ Object.defineProperty(this, "onKeyDown", {
3308
+ enumerable: true,
3309
+ configurable: true,
3310
+ writable: true,
3311
+ value: (e) => {
3312
+ // Command + S -> 保存 & 更改场景
3313
+ if (e.metaKey && e.code === 'KeyS') {
3314
+ this.measureController.save().changeMode('Watch');
3315
+ e.preventDefault();
3316
+ return;
3317
+ }
3318
+ // Escape -> 切换到观察模式 / 如果已经在观察模式,退出功能
3319
+ if (e.code === 'Escape')
3320
+ return this.escape();
3321
+ }
3322
+ });
3323
+ Object.defineProperty(this, "onMouseDown", {
3324
+ enumerable: true,
3325
+ configurable: true,
3326
+ writable: true,
3327
+ value: (e) => {
3328
+ // 鼠标右键取消
3329
+ if (e.button !== 2)
3330
+ return;
3331
+ e.preventDefault();
3332
+ this.escape();
3333
+ }
3334
+ });
3335
+ this.five = five;
3336
+ this.measureController = measureController;
3337
+ const fiveElement = this.five.getElement();
3338
+ if (!fiveElement)
3339
+ return;
3340
+ document.body.addEventListener('keydown', this.onKeyDown);
3341
+ fiveElement.addEventListener('mousedown', this.onMouseDown);
3342
+ }
3343
+ dispose() {
3344
+ const fiveElement = this.five.getElement();
3345
+ if (!fiveElement)
3346
+ return;
3347
+ document.body.removeEventListener('keydown', this.onKeyDown);
3348
+ fiveElement.removeEventListener('mousedown', this.onMouseDown);
3349
+ }
3350
+ escape() {
3351
+ if (this.measureController.getCurrentMode() === 'Watch')
3352
+ return this.measureController.disable();
3353
+ return this.measureController.changeMode('Watch');
3354
+ }
3355
+ }
3356
+
3357
+ const rangePieceImg = 'data:image/png;base64,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';
3358
+ const rangePieceIntersectImg = 'data:image/png;base64,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';
3359
+ var htmlString = `
3360
+ <style>
3361
+ .range-piece__container {
3362
+ position: absolute;
3363
+ top: 39%;
3364
+ left: 50%;
3365
+ margin-left: -54px;
3366
+ width: 108px;
3367
+ height: 108px;
3368
+ display: flex;
3369
+ align-items: center;
3370
+ justify-content: center;
3371
+ animation: pieceContainer 0.3s ease-in-out;
3372
+ animation-fill-mode: forwards;
3373
+ }
3374
+ .range-piece__content {
3375
+ width: 100%;
3376
+ height: 100%;
3377
+ background-image: url(${rangePieceImg});
3378
+ opacity: 0.4;
3379
+ background-size: 100%;
3380
+ background-repeat: no-repeat;
3381
+ transition: linear transform 0.1s;
3382
+ }
3383
+ .range-piece__content--active {
3384
+ animation: dotting ease-in-out 0.5s;
3385
+ }
3386
+ .range-piece__aim {
3387
+ width: 100%;
3388
+ height: 100%;
3389
+ opacity: 1;
3390
+ position: absolute;
3391
+ background: url(${rangePieceIntersectImg}) center / contain no-repeat;
3392
+ }
3393
+ @keyframes dotting {
3394
+ 0% {
3395
+ opacity: 0.4;
3396
+ transform: scale(1);
3397
+ }
3398
+ 50% {
3399
+ opacity: 1;
3400
+ transform: scale(0.8);
3401
+ }
3402
+ 100% {
3403
+ opacity: 0.4;
3404
+ transform: scale(1);
3405
+ }
3406
+ }
3407
+ @keyframes pieceContainer {
3408
+ from {
3409
+ top: 49%;
3410
+ }
3411
+ to {
3412
+ top: 39%;
3413
+ }
3414
+ }
3415
+ </style>
3416
+ <div class="range-piece__container">
3417
+ <div class='range-piece__content'></div>
3418
+ <div class="range-piece__aim"></div>
3419
+ </div>
3420
+ `;
3421
+
3422
+ function noop() {
3423
+ return void 0;
3424
+ }
3425
+
3426
+ const { Vector2 } = THREE__namespace;
3427
+ /**
3428
+ * 计算 three 中的 mouse 的值
3429
+ * @param {{x:Number, y:Number}} mouseXY 鼠标相对屏幕位置
3430
+ * @param {Element} element canvas元素(three的展示元素)
3431
+ */
3432
+ function calculateThreeMouse(mouseXY, element) {
3433
+ const { offsetWidth: width, offsetHeight: height } = element;
3434
+ const { top, left } = element.getBoundingClientRect();
3435
+ return Object.assign(new Vector2(), {
3436
+ x: ((mouseXY.x - left) / width) * 2 - 1,
3437
+ y: (-(mouseXY.y - top) / height) * 2 + 1,
3438
+ });
3439
+ }
3440
+
3441
+ class RangePieceController {
3442
+ // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
3443
+ constructor(params) {
3444
+ Object.defineProperty(this, "container", {
3445
+ enumerable: true,
3446
+ configurable: true,
3447
+ writable: true,
3448
+ value: document.createElement('div')
3449
+ });
3450
+ Object.defineProperty(this, "five", {
3451
+ enumerable: true,
3452
+ configurable: true,
3453
+ writable: true,
3454
+ value: void 0
3455
+ });
3456
+ Object.defineProperty(this, "group", {
3457
+ enumerable: true,
3458
+ configurable: true,
3459
+ writable: true,
3460
+ value: void 0
3461
+ });
3462
+ Object.defineProperty(this, "mouseGroup", {
3463
+ enumerable: true,
3464
+ configurable: true,
3465
+ writable: true,
3466
+ value: void 0
3467
+ });
3468
+ Object.defineProperty(this, "hasAppendMouseGroup", {
3469
+ enumerable: true,
3470
+ configurable: true,
3471
+ writable: true,
3472
+ value: false
3473
+ });
3474
+ Object.defineProperty(this, "fiveHelper", {
3475
+ enumerable: true,
3476
+ configurable: true,
3477
+ writable: true,
3478
+ value: void 0
3479
+ });
3480
+ Object.defineProperty(this, "hook", {
3481
+ enumerable: true,
3482
+ configurable: true,
3483
+ writable: true,
3484
+ value: void 0
3485
+ });
3486
+ Object.defineProperty(this, "content", {
3487
+ enumerable: true,
3488
+ configurable: true,
3489
+ writable: true,
3490
+ value: void 0
3491
+ });
3492
+ Object.defineProperty(this, "intersectMesh", {
3493
+ enumerable: true,
3494
+ configurable: true,
3495
+ writable: true,
3496
+ value: void 0
3497
+ });
3498
+ Object.defineProperty(this, "centerMouseXY", {
3499
+ enumerable: true,
3500
+ configurable: true,
3501
+ writable: true,
3502
+ value: void 0
3503
+ });
3504
+ Object.defineProperty(this, "raycaster", {
3505
+ enumerable: true,
3506
+ configurable: true,
3507
+ writable: true,
3508
+ value: new THREE.Raycaster()
3509
+ });
3510
+ Object.defineProperty(this, "pieceStyl", {
3511
+ enumerable: true,
3512
+ configurable: true,
3513
+ writable: true,
3514
+ value: {
3515
+ matrix3d: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
3516
+ scale: 1,
3517
+ opacity: 0.4,
3518
+ }
3519
+ });
3520
+ Object.defineProperty(this, "onCameraDirectionUpdate", {
3521
+ enumerable: true,
3522
+ configurable: true,
3523
+ writable: true,
3524
+ value: () => {
3525
+ const intersection = this.getIntersection();
3526
+ if (intersection) {
3527
+ this.pieceChange(intersection);
3528
+ this.updateMouseGroup(intersection);
3529
+ const nowPoint = new Point(this.mouseGroup.position);
3530
+ this.hook.emit('nowPointChange', nowPoint);
3531
+ }
3532
+ }
3533
+ });
3534
+ Object.defineProperty(this, "onWillChangeState", {
3535
+ enumerable: true,
3536
+ configurable: true,
3537
+ writable: true,
3538
+ value: (state, newState) => {
3539
+ var _a;
3540
+ this.dotAnimation();
3541
+ const point = (_a = this.getIntersection()) === null || _a === void 0 ? void 0 : _a.point;
3542
+ if (!point)
3543
+ return;
3544
+ if (newState === 'editing') {
3545
+ this.hook.emit('getStartPoint', new Point(point));
3546
+ }
3547
+ else {
3548
+ this.hook.emit('getEndPoint', new Point(point));
3549
+ }
3550
+ }
3551
+ });
3552
+ /** 计算目标中心点经纬度 */
3553
+ Object.defineProperty(this, "computedCenterMouseXY", {
3554
+ enumerable: true,
3555
+ configurable: true,
3556
+ writable: true,
3557
+ value: () => {
3558
+ const aimRef = this.container.querySelector('.range-piece__aim');
3559
+ if (!aimRef)
3560
+ return null;
3561
+ const { left, top, width, height } = aimRef.getBoundingClientRect();
3562
+ const mouseX = Math.round(left + width / 2);
3563
+ const mouseY = Math.round(top + height / 2);
3564
+ const mouse = { x: mouseX, y: mouseY };
3565
+ const mouseXY = calculateThreeMouse(mouse, this.five.getElement()); // 经纬度
3566
+ this.centerMouseXY = mouseXY;
3567
+ }
3568
+ });
3569
+ /** 计算目标中心点intersection */
3570
+ Object.defineProperty(this, "getIntersection", {
3571
+ enumerable: true,
3572
+ configurable: true,
3573
+ writable: true,
3574
+ value: () => {
3575
+ if (!this.centerMouseXY)
3576
+ return null;
3577
+ this.raycaster.setFromCamera(this.centerMouseXY, this.five.camera);
3578
+ const intersection = this.five.model.intersectRaycaster(this.raycaster)[0];
3579
+ if (intersection)
3580
+ return intersection;
3581
+ else
3582
+ return null;
3583
+ }
3584
+ });
3585
+ this.five = params.five;
3586
+ this.hook = params.hook;
3587
+ this.group = params.group;
3588
+ this.mouseGroup = getMouseGroup();
3589
+ this.fiveHelper = params.fiveHelper;
3590
+ this.container.innerHTML = htmlString;
3591
+ this.container.classList.add('range-piece-controller');
3592
+ this.content = this.container.querySelector('.range-piece__content');
3593
+ if (this.content) {
3594
+ this.content.style.transform = `matrix3d(${this.pieceStyl.matrix3d.toString()}) scale(${this.pieceStyl.scale})`;
3595
+ this.content.style.opacity = `${this.pieceStyl.opacity}`;
3596
+ }
3597
+ params.container.append(this.container);
3598
+ this.intersectMesh = new THREE.Mesh(new THREE.RingGeometry(0.04, 0.08, 32), new THREE.MeshBasicMaterial({ color: 0x12fffb, opacity: 0, side: THREE.DoubleSide, transparent: true }));
3599
+ this.container.addEventListener('animationend', this.computedCenterMouseXY);
3600
+ this.five.on('cameraUpdate', this.onCameraDirectionUpdate);
3601
+ this.hook.on('willChangeState', this.onWillChangeState);
3602
+ }
3603
+ dispose() {
3604
+ this.container.removeEventListener('animationend', this.computedCenterMouseXY);
3605
+ this.five.off('cameraUpdate', this.onCameraDirectionUpdate);
3606
+ this.hook.off('willChangeState', this.onWillChangeState);
3607
+ this.container.remove();
3608
+ this.group.remove(this.mouseGroup);
3609
+ this.mouseGroup.remove();
3610
+ this.hasAppendMouseGroup = false;
3611
+ this.five.scene.remove(this.intersectMesh);
3612
+ }
3613
+ pieceChange(intersection) {
3614
+ const face = intersection.face;
3615
+ const point = intersection.point;
3616
+ if (face && point) {
3617
+ const normal = face.normal.clone();
3618
+ const positionVector = normal.clone().multiplyScalar(0.05);
3619
+ const position = point.clone().add(positionVector);
3620
+ this.intersectMesh.position.copy(position);
3621
+ const lookAtVector = position.clone().add(positionVector);
3622
+ this.intersectMesh.lookAt(lookAtVector);
3623
+ this.five.scene.add(this.intersectMesh);
3624
+ const matrix = this.intersectMesh.modelViewMatrix.clone().toArray();
3625
+ this.changePieceStyl('matrix3d', matrix);
3626
+ const scale = this.calculateSize(point);
3627
+ this.changePieceStyl('scale', scale);
3628
+ }
3629
+ }
3630
+ calculateSize(vector) {
3631
+ if (!vector)
3632
+ return;
3633
+ const cameraPos = this.five.camera.position;
3634
+ let distance = vector.distanceTo(cameraPos);
3635
+ const maxDis = 4;
3636
+ const minDis = 1;
3637
+ if (distance > maxDis)
3638
+ distance = maxDis;
3639
+ if (distance < minDis)
3640
+ distance = minDis;
3641
+ const scale = (-0.51 / (maxDis - minDis)) * distance + 1;
3642
+ return scale;
3643
+ }
3644
+ /** 点击按钮时圆片动画 */
3645
+ dotAnimation() {
3646
+ const firstEasing = TWEEN__default["default"].Easing.Quadratic.InOut;
3647
+ const from = { opacity: 0.4, scale: this.pieceStyl.scale };
3648
+ const to = { opacity: [1, 0.4], scale: [this.pieceStyl.scale * 0.8, this.pieceStyl.scale] };
3649
+ let stop = noop;
3650
+ const firstTween = new TWEEN__default["default"].Tween(from)
3651
+ .to(to, 500)
3652
+ .easing(firstEasing)
3653
+ .start(0)
3654
+ .onUpdate(({ opacity, scale }) => {
3655
+ this.changePieceStyl('scale', scale);
3656
+ this.changePieceStyl('opacity', opacity);
3657
+ })
3658
+ .onComplete(() => {
3659
+ stop();
3660
+ });
3661
+ stop = requestAnimationFrameInterval((time) => {
3662
+ firstTween.update(time);
3663
+ });
3664
+ }
3665
+ changePieceStyl(key, value) {
3666
+ if (!this.content)
3667
+ return;
3668
+ this.pieceStyl[key] = value;
3669
+ this.content.style.transform = `matrix3d(${this.pieceStyl.matrix3d.toString()}) scale(${this.pieceStyl.scale})`;
3670
+ this.content.style.opacity = `${this.pieceStyl.opacity}`;
3671
+ }
3672
+ updateMouseGroup(intersection, mesh) {
3673
+ if (!this.hasAppendMouseGroup) {
3674
+ this.group.add(this.mouseGroup);
3675
+ this.hasAppendMouseGroup = true;
3676
+ const aimRef = this.container.querySelector('.range-piece__aim');
3677
+ if (aimRef)
3678
+ aimRef.style.opacity = '0';
3679
+ }
3680
+ if (!intersection)
3681
+ return this.mouseGroup;
3682
+ this.mouseGroup.position.copy(intersection.point);
3683
+ // ============ update mouseGroup quaternion ============
3684
+ if (mesh) {
3685
+ this.mouseGroup.quaternion.copy(mesh.quaternion);
3686
+ }
3687
+ else if (intersection.face) {
3688
+ const normal = intersection.face.normal;
3689
+ const positionVector = normal.clone().multiplyScalar(0.05);
3690
+ const position = intersection.point.clone().add(positionVector);
3691
+ const lookAtVector = position.clone().add(positionVector);
3692
+ this.mouseGroup.lookAt(lookAtVector);
3693
+ }
3694
+ return this.mouseGroup;
3695
+ }
3696
+ }
3697
+
3698
+ class MeasureController {
3699
+ constructor(five$1, params) {
3700
+ var _a, _b;
3701
+ Object.defineProperty(this, "hasOpen", {
3702
+ enumerable: true,
3703
+ configurable: true,
3704
+ writable: true,
3705
+ value: false
3706
+ });
3707
+ Object.defineProperty(this, "hook", {
3708
+ enumerable: true,
3709
+ configurable: true,
3710
+ writable: true,
3711
+ value: new five.Subscribe()
3712
+ });
3713
+ Object.defineProperty(this, "magnifier", {
3714
+ enumerable: true,
3715
+ configurable: true,
3716
+ writable: true,
3717
+ value: void 0
3718
+ });
3719
+ Object.defineProperty(this, "five", {
3720
+ enumerable: true,
3721
+ configurable: true,
3722
+ writable: true,
3723
+ value: void 0
3724
+ });
3725
+ Object.defineProperty(this, "model", {
3726
+ enumerable: true,
3727
+ configurable: true,
3728
+ writable: true,
3729
+ value: void 0
3730
+ });
3731
+ Object.defineProperty(this, "group", {
3732
+ enumerable: true,
3733
+ configurable: true,
3734
+ writable: true,
3735
+ value: void 0
3736
+ });
3737
+ Object.defineProperty(this, "fiveHelper", {
3738
+ enumerable: true,
3739
+ configurable: true,
3740
+ writable: true,
3741
+ value: void 0
3742
+ });
3743
+ Object.defineProperty(this, "useUIController", {
3744
+ enumerable: true,
3745
+ configurable: true,
3746
+ writable: true,
3747
+ value: void 0
3748
+ });
3749
+ Object.defineProperty(this, "params", {
3750
+ enumerable: true,
3751
+ configurable: true,
3752
+ writable: true,
3753
+ value: void 0
3754
+ });
3755
+ Object.defineProperty(this, "useGuideController", {
3756
+ enumerable: true,
3757
+ configurable: true,
3758
+ writable: true,
3759
+ value: void 0
3760
+ });
3761
+ Object.defineProperty(this, "rangePieceController", {
3762
+ enumerable: true,
3763
+ configurable: true,
3764
+ writable: true,
3765
+ value: void 0
3766
+ });
3767
+ Object.defineProperty(this, "container", {
3768
+ enumerable: true,
3769
+ configurable: true,
3770
+ writable: true,
3771
+ value: document.createElement('div')
3772
+ });
3773
+ Object.defineProperty(this, "shortcutKeyController", {
3774
+ enumerable: true,
3775
+ configurable: true,
3776
+ writable: true,
3777
+ value: void 0
3778
+ });
3779
+ Object.defineProperty(this, "controller", {
3780
+ enumerable: true,
3781
+ configurable: true,
3782
+ writable: true,
3783
+ value: null
3784
+ });
3785
+ Object.defineProperty(this, "controllerParams", {
3786
+ enumerable: true,
3787
+ configurable: true,
3788
+ writable: true,
3789
+ value: void 0
3790
+ });
3791
+ Object.defineProperty(this, "getCurrentMode", {
3792
+ enumerable: true,
3793
+ configurable: true,
3794
+ writable: true,
3795
+ value: () => {
3796
+ if (this.controller instanceof EditController)
3797
+ return 'Edit';
3798
+ if (this.controller instanceof WatchController)
3799
+ return 'Watch';
3800
+ if (this.controller instanceof MixedController)
3801
+ return 'Mixed';
3802
+ return null;
3803
+ }
3804
+ });
3805
+ /** 变更场景
3806
+ * @description 如果从编辑场景改变到观看场景,不会自动保存,默认丢弃所有改动
3807
+ */
3808
+ Object.defineProperty(this, "changeMode", {
3809
+ enumerable: true,
3810
+ configurable: true,
3811
+ writable: true,
3812
+ value: (mode) => {
3813
+ var _a;
3814
+ if (!this.hasOpen)
3815
+ return;
3816
+ if (this.getCurrentMode() === mode)
3817
+ return;
3818
+ // 不支持Mixed模式与其他模式切换
3819
+ if (this.getCurrentMode() === 'Mixed' || mode === 'Mixed')
3820
+ return new Error('不支持切换的Mode');
3821
+ (_a = this.controller) === null || _a === void 0 ? void 0 : _a.dispose();
3822
+ const controllerMap = {
3823
+ Watch: WatchController,
3824
+ Edit: EditController,
3825
+ };
3826
+ if (!controllerMap[mode])
3827
+ throw new Error('不存在的 Mode');
3828
+ this.controller = new controllerMap[mode](this.controllerParams);
3829
+ this.hook.emit('modeChange', mode);
3830
+ }
3831
+ });
3832
+ this.five = five$1;
3833
+ this.params = params;
3834
+ this.model = new Model({ userDistanceItemCreator: this.params.userDistanceItemCreator });
3835
+ this.fiveHelper = new FiveHelper(five$1);
3836
+ // magnifier
3837
+ this.magnifier = new Magnifier(five$1, (_a = params.magnifierParams) !== null && _a !== void 0 ? _a : { width: 190, height: 190, scale: 2 });
3838
+ // ==================== Group ====================
3839
+ this.group = new THREE.Group();
3840
+ this.group.name = 'plugin-measure-group';
3841
+ this.container.classList.add('five-plugin-measure-container');
3842
+ this.container.style.position = 'relative';
3843
+ this.container.style.pointerEvents = 'none';
3844
+ this.container.style.width = '100%';
3845
+ this.container.style.height = '100%';
3846
+ this.container.style.opacity = '0';
3847
+ this.container.style.background = 'rgba(0, 0, 0, 0.15)';
3848
+ const openParams = (_b = this.params.openParams) !== null && _b !== void 0 ? _b : {};
3849
+ this.controllerParams = {
3850
+ five: this.five,
3851
+ hook: this.hook,
3852
+ group: this.group,
3853
+ model: this.model,
3854
+ magnifier: this.magnifier,
3855
+ container: this.container,
3856
+ fiveHelper: this.fiveHelper,
3857
+ openParams,
3858
+ mouseGroup: getMouseGroup(),
3859
+ userDistanceItemCreator: this.params.userDistanceItemCreator,
3860
+ };
3861
+ if (this.params.useUIController !== false)
3862
+ this.useUIController = new UIController(this, this.controllerParams);
3863
+ if (this.params.useGuideController !== false)
3864
+ this.useGuideController = new GuideController(this, this.controllerParams);
3865
+ }
3866
+ appendTo(parent) {
3867
+ // const intersect = new IntersectController(this.five)
3868
+ // intersect.appendTo(parent)
3869
+ parent.append(this.container);
3870
+ }
3871
+ dispose() {
3872
+ var _a, _b;
3873
+ this.disable();
3874
+ (_a = this.useUIController) === null || _a === void 0 ? void 0 : _a.dispose();
3875
+ (_b = this.magnifier) === null || _b === void 0 ? void 0 : _b.dispose();
3876
+ this.five.needsRender = true;
3877
+ }
3878
+ /** 加载数据
3879
+ * @description 数据加载时会覆盖当前已保存的数据
3880
+ * @description 如果当前正在编辑中,会自动退出并保存编辑
3881
+ */
3882
+ load(data) {
3883
+ this.model.parse(data);
3884
+ this.save();
3885
+ }
3886
+ /** 插件功能入口
3887
+ * @description 会隐藏鼠标的默认聚焦环
3888
+ * @description 会隐藏当前 VR 内的点位展示
3889
+ */
3890
+ enable() {
3891
+ var _a, _b, _c;
3892
+ if (this.hasOpen)
3893
+ return;
3894
+ this.hasOpen = true;
3895
+ this.five.scene.add(this.group);
3896
+ // 修改透明度
3897
+ this.container.style.opacity = '1';
3898
+ if ((_a = this.params.openParams) === null || _a === void 0 ? void 0 : _a.isMobile) {
3899
+ this.controller = new MixedController(this.controllerParams);
3900
+ this.rangePieceController = new RangePieceController(this.controllerParams);
3901
+ }
3902
+ else {
3903
+ // 隐藏点位和鼠标聚焦环
3904
+ this.five.helperVisible = false;
3905
+ this.controller = new WatchController(this.controllerParams);
3906
+ }
3907
+ (_b = this.useUIController) === null || _b === void 0 ? void 0 : _b.show();
3908
+ (_c = this.useGuideController) === null || _c === void 0 ? void 0 : _c.show();
3909
+ this.shortcutKeyController = new ShortcutKeyController(this, this.five);
3910
+ this.hook.emit('enable', true);
3911
+ }
3912
+ /** 关闭插件功能
3913
+ * @description 清除标尺线条
3914
+ * @description 还原点位展示和默认鼠标 UI
3915
+ */
3916
+ disable() {
3917
+ var _a, _b, _c, _d, _e;
3918
+ this.hasOpen = false;
3919
+ // 修改透明度
3920
+ this.container.style.opacity = '0';
3921
+ // 展示点位和鼠标聚焦环
3922
+ (_a = this.controller) === null || _a === void 0 ? void 0 : _a.dispose();
3923
+ (_b = this.rangePieceController) === null || _b === void 0 ? void 0 : _b.dispose();
3924
+ (_c = this.useUIController) === null || _c === void 0 ? void 0 : _c.hide();
3925
+ (_d = this.useGuideController) === null || _d === void 0 ? void 0 : _d.hide();
3926
+ (_e = this.shortcutKeyController) === null || _e === void 0 ? void 0 : _e.dispose();
3927
+ this.controller = null;
3928
+ this.five.helperVisible = true;
3929
+ this.five.scene.remove(this.group);
3930
+ this.five.needsRender = true;
3931
+ this.hook.emit('disable', true);
3932
+ }
3933
+ /** 撤销编辑 */
3934
+ revoke() {
3935
+ if (!(this.controller instanceof EditController))
3936
+ return;
3937
+ this.controller.revoke();
3938
+ return;
3939
+ }
3940
+ removeLineByID(lineID) {
3941
+ this.model.removeLineByID(lineID);
3942
+ }
3943
+ /**
3944
+ * 高亮当前线段
3945
+ */
3946
+ highlightLine(lineID) {
3947
+ if (this.getCurrentMode() !== 'Watch')
3948
+ return false;
3949
+ const line = this.model.getLineByID(lineID);
3950
+ if (!line)
3951
+ return false;
3952
+ this.controller.highlightLine(line);
3953
+ return true;
3954
+ }
3955
+ clearHighlightLines() {
3956
+ if (this.getCurrentMode() !== 'Watch')
3957
+ return false;
3958
+ this.controller.clearHighlightLines();
3959
+ return true;
3960
+ }
3961
+ /** 保存编辑 */
3962
+ save() {
3963
+ if (!(this.controller instanceof EditController))
3964
+ return this;
3965
+ this.model.mergeModel(this.controller.model);
3966
+ return this;
3967
+ }
3968
+ /** 把当前以保存的数据转换成 JSON 对象 */
3969
+ toJson() {
3970
+ return this.model.toJson();
3971
+ }
3972
+ /**
3973
+ * @description 改变插件的模式(pc端模式或移动端模式)
3974
+ * @param isMobile true为移动端模式,false为pc端
3975
+ */
3976
+ changeIsMobile(isMobile) {
3977
+ var _a, _b;
3978
+ if (((_a = this.controllerParams.openParams) === null || _a === void 0 ? void 0 : _a.isMobile) === undefined) {
3979
+ this.controllerParams.openParams.isMobile = isMobile;
3980
+ }
3981
+ if (this.controllerParams.openParams.isMobile === isMobile)
3982
+ return;
3983
+ this.controllerParams.openParams.isMobile = isMobile;
3984
+ if (this.params.useUIController !== false)
3985
+ (_b = this.useUIController) === null || _b === void 0 ? void 0 : _b.dispose();
3986
+ this.useUIController = new UIController(this, this.controllerParams);
3987
+ }
3988
+ }
3989
+
3990
+ const PanoMeasurePlugin = function PanoMeasurePlugin(five, params) {
3991
+ return new MeasureController(five, params);
3992
+ };
3993
+
3994
+ exports.Magnifier = Magnifier;
3995
+ exports.PanoMeasurePlugin = PanoMeasurePlugin;
3996
+ exports["default"] = PanoMeasurePlugin;