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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +44 -5
  3. package/dist/dnalogel.cjs.js +7 -2
  4. package/dist/dnalogel.es.js +3668 -184
  5. package/dist/dnalogel.umd.js +7 -2
  6. package/dist/style.css +1 -1
  7. package/libs/CSS3DRenderPlugin/index.js +1 -1
  8. package/libs/PanoCompassPlugin/Assets/roomInfoIcon.d.ts +1 -0
  9. package/libs/PanoCompassPlugin/Assets/roomInfoIcon.js +1 -0
  10. package/libs/PanoCompassPlugin/getRoomInfoInstance.d.ts +8 -0
  11. package/libs/PanoCompassPlugin/getRoomInfoInstance.js +48 -0
  12. package/libs/PanoCompassPlugin/index.d.ts +29 -3
  13. package/libs/PanoCompassPlugin/index.js +126 -44
  14. package/libs/PanoMeasurePlugin/Controller/BaseController.d.ts +36 -0
  15. package/libs/PanoMeasurePlugin/Controller/BaseController.js +69 -0
  16. package/libs/PanoMeasurePlugin/Controller/EditController.d.ts +52 -0
  17. package/libs/PanoMeasurePlugin/Controller/EditController.js +216 -0
  18. package/libs/PanoMeasurePlugin/Controller/ShortcutKeyController.d.ts +12 -0
  19. package/libs/PanoMeasurePlugin/Controller/ShortcutKeyController.js +44 -0
  20. package/libs/PanoMeasurePlugin/Controller/WatchController.d.ts +25 -0
  21. package/libs/PanoMeasurePlugin/Controller/WatchController.js +223 -0
  22. package/libs/PanoMeasurePlugin/Controller/index.d.ts +61 -0
  23. package/libs/PanoMeasurePlugin/Controller/index.js +176 -0
  24. package/libs/PanoMeasurePlugin/Model/index.d.ts +38 -0
  25. package/libs/PanoMeasurePlugin/Model/index.js +114 -0
  26. package/libs/PanoMeasurePlugin/Model/line.d.ts +30 -0
  27. package/libs/PanoMeasurePlugin/Model/line.js +64 -0
  28. package/libs/PanoMeasurePlugin/Model/point.d.ts +16 -0
  29. package/libs/PanoMeasurePlugin/Model/point.js +28 -0
  30. package/libs/PanoMeasurePlugin/Model/polyline.d.ts +16 -0
  31. package/libs/PanoMeasurePlugin/Model/polyline.js +48 -0
  32. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.d.ts +2 -0
  33. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete.svg.js +15 -0
  34. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.d.ts +2 -0
  35. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_bg.png.js +2 -0
  36. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_hover_bg.png.d.ts +2 -0
  37. package/libs/PanoMeasurePlugin/Modules/DeleteDom/_Assets/delete_hover_bg.png.js +2 -0
  38. package/libs/PanoMeasurePlugin/Modules/DeleteDom/index.d.ts +22 -0
  39. package/libs/PanoMeasurePlugin/Modules/DeleteDom/index.js +108 -0
  40. package/libs/PanoMeasurePlugin/Modules/FiveHelper.d.ts +11 -0
  41. package/libs/PanoMeasurePlugin/Modules/FiveHelper.js +33 -0
  42. package/libs/PanoMeasurePlugin/Modules/GuideController.d.ts +18 -0
  43. package/libs/PanoMeasurePlugin/Modules/GuideController.js +75 -0
  44. package/libs/PanoMeasurePlugin/Modules/Magnifier.d.ts +24 -0
  45. package/libs/PanoMeasurePlugin/Modules/Magnifier.js +103 -0
  46. package/libs/PanoMeasurePlugin/Modules/UIController/HTML.d.ts +6 -0
  47. package/libs/PanoMeasurePlugin/Modules/UIController/HTML.js +117 -0
  48. package/libs/PanoMeasurePlugin/Modules/UIController/MainBtnController.d.ts +18 -0
  49. package/libs/PanoMeasurePlugin/Modules/UIController/MainBtnController.js +102 -0
  50. package/libs/PanoMeasurePlugin/Modules/UIController/Revoke/index.d.ts +12 -0
  51. package/libs/PanoMeasurePlugin/Modules/UIController/Revoke/index.js +35 -0
  52. package/libs/PanoMeasurePlugin/Modules/UIController/index.d.ts +16 -0
  53. package/libs/PanoMeasurePlugin/Modules/UIController/index.js +69 -0
  54. package/libs/PanoMeasurePlugin/Modules/UIController/style.d.ts +17 -0
  55. package/libs/PanoMeasurePlugin/Modules/UIController/style.js +78 -0
  56. package/libs/PanoMeasurePlugin/index.d.ts +7 -0
  57. package/libs/PanoMeasurePlugin/index.js +5 -0
  58. package/libs/PanoMeasurePlugin/typings/data.d.ts +28 -0
  59. package/libs/PanoMeasurePlugin/typings/data.js +1 -0
  60. package/libs/PanoMeasurePlugin/typings/event.type.d.ts +28 -0
  61. package/libs/PanoMeasurePlugin/typings/event.type.js +1 -0
  62. package/libs/PanoMeasurePlugin/typings/utils.type.d.ts +1 -0
  63. package/libs/PanoMeasurePlugin/typings/utils.type.js +1 -0
  64. package/libs/PanoMeasurePlugin/utils/clearGroup.d.ts +2 -0
  65. package/libs/PanoMeasurePlugin/utils/clearGroup.js +3 -0
  66. package/libs/PanoMeasurePlugin/utils/constants.d.ts +4 -0
  67. package/libs/PanoMeasurePlugin/utils/constants.js +31 -0
  68. package/libs/PanoMeasurePlugin/utils/distanceDom.d.ts +28 -0
  69. package/libs/PanoMeasurePlugin/utils/distanceDom.js +114 -0
  70. package/libs/PanoMeasurePlugin/utils/findAssociatedLines.d.ts +2 -0
  71. package/libs/PanoMeasurePlugin/utils/findAssociatedLines.js +21 -0
  72. package/libs/PanoMeasurePlugin/utils/findClosestPoint.d.ts +10 -0
  73. package/libs/PanoMeasurePlugin/utils/findClosestPoint.js +27 -0
  74. package/libs/PanoMeasurePlugin/utils/getIntersectionFromEvent.d.ts +4 -0
  75. package/libs/PanoMeasurePlugin/utils/getIntersectionFromEvent.js +9 -0
  76. package/libs/PanoMeasurePlugin/utils/getPointFromHammerEvent.d.ts +10 -0
  77. package/libs/PanoMeasurePlugin/utils/getPointFromHammerEvent.js +14 -0
  78. package/libs/PanoMeasurePlugin/utils/ironbox.d.ts +1 -0
  79. package/libs/PanoMeasurePlugin/utils/ironbox.js +1 -0
  80. package/libs/PanoMeasurePlugin/utils/isNDCPointInScreen.d.ts +2 -0
  81. package/libs/PanoMeasurePlugin/utils/isNDCPointInScreen.js +6 -0
  82. package/libs/PanoMeasurePlugin/utils/line.d.ts +17 -0
  83. package/libs/PanoMeasurePlugin/utils/line.js +32 -0
  84. package/libs/PanoMeasurePlugin/utils/math.d.ts +17 -0
  85. package/libs/PanoMeasurePlugin/utils/math.js +44 -0
  86. package/libs/PanoMeasurePlugin/utils/mouseGroup.d.ts +2 -0
  87. package/libs/PanoMeasurePlugin/utils/mouseGroup.js +21 -0
  88. package/libs/PanoMeasurePlugin/utils/ndc2Screen.d.ts +5 -0
  89. package/libs/PanoMeasurePlugin/utils/ndc2Screen.js +6 -0
  90. package/libs/PanoRulerPlugin/index.js +1 -0
  91. package/libs/PanoRulerPlugin/style.d.ts +1 -1
  92. package/libs/PanoRulerPlugin/style.js +1 -0
  93. package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.svelte +3 -3
  94. package/libs/floorplan/ModelFloorplanPlugin/Components/Camera.svelte.map +1 -1
  95. package/libs/floorplan/ModelFloorplanPlugin/Controller.d.ts +2 -0
  96. package/libs/floorplan/ModelFloorplanPlugin/Controller.js +3 -1
  97. package/libs/floorplan/TopviewFloorplanPlugin/Controller.d.ts +2 -0
  98. package/libs/floorplan/TopviewFloorplanPlugin/Controller.js +4 -3
  99. package/libs/floorplan/constant.d.ts +5 -0
  100. package/libs/floorplan/constant.js +6 -0
  101. package/libs/floorplan/typings/floorplanServerData.d.ts +4 -0
  102. package/libs/index.d.ts +4 -1
  103. package/libs/index.js +4 -1
  104. package/libs/shared-utils/getPxmm.d.ts +6 -1
  105. package/libs/shared-utils/getPxmm.js +26 -12
  106. package/package.json +2 -1
@@ -0,0 +1,108 @@
1
+ import deleteSvg from './_Assets/delete.svg';
2
+ import deleteBg from './_Assets/delete_bg.png';
3
+ import deleteHoverBg from './_Assets/delete_hover_bg.png';
4
+ export default class DeleteDom {
5
+ visible = false;
6
+ five;
7
+ lines = [];
8
+ points = [];
9
+ onClick;
10
+ content = document.createElement('div');
11
+ container = document.createElement('div');
12
+ constructor(five, opts) {
13
+ this.five = five;
14
+ this.onClick = opts?.onClick || (() => void 0);
15
+ // container
16
+ this.container.classList.add('fpm__delete');
17
+ this.container.style.opacity = '0';
18
+ this.container.style.position = 'absolute';
19
+ this.container.style.left = '0';
20
+ this.container.style.top = '0';
21
+ this.container.style.transform = `translate3d(0, 0, 10px)`;
22
+ this.container.style.pointerEvents = `none`;
23
+ // content
24
+ this.content.classList.add('fpm__delete-content');
25
+ this.content.style.width = '67px';
26
+ this.content.style.height = '31px';
27
+ this.content.style.display = 'flex';
28
+ this.content.style.alignItems = 'center';
29
+ this.content.style.justifyContent = 'center';
30
+ this.content.style.transform = 'translate(-50%, -50%)';
31
+ this.content.style.color = '#fff';
32
+ this.content.style.fontSize = '14px';
33
+ this.content.style.lineHeight = '31px';
34
+ this.content.style.borderRadius = '15px';
35
+ this.content.style.backgroundSize = '100% 100%';
36
+ this.content.style.cursor = 'pointer';
37
+ this.content.style.userSelect = 'none';
38
+ this.content.style.backgroundImage = `url(${deleteBg})`;
39
+ this.content.innerHTML = `
40
+ ${deleteSvg}
41
+ <span>删除</span>
42
+ `;
43
+ this.container.append(this.content);
44
+ const deleteSvgDom = this.content.querySelector('.fpm__delete-icon');
45
+ if (deleteSvgDom) {
46
+ deleteSvgDom.style.width = '20px';
47
+ deleteSvgDom.style.height = '20px';
48
+ deleteSvgDom.style.marginRight = '2px';
49
+ }
50
+ this.content.addEventListener('click', this.onClick);
51
+ this.content.addEventListener('mouseenter', this.onMouseEnter);
52
+ this.content.addEventListener('mouseleave', this.onMouseLeave);
53
+ }
54
+ dispose() {
55
+ this.content.removeEventListener('click', this.onClick);
56
+ this.content.removeEventListener('mouseenter', this.onMouseEnter);
57
+ this.content.removeEventListener('mouseleave', this.onMouseLeave);
58
+ this.container.remove();
59
+ }
60
+ appendTo(element) {
61
+ element.append(this.container);
62
+ return this;
63
+ }
64
+ setLines(lines) {
65
+ this.lines = lines;
66
+ this.points = Array.from(new Set(this.lines.map((line) => [line.points[0], line.points[1]]).flat(1)));
67
+ return this;
68
+ }
69
+ updatePosition() {
70
+ if (this.lines.length === 0)
71
+ return this;
72
+ const points = this.points.map((point) => point.position);
73
+ const ndcPoints = points.map((point) => point.clone().project(this.five.camera));
74
+ if (ndcPoints.some((ndcPoint) => Math.abs(ndcPoint.z) > 1))
75
+ return this.hide();
76
+ const xArray = ndcPoints.map((point) => point.x);
77
+ const yArray = ndcPoints.map((point) => point.y);
78
+ const centerX = (Math.min(...xArray) + Math.max(...xArray)) / 2;
79
+ const maxY = Math.max(...yArray);
80
+ const wrapper = this.container.parentElement;
81
+ if (!wrapper)
82
+ return this;
83
+ const centerScreenX = ((centerX + 1) / 2) * wrapper.clientWidth;
84
+ const maxScreenY = (-(maxY - 1) / 2) * wrapper.clientHeight;
85
+ const x = centerScreenX;
86
+ const y = maxScreenY - 34;
87
+ this.container.style.transform = `translate3d(${x}px, ${y}px, 10px)`;
88
+ return this.show();
89
+ }
90
+ hide() {
91
+ this.visible = false;
92
+ this.container.style.opacity = '0';
93
+ this.container.style.pointerEvents = 'none';
94
+ return this;
95
+ }
96
+ show() {
97
+ this.visible = true;
98
+ this.container.style.opacity = '1';
99
+ this.container.style.pointerEvents = 'auto';
100
+ return this;
101
+ }
102
+ onMouseEnter = () => {
103
+ this.content.style.backgroundImage = `url(${deleteHoverBg})`;
104
+ };
105
+ onMouseLeave = () => {
106
+ this.content.style.backgroundImage = `url(${deleteBg})`;
107
+ };
108
+ }
@@ -0,0 +1,11 @@
1
+ import { Line3, Vector3 } from 'three';
2
+ import { Five, Intersection } from '@realsee/five';
3
+ export default class FiveHelper {
4
+ edges: Line3[];
5
+ private five;
6
+ constructor(five: Five);
7
+ dispose(): void;
8
+ getAdsorbentPoint(intersection: Intersection): Vector3 | null;
9
+ /** 模型加载后获取折线 */
10
+ private onModelLoaded;
11
+ }
@@ -0,0 +1,33 @@
1
+ import { Vector3 } from 'three';
2
+ export default class FiveHelper {
3
+ edges = [];
4
+ five;
5
+ constructor(five) {
6
+ this.five = five;
7
+ this.five.model.loaded ? this.onModelLoaded() : this.five.on('modelLoaded', this.onModelLoaded);
8
+ }
9
+ dispose() { }
10
+ getAdsorbentPoint(intersection) {
11
+ if (this.edges.length === 0)
12
+ return null;
13
+ let distance = Infinity;
14
+ let closestPoint;
15
+ this.edges.forEach((line) => {
16
+ const _closestPoint = line.closestPointToPoint(intersection.point, true, new Vector3());
17
+ const _distance = _closestPoint.distanceTo(intersection.point);
18
+ if (_distance < distance) {
19
+ closestPoint = _closestPoint;
20
+ distance = _distance;
21
+ }
22
+ });
23
+ if (distance > 0.1)
24
+ return null;
25
+ return closestPoint || null;
26
+ }
27
+ /** 模型加载后获取折线 */
28
+ onModelLoaded = () => {
29
+ if (!this.five.model)
30
+ return;
31
+ this.edges = this.five.model.getEdges();
32
+ };
33
+ }
@@ -0,0 +1,18 @@
1
+ import MeasureController from '../Controller';
2
+ export interface GuideControllerParams {
3
+ container: Element;
4
+ }
5
+ export declare class GuideController {
6
+ private measureController;
7
+ private textDom;
8
+ private container;
9
+ private hasAnchor;
10
+ constructor(measureController: MeasureController, params: GuideControllerParams);
11
+ dispose(): void;
12
+ show(): this;
13
+ hide(): this;
14
+ private initDom;
15
+ private onModelChange;
16
+ private anchorChange;
17
+ private onEditedLineChange;
18
+ }
@@ -0,0 +1,75 @@
1
+ export class GuideController {
2
+ measureController;
3
+ textDom = document.createElement('span');
4
+ container = document.createElement('div');
5
+ hasAnchor = false;
6
+ constructor(measureController, params) {
7
+ this.initDom();
8
+ params.container.append(this.container);
9
+ this.measureController = measureController;
10
+ measureController.hook.on('modeChange', this.onModelChange);
11
+ measureController.hook.on('anchorChange', this.anchorChange);
12
+ measureController.hook.on('editedLineChange', this.onEditedLineChange);
13
+ }
14
+ dispose() {
15
+ this.hide();
16
+ this.container.remove();
17
+ }
18
+ show() {
19
+ this.container.style.opacity = '1';
20
+ this.container.style.transform = 'translate(0, 0)';
21
+ return this;
22
+ }
23
+ hide() {
24
+ this.container.style.opacity = '0';
25
+ this.container.style.transform = 'translate(0, -10px)';
26
+ this.measureController.hook.off('modeChange', this.onModelChange);
27
+ this.measureController.hook.off('anchorChange', this.anchorChange);
28
+ this.measureController.hook.off('editedLineChange', this.onEditedLineChange);
29
+ return this;
30
+ }
31
+ initDom() {
32
+ const container = this.container;
33
+ const textDom = this.textDom;
34
+ container.classList.add('fpm__guide-container');
35
+ container.style.position = 'absolute';
36
+ container.style.top = '0px';
37
+ container.style.left = '0px';
38
+ container.style.width = '100%';
39
+ container.style.height = '110px';
40
+ container.style.display = 'flex';
41
+ container.style.alignItems = 'center';
42
+ container.style.justifyContent = 'center';
43
+ container.style.transform = 'translate(0, -10px)';
44
+ container.style.background = `linear-gradient(180deg, rgba(0,0,0,0.40) 0%, rgba(0,0,0,0.00) 100%)`;
45
+ container.style.transition = 'opacity 500ms ease-in-out, transform 500ms ease-in-out';
46
+ container.style.opacity = '0';
47
+ textDom.classList.add('fpm__guide-text');
48
+ textDom.style.color = '#fff';
49
+ textDom.style.fontSize = '20px';
50
+ textDom.innerText = `点击下方“添加”开始测距`;
51
+ container.appendChild(textDom);
52
+ }
53
+ onModelChange = (mode) => {
54
+ if (mode === 'Watch') {
55
+ this.textDom.innerText = ``;
56
+ return;
57
+ }
58
+ this.textDom.innerText = `请选择第一个测量点,Esc或单击鼠标右键可取消选择`;
59
+ };
60
+ anchorChange = (anchor) => {
61
+ if (!this.hasAnchor && !!anchor) {
62
+ this.hasAnchor = true;
63
+ this.textDom.innerText = `选择下一个测量点,Esc或单击鼠标右键取消选择`;
64
+ }
65
+ else if (!anchor) {
66
+ this.hasAnchor = false;
67
+ this.textDom.innerText = `请选择第一个测量点,Esc或单击鼠标右键可取消选择`;
68
+ }
69
+ };
70
+ onEditedLineChange = (lines) => {
71
+ if (lines.length === 1) {
72
+ this.textDom.innerText = `可以连续选择测量点,或点击下方“完成”结束测量(Esc取消,Command+S保存)`;
73
+ }
74
+ };
75
+ }
@@ -0,0 +1,24 @@
1
+ import { Five } from '@realsee/five';
2
+ import { Vector3 } from 'three';
3
+ export interface MagnifierOptions {
4
+ width: number;
5
+ height: number;
6
+ scale: number;
7
+ }
8
+ export default class Magnifier {
9
+ private five;
10
+ private scale;
11
+ private width;
12
+ private height;
13
+ private pixelRatio;
14
+ private originWidth;
15
+ private originHeight;
16
+ private context;
17
+ private canvas;
18
+ private container?;
19
+ constructor(five: Five, options: MagnifierOptions);
20
+ dispose(): void;
21
+ clear(): void;
22
+ appendTo(element: Element): void;
23
+ updateWithPoint(point: Vector3): void;
24
+ }
@@ -0,0 +1,103 @@
1
+ import { Vector2 } from 'three';
2
+ /** 交换数组元素 */
3
+ function exchange(array, index1, index2) {
4
+ const value = array[index1];
5
+ array[index1] = array[index2];
6
+ array[index2] = value;
7
+ }
8
+ export default class Magnifier {
9
+ five;
10
+ scale;
11
+ width;
12
+ height;
13
+ pixelRatio;
14
+ originWidth;
15
+ originHeight;
16
+ context;
17
+ canvas = document.createElement('canvas');
18
+ container;
19
+ constructor(five, options) {
20
+ if (!five.renderer)
21
+ throw new Error('Five Render 未初始化');
22
+ this.five = five;
23
+ const scale = options.scale;
24
+ const pixelRatio = five.renderer.getPixelRatio();
25
+ const originWidth = options.width;
26
+ const originHeight = options.height;
27
+ const width = originWidth * pixelRatio;
28
+ const height = originHeight * pixelRatio;
29
+ const magnifier = this.canvas;
30
+ const context = this.canvas.getContext('2d');
31
+ if (!context)
32
+ throw new Error('CANNOT CREATE CONTEXT2D');
33
+ this.scale = scale;
34
+ this.context = context;
35
+ this.width = width;
36
+ this.height = height;
37
+ this.originWidth = originWidth;
38
+ this.originHeight = originHeight;
39
+ this.pixelRatio = pixelRatio;
40
+ magnifier.classList.add('plugin-measure-magnifier');
41
+ magnifier.style.position = 'absolute';
42
+ magnifier.style.pointerEvents = 'none';
43
+ magnifier.style.borderRadius = '50%';
44
+ magnifier.style.left = -width / 2 + 'px';
45
+ magnifier.style.top = -height - 90 + 'px';
46
+ magnifier.setAttribute('width', width.toString());
47
+ magnifier.setAttribute('height', height.toString());
48
+ this.canvas.style.width = originWidth + 'px';
49
+ this.canvas.style.height = originHeight + 'px';
50
+ }
51
+ dispose() {
52
+ this.clear();
53
+ this.canvas.remove();
54
+ }
55
+ clear() {
56
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
57
+ }
58
+ appendTo(element) {
59
+ this.container = element;
60
+ element.append(this.canvas);
61
+ }
62
+ updateWithPoint(point) {
63
+ if (!this.five.renderer || !this.container)
64
+ return;
65
+ const { scale, pixelRatio, context, originWidth, originHeight, width, height } = this;
66
+ const position2d = point.clone().project(this.five.camera);
67
+ const left = ((position2d.x + 1) / 2) * this.container.clientWidth;
68
+ const right = (-(position2d.x - 1) / 2) * this.container.clientWidth;
69
+ const top = (-(position2d.y - 1) / 2) * this.container.clientHeight;
70
+ if (left < 183) {
71
+ this.canvas.style.top = -originHeight / 2 + 'px';
72
+ this.canvas.style.left = 90 + 'px';
73
+ }
74
+ else if (top < 183) {
75
+ this.canvas.style.top = 90 + 'px';
76
+ this.canvas.style.left = -originWidth / 2 + 'px';
77
+ }
78
+ else if (right < 183) {
79
+ this.canvas.style.top = -originHeight / 2 + 'px';
80
+ this.canvas.style.left = -originWidth - 90 + 'px';
81
+ }
82
+ else {
83
+ this.canvas.style.left = -originWidth / 2 + 'px';
84
+ this.canvas.style.top = -originHeight - 90 + 'px';
85
+ }
86
+ this.canvas.style.transform = `translate3d(${left}px, ${top}px, 10px)`;
87
+ const renderSize = this.five.renderer.getSize(new Vector2());
88
+ const x = ((position2d.x + 1) / 2) * renderSize.x;
89
+ const y = ((position2d.y + 1) / 2) * renderSize.y;
90
+ const pixels = this.five.getPixels(x - originWidth / scale / 2, y - originHeight / scale / 2, originWidth / scale, originHeight / scale, pixelRatio * scale);
91
+ const length = (width * height) / 2;
92
+ for (let index = 0; index < length; index++) {
93
+ const targetIndex = (height - Math.floor(index / width) - 1) * width + (index % width);
94
+ exchange(pixels, index * 4 + 0, targetIndex * 4 + 0);
95
+ exchange(pixels, index * 4 + 1, targetIndex * 4 + 1);
96
+ exchange(pixels, index * 4 + 2, targetIndex * 4 + 2);
97
+ exchange(pixels, index * 4 + 3, targetIndex * 4 + 3);
98
+ }
99
+ const imageData = context.createImageData(width, height);
100
+ imageData.data.set(pixels);
101
+ context.putImageData(imageData, 0, 0);
102
+ }
103
+ }
@@ -0,0 +1,6 @@
1
+ export declare 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";
2
+ export declare 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";
3
+ export declare const MAIN_MOUSE_ENTER_FILL = "url(#fpm__main-b)";
4
+ export declare const MAIN_MOUSE_LEAVE_FILL = "url(#fpm__main-c)";
5
+ declare const _default: string;
6
+ export default _default;
@@ -0,0 +1,117 @@
1
+ export 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';
2
+ export 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';
3
+ export const MAIN_MOUSE_ENTER_FILL = 'url(#fpm__main-b)';
4
+ export const MAIN_MOUSE_LEAVE_FILL = 'url(#fpm__main-c)';
5
+ const revokeSvg = `
6
+ <svg class="fpm__revoke-icon" width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
7
+ <defs>
8
+ <linearGradient x1="47.631%" y1="55.183%" x2="2.967%" y2="86.323%" id="fpm__revoke-a">
9
+ <stop stop-color="#FFF" offset="0%" />
10
+ <stop stop-color="#FFF" stop-opacity=".5" offset="100%" />
11
+ </linearGradient>
12
+ <linearGradient x1="5.297%" y1="43.016%" x2="38.238%" y2="79.932%" id="fpm__revoke-b">
13
+ <stop stop-color="#FFF" offset="0%" />
14
+ <stop stop-color="#FFF" stop-opacity="0" offset="100%" />
15
+ </linearGradient>
16
+ </defs>
17
+ <path
18
+ 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"
19
+ fill="url(#fpm__revoke-a)"
20
+ fill-rule="nonzero"
21
+ stroke="url(#fpm__revoke-b)"
22
+ stroke-width=".5"
23
+ />
24
+ </svg>
25
+ `;
26
+ const exitSvg = `
27
+ <svg class="fpm__exit-icon width="40" height="40" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
28
+ <defs>
29
+ <linearGradient x1="36.288%" y1="73.736%" x2="54.242%" y2="97.166%" id="fpm__exit-a">
30
+ <stop stop-color="#FFF" offset="0%" />
31
+ <stop stop-color="#FFF" stop-opacity=".5" offset="100%" />
32
+ </linearGradient>
33
+ <linearGradient x1="100%" y1="47.234%" x2="24.047%" y2="47.234%" id="fpm__exit-b">
34
+ <stop stop-color="#FFF" offset="0%" />
35
+ <stop stop-color="#FFF" stop-opacity=".005" offset="99.535%" />
36
+ <stop stop-color="#FFF" stop-opacity="0" offset="100%" />
37
+ </linearGradient>
38
+ </defs>
39
+ <path
40
+ 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"
41
+ fill="url(#fpm__exit-a)"
42
+ fill-rule="nonzero"
43
+ stroke="url(#fpm__exit-b)"
44
+ stroke-width=".5"
45
+ />
46
+ </svg>
47
+ `;
48
+ const mainSvg = `
49
+ <svg class="fpm__main-icon" width="60" height="60" viewBox="0 0 60 60" xmlns="http://www.w3.org/2000/svg">
50
+ <defs>
51
+ <mask id="fpm__main-icon-mask">
52
+ <rect id="fpm__main-icon-mask-black" x="0" y="0" width="30" height="30" fill="black"></rect>
53
+ <rect id="fpm__main-icon-mask-white" x="0" y="0" width="0" height="30" fill="white"></rect>
54
+ </mask>
55
+ <linearGradient id="fpm__main-a" x1="25.371%" y1="0%" x2="109.587%" y2="172.268%">
56
+ <stop stop-color="#FFF" offset="0%" />
57
+ <stop stop-color="#FFF" stop-opacity=".77" offset="44.051%" />
58
+ <stop stop-color="#FFF" stop-opacity=".201" offset="100%" />
59
+ </linearGradient>
60
+ <radialGradient id="fpm__main-b" fx="50%" fy="50%" r="50.864%" gradientTransform="matrix(-.98302 0 0 -1 .992 1)">
61
+ <stop stop-color="#2D7CFF" offset="0%" />
62
+ <stop stop-color="#2D7CFF" stop-opacity=".3" offset="100%" />
63
+ </radialGradient>
64
+ <radialGradient id="fpm__main-c" fx="50%" fy="50%" r="50.864%" gradientTransform="matrix(-.98302 0 0 -1 .992 1)">
65
+ <stop stop-opacity=".4" offset="0%" />
66
+ <stop stop-opacity=".12" offset="100%" />
67
+ </radialGradient>
68
+ </defs>
69
+ <g fill="none" fill-rule="evenodd">
70
+ <circle fill="url(#fpm__main-a)" cx="30" cy="30" r="30" />
71
+ <path
72
+ class="fpm__main-icon-path"
73
+ d="${MAIN_NORMAL_PATH}"
74
+ fill="${MAIN_MOUSE_LEAVE_FILL}"
75
+ fill-rule="nonzero"
76
+ transform="translate(14 14)"
77
+ />
78
+ </g>
79
+ </svg>
80
+ `;
81
+ export default `
82
+ <style>
83
+ .fpm__revoke {
84
+ opacity: 0.3;
85
+ }
86
+
87
+ .fpm__revoke.enabled {
88
+ opacity: 0.7;
89
+ }
90
+
91
+ .fpm__revoke.enabled:hover {
92
+ opacity: 1;
93
+ }
94
+
95
+ .fpm__revoke-icon {
96
+ width: 40px;
97
+ height: 40px;
98
+ margin-top: 10px;
99
+ cursor: pointer;
100
+ }
101
+ </style>
102
+ <div class="fpm_ui-bg"></div>
103
+ <div class="fpm_operating-space">
104
+ <div class="fpm__ui-item fpm__revoke">
105
+ ${revokeSvg}
106
+ <span class="fpm__text fpm__revoke-text">撤销</span>
107
+ </div>
108
+ <div class="fpm__ui-item fpm__main">
109
+ ${mainSvg}
110
+ <span class="fpm__text fpm__main-text">添加</span>
111
+ </div>
112
+ <div class="fpm__ui-item fpm__exit">
113
+ ${exitSvg}
114
+ <span class="fpm__text fpm__exit-text">退出</span>
115
+ </div>
116
+ </div>
117
+ `;
@@ -0,0 +1,18 @@
1
+ import MeasureController from '../../Controller';
2
+ export declare class MainBtnController {
3
+ private container;
4
+ private measureController;
5
+ private mainIconMaskTween?;
6
+ private mainElement;
7
+ constructor(measureController: MeasureController, container: Element);
8
+ dispose(): void;
9
+ private getMainElement;
10
+ private change2Add;
11
+ private change2Cancel;
12
+ private change2Done;
13
+ private onMouseEnter;
14
+ private onMouseLeave;
15
+ private onClick;
16
+ private editedLineChangeHandler;
17
+ private modeChangeHandler;
18
+ }
@@ -0,0 +1,102 @@
1
+ import TWEEN from '@tweenjs/tween.js';
2
+ import { mainIconStyle as mainIconStyle, mainItemStyle as mainItemStyle } from './style';
3
+ import { tweenProgress } from '../../../shared-utils/animationFrame/BetterTween';
4
+ import { MAIN_NORMAL_PATH, MAIN_DONE_PATH, MAIN_MOUSE_ENTER_FILL, MAIN_MOUSE_LEAVE_FILL } from './HTML';
5
+ export class MainBtnController {
6
+ container;
7
+ measureController;
8
+ mainIconMaskTween;
9
+ mainElement;
10
+ constructor(measureController, container) {
11
+ this.measureController = measureController;
12
+ this.container = container;
13
+ this.mainElement = this.getMainElement();
14
+ Object.assign(this.mainElement.mainIcon.style, mainIconStyle);
15
+ Object.assign(this.mainElement.mainItem.style, mainItemStyle);
16
+ this.change2Add();
17
+ this.measureController.hook.on('modeChange', this.modeChangeHandler);
18
+ this.mainElement.mainIcon.addEventListener('click', this.onClick);
19
+ this.mainElement.mainIcon.addEventListener('mouseenter', this.onMouseEnter);
20
+ this.mainElement.mainIcon.addEventListener('mouseleave', this.onMouseLeave);
21
+ }
22
+ dispose() {
23
+ this.measureController.hook.off('modeChange', this.modeChangeHandler);
24
+ this.measureController.hook.off('editedLineChange', this.editedLineChangeHandler);
25
+ this.mainElement.mainIcon.removeEventListener('click', this.onClick);
26
+ this.mainElement.mainIcon.removeEventListener('mouseenter', this.onMouseEnter);
27
+ this.mainElement.mainIcon.removeEventListener('mouseleave', this.onMouseLeave);
28
+ }
29
+ getMainElement() {
30
+ const mainTextDom = this.container.querySelector('.fpm__main-text');
31
+ const mainItem = this.container.querySelector('.fpm__main');
32
+ const mainIcon = this.container.querySelector('.fpm__main-icon');
33
+ const pathDom = mainItem?.querySelector('.fpm__main-icon-path');
34
+ const maskWhiteRect = mainIcon?.querySelector('#fpm__main-icon-mask-white');
35
+ if (!mainItem || !mainTextDom || !mainIcon || !pathDom || !maskWhiteRect)
36
+ throw new Error('cannot find dom');
37
+ return { mainTextDom, mainItem, mainIcon, pathDom, maskWhiteRect };
38
+ }
39
+ change2Add() {
40
+ this.measureController.hook.off('editedLineChange', this.editedLineChangeHandler);
41
+ const { mainIcon, mainTextDom, pathDom } = this.mainElement;
42
+ mainIcon.style.transition = mainTextDom.innerText === '完成' ? 'none' : 'transform 300ms ease-in-out';
43
+ mainIcon.style.transform = 'rotate(0deg)';
44
+ mainTextDom.innerText = '添加';
45
+ pathDom?.setAttribute('d', MAIN_NORMAL_PATH);
46
+ }
47
+ change2Cancel(withAnime = true) {
48
+ const { mainIcon, mainTextDom, pathDom } = this.mainElement;
49
+ pathDom.setAttribute('d', MAIN_NORMAL_PATH);
50
+ pathDom.setAttribute('mask', '');
51
+ mainIcon.style.transition = withAnime ? 'transform 300ms ease-in-out' : 'none';
52
+ mainIcon.style.transform = 'rotate(45deg)';
53
+ mainTextDom && (mainTextDom.innerText = '取消');
54
+ this.measureController.hook.on('editedLineChange', this.editedLineChangeHandler);
55
+ }
56
+ change2Done() {
57
+ const { mainTextDom, mainIcon, pathDom, maskWhiteRect } = this.getMainElement();
58
+ if (mainTextDom.innerText === '完成')
59
+ return;
60
+ mainIcon.style.transition = 'none';
61
+ mainIcon.style.transform = 'rotate(0deg)';
62
+ mainTextDom.innerText = '完成';
63
+ pathDom.setAttribute('d', MAIN_DONE_PATH);
64
+ pathDom.setAttribute('mask', `url(#fpm__main-icon-mask)`);
65
+ this.mainIconMaskTween?.dispose();
66
+ this.mainIconMaskTween = tweenProgress()
67
+ .easing(TWEEN.Easing.Quartic.InOut)
68
+ .onUpdate(({ progress }) => {
69
+ maskWhiteRect.setAttribute('width', (progress * 30).toString());
70
+ })
71
+ .onComplete(() => this.mainIconMaskTween?.dispose())
72
+ .play();
73
+ }
74
+ /* 鼠标移入时变成蓝色 */
75
+ onMouseEnter = () => {
76
+ const { mainItem, pathDom } = this.mainElement;
77
+ mainItem.style.opacity = '1';
78
+ pathDom.setAttribute('fill', MAIN_MOUSE_ENTER_FILL);
79
+ };
80
+ /* 鼠标移出时变成灰色 */
81
+ onMouseLeave = () => {
82
+ const { mainItem, pathDom } = this.mainElement;
83
+ mainItem.style.opacity = '0.7';
84
+ pathDom.setAttribute('fill', MAIN_MOUSE_LEAVE_FILL);
85
+ };
86
+ onClick = () => {
87
+ const mode = this.measureController.getCurrentMode();
88
+ mode === 'Watch' ? this.measureController.changeMode('Edit') : this.measureController.save().changeMode('Watch');
89
+ };
90
+ editedLineChangeHandler = (lines) => {
91
+ // 线的数量大于 1 时,没有状态的变化
92
+ if (lines.length > 1)
93
+ return;
94
+ // 因为撤销导致的状态变更 -> 取消
95
+ if (lines.length === 0)
96
+ return this.change2Cancel(false);
97
+ this.change2Done();
98
+ };
99
+ modeChangeHandler = (mode) => {
100
+ mode === 'Watch' ? this.change2Add() : this.change2Cancel();
101
+ };
102
+ }
@@ -0,0 +1,12 @@
1
+ import MeasureController, { Mode } from '../../../Controller';
2
+ export default class Revoke {
3
+ private container;
4
+ private revokeIcon;
5
+ private revokeItem;
6
+ private measureController;
7
+ constructor(measureController: MeasureController, container: Element);
8
+ dispose(): void;
9
+ onClick: () => void;
10
+ onModeChange: (mode: Mode) => void;
11
+ handleRevoke: () => () => void;
12
+ }