Browse Source

chore:update

wxyyxc1992 5 years ago
parent
commit
86b62c707d
98 changed files with 21243 additions and 3736 deletions
  1. 0
    234
      dist/cjs/board/Whiteboard/index.js
  2. 6
    3
      dist/cjs/drawboard/Baseboard/index.js
  3. 168
    37
      dist/cjs/drawboard/Drawboard/index.js
  4. 0
    0
      dist/cjs/event/SyncEvent.js
  5. 0
    0
      dist/cjs/event/border-events.js
  6. 2
    0
      dist/cjs/event/marker-events.js
  7. 11
    2
      dist/cjs/index.js
  8. 3
    3
      dist/cjs/markers/ArrowMarker/index.js
  9. 93
    62
      dist/cjs/markers/BaseMarker/index.js
  10. 3
    3
      dist/cjs/markers/CoverMarker/index.js
  11. 3
    3
      dist/cjs/markers/HighlightMarker/index.js
  12. 3
    3
      dist/cjs/markers/LineMarker/index.js
  13. 46
    17
      dist/cjs/markers/LinearMarker/index.js
  14. 10
    3
      dist/cjs/markers/RectMarker/RectBaseMarker.js
  15. 3
    3
      dist/cjs/markers/RectMarker/index.js
  16. 66
    41
      dist/cjs/markers/RectangularMarker/index.js
  17. 20
    4
      dist/cjs/markers/TextMarker/index.js
  18. 41
    0
      dist/cjs/renderer/DomEventAware/index.js
  19. 1
    1
      dist/cjs/renderer/Synthetizer/index.js
  20. 58
    8
      dist/cjs/toolbar/Toolbar.js
  21. 18
    2
      dist/cjs/toolbar/ToolbarButton.js
  22. 8
    1
      dist/cjs/toolbar/ToolbarItem.js
  23. 31
    27
      dist/cjs/toolbar/toolbar-items.js
  24. 10
    0
      dist/cjs/utils/layout.js
  25. 6
    0
      dist/cjs/utils/types.js
  26. 206
    0
      dist/cjs/whiteboard/AbstractWhiteboard/index.js
  27. 20
    0
      dist/cjs/whiteboard/AbstractWhiteboard/snap.js
  28. 76
    0
      dist/cjs/whiteboard/MirrorWhiteboard/index.js
  29. 103
    0
      dist/cjs/whiteboard/ReplayWhiteboard/index.js
  30. 67
    30
      dist/cjs/whiteboard/WhitePage/index.js
  31. 159
    0
      dist/cjs/whiteboard/Whiteboard/index.js
  32. 18921
    2825
      dist/index.js
  33. 1
    1
      dist/index.js.map
  34. 0
    53
      dist/types/board/Drawboard/index.d.ts
  35. 0
    28
      dist/types/board/WhitePage/index.d.ts
  36. 0
    45
      dist/types/board/Whiteboard/index.d.ts
  37. 0
    5
      dist/types/board/types.d.ts
  38. 5
    4
      dist/types/drawboard/Baseboard/index.d.ts
  39. 64
    0
      dist/types/drawboard/Drawboard/index.d.ts
  40. 0
    11
      dist/types/event/Event.d.ts
  41. 15
    0
      dist/types/event/SyncEvent.d.ts
  42. 1
    0
      dist/types/event/border-events.d.ts
  43. 11
    0
      dist/types/event/marker-events.d.ts
  44. 8
    3
      dist/types/index.d.ts
  45. 2
    2
      dist/types/markers/ArrowMarker/index.d.ts
  46. 28
    23
      dist/types/markers/BaseMarker/index.d.ts
  47. 2
    2
      dist/types/markers/CoverMarker/index.d.ts
  48. 2
    2
      dist/types/markers/HighlightMarker/index.d.ts
  49. 2
    2
      dist/types/markers/LineMarker/index.d.ts
  50. 17
    12
      dist/types/markers/LinearMarker/index.d.ts
  51. 5
    3
      dist/types/markers/RectMarker/RectBaseMarker.d.ts
  52. 2
    2
      dist/types/markers/RectMarker/index.d.ts
  53. 11
    8
      dist/types/markers/RectangularMarker/index.d.ts
  54. 8
    5
      dist/types/markers/TextMarker/index.d.ts
  55. 6
    0
      dist/types/markers/types.d.ts
  56. 11
    0
      dist/types/renderer/DomEventAware/index.d.ts
  57. 1
    1
      dist/types/renderer/Synthetizer/index.d.ts
  58. 17
    5
      dist/types/toolbar/Toolbar.d.ts
  59. 6
    2
      dist/types/toolbar/ToolbarButton.d.ts
  60. 6
    7
      dist/types/toolbar/ToolbarItem.d.ts
  61. 4
    1
      dist/types/toolbar/toolbar-items.d.ts
  62. 5
    0
      dist/types/utils/layout.d.ts
  63. 6
    0
      dist/types/utils/types.d.ts
  64. 42
    0
      dist/types/whiteboard/AbstractWhiteboard/index.d.ts
  65. 32
    0
      dist/types/whiteboard/AbstractWhiteboard/snap.d.ts
  66. 8
    0
      dist/types/whiteboard/MirrorWhiteboard/index.d.ts
  67. 20
    0
      dist/types/whiteboard/ReplayWhiteboard/index.d.ts
  68. 30
    0
      dist/types/whiteboard/WhitePage/index.d.ts
  69. 10
    0
      dist/types/whiteboard/Whiteboard/index.d.ts
  70. 0
    0
      example/drawboard-fullscreen/index.ts
  71. 0
    0
      example/drawboard/index.ts
  72. 0
    27
      example/index.ts
  73. 0
    0
      example/mirror-whiteboard/index.ts
  74. 0
    0
      example/mirror/index.less
  75. 0
    32
      example/mirror/index.ts
  76. 0
    13
      example/whiteboard/index.ts
  77. 4
    0
      package.json
  78. 27
    0
      src/assets/finish.svg
  79. 1
    0
      src/assets/rollback-disable.svg
  80. 1
    0
      src/assets/rollback.svg
  81. 6
    3
      src/drawboard/Baseboard/index.ts
  82. 153
    29
      src/drawboard/Drawboard/index.ts
  83. 3
    1
      src/event/border-events.ts
  84. 8
    1
      src/markers/BaseMarker/index.ts
  85. 14
    4
      src/toolbar/Toolbar.ts
  86. 18
    1
      src/toolbar/ToolbarButton.ts
  87. 17
    2
      src/toolbar/ToolbarItem.ts
  88. 11
    0
      src/toolbar/index.less
  89. 24
    14
      src/toolbar/toolbar-items.ts
  90. 2
    0
      src/types.d.ts
  91. 9
    0
      src/utils/layout.ts
  92. 16
    0
      src/whiteboard/AbstractWhiteboard/index.less
  93. 115
    6
      src/whiteboard/AbstractWhiteboard/index.ts
  94. 9
    50
      src/whiteboard/MirrorWhiteboard/index.ts
  95. 1
    1
      src/whiteboard/ReplayWhiteboard/index.ts
  96. 32
    8
      src/whiteboard/WhitePage/index.ts
  97. 71
    4
      src/whiteboard/Whiteboard/index.ts
  98. 151
    1
      yarn.lock

+ 0
- 234
dist/cjs/board/Whiteboard/index.js View File

1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-var Siema = require("siema");
4
-var index_1 = require("../WhitePage/index");
5
-var uuid_1 = require("../../utils/uuid");
6
-var dom_1 = require("../../utils/dom");
7
-require("./index.less");
8
-var LeftArrowIcon = require('../../assets/bx-left-arrow.svg');
9
-var RightArrowIcon = require('../../assets/bx-right-arrow.svg');
10
-var prefix = 'fcw-board';
11
-var SerializableWhiteboard = (function () {
12
-    function SerializableWhiteboard() {
13
-    }
14
-    return SerializableWhiteboard;
15
-}());
16
-exports.SerializableWhiteboard = SerializableWhiteboard;
17
-var Whiteboard = (function () {
18
-    function Whiteboard(target, _a) {
19
-        var _b = _a === void 0 ? {} : _a, sources = _b.sources, eventHub = _b.eventHub, mode = _b.mode, visiblePageIndex = _b.visiblePageIndex;
20
-        this.id = uuid_1.uuid();
21
-        this.sources = [];
22
-        this.mode = 'master';
23
-        this.isFullscreen = false;
24
-        this.pages = [];
25
-        this.isInitialized = false;
26
-        this.isSyncing = false;
27
-        this.visiblePageIndex = 0;
28
-        if (target) {
29
-            this.target = target;
30
-        }
31
-        else {
32
-            this.target = document.createElement('div');
33
-            document.body.appendChild(this.target);
34
-        }
35
-        if (!this.target.id) {
36
-            this.target.id = this.id;
37
-        }
38
-        dom_1.addClassName(this.target, prefix);
39
-        if (sources) {
40
-            this.sources = sources;
41
-        }
42
-        this.eventHub = eventHub;
43
-        if (mode) {
44
-            this.mode = mode;
45
-        }
46
-        if (typeof visiblePageIndex !== 'undefined') {
47
-            this.visiblePageIndex = visiblePageIndex;
48
-        }
49
-        this.init();
50
-    }
51
-    Object.defineProperty(Whiteboard.prototype, "activePage", {
52
-        get: function () {
53
-            return this.pages[this.visiblePageIndex];
54
-        },
55
-        enumerable: true,
56
-        configurable: true
57
-    });
58
-    Whiteboard.prototype.open = function () {
59
-        var _this = this;
60
-        this.pages.forEach(function (page, i) {
61
-            page.open();
62
-            if (i !== _this.visiblePageIndex) {
63
-                page.hide();
64
-            }
65
-        });
66
-    };
67
-    Whiteboard.prototype.close = function () {
68
-        if (this.emitInterval) {
69
-            clearInterval(this.emitInterval);
70
-        }
71
-    };
72
-    Whiteboard.prototype.show = function () {
73
-        if (this.activePage) {
74
-            this.activePage.show();
75
-        }
76
-    };
77
-    Whiteboard.prototype.hide = function () {
78
-        if (this.activePage) {
79
-            this.activePage.hide();
80
-        }
81
-    };
82
-    Whiteboard.prototype.snap = function () {
83
-        return {
84
-            id: this.id,
85
-            sources: this.sources,
86
-            pageIds: this.pages.map(function (page) { return page.id; }),
87
-            visiblePageIndex: this.visiblePageIndex
88
-        };
89
-    };
90
-    Whiteboard.prototype.init = function () {
91
-        this.imgsContainer = dom_1.createDivWithClassName(prefix + "-imgs", this.target);
92
-        this.pagesContainer = dom_1.createDivWithClassName(prefix + "-pages", this.target);
93
-        if (this.mode === 'master') {
94
-            this.initMaster();
95
-            this.emitSnapshot();
96
-        }
97
-        if (this.mode === 'mirror') {
98
-            this.initMirror();
99
-        }
100
-    };
101
-    Whiteboard.prototype.initMaster = function () {
102
-        var _this = this;
103
-        this.sources.forEach(function (source) {
104
-            var page = new index_1.WhitePage({ imgSrc: source }, {
105
-                mode: _this.mode,
106
-                eventHub: _this.eventHub,
107
-                parentContainer: _this.pagesContainer
108
-            });
109
-            page.container.style.visibility = 'hidden';
110
-            _this.pages.push(page);
111
-        });
112
-        this.initSiema();
113
-        var controller = dom_1.createDivWithClassName(prefix + "-controller", this.target);
114
-        var prevEle = dom_1.createDivWithClassName(prefix + "-flip-arrow", controller);
115
-        prevEle.innerHTML = LeftArrowIcon;
116
-        var nextEle = dom_1.createDivWithClassName(prefix + "-flip-arrow", controller);
117
-        nextEle.innerHTML = RightArrowIcon;
118
-        nextEle.addEventListener('click', function () {
119
-            var nextPageIndex = _this.visiblePageIndex + 1 > _this.pages.length - 1 ? 0 : _this.visiblePageIndex + 1;
120
-            _this.onPageChange(nextPageIndex);
121
-        });
122
-        prevEle.addEventListener('click', function () {
123
-            var nextPageIndex = _this.visiblePageIndex - 1 < 0 ? _this.pages.length - 1 : _this.visiblePageIndex - 1;
124
-            _this.onPageChange(nextPageIndex);
125
-        });
126
-    };
127
-    Whiteboard.prototype.initMirror = function () {
128
-        var _this = this;
129
-        if (!this.eventHub) {
130
-            throw new Error('Invalid eventHub');
131
-        }
132
-        this.eventHub.on('sync', function (ev) {
133
-            if (ev.target !== 'whiteboard') {
134
-                return;
135
-            }
136
-            if (ev.event === 'snap') {
137
-                if (_this.isInitialized) {
138
-                    return;
139
-                }
140
-                _this.onSnapshot(ev.data);
141
-            }
142
-            if (ev.event === 'changeIndex' && ev.id === _this.id) {
143
-                if (_this.isInitialized) {
144
-                    _this.onPageChange(ev.data);
145
-                }
146
-            }
147
-        });
148
-    };
149
-    Whiteboard.prototype.initSiema = function () {
150
-        var _this = this;
151
-        this.sources.forEach(function (source) {
152
-            var imgEle = document.createElement('img');
153
-            dom_1.addClassName(imgEle, prefix + "-img");
154
-            imgEle.src = source;
155
-            imgEle.alt = 'Siema image';
156
-            _this.imgsContainer.appendChild(imgEle);
157
-        });
158
-        this.siema = new Siema({
159
-            selector: this.imgsContainer,
160
-            duration: 200,
161
-            easing: 'ease-out',
162
-            perPage: 1,
163
-            startIndex: 0,
164
-            draggable: false,
165
-            multipleDrag: true,
166
-            threshold: 20,
167
-            loop: false,
168
-            rtl: false
169
-        });
170
-    };
171
-    Whiteboard.prototype.onPageChange = function (nextPageIndex) {
172
-        this.siema.goTo(nextPageIndex);
173
-        this.visiblePageIndex = nextPageIndex;
174
-        this.pages.forEach(function (page, i) {
175
-            if (nextPageIndex === i) {
176
-                page.show();
177
-            }
178
-            else {
179
-                page.hide();
180
-            }
181
-        });
182
-        if (this.mode === 'master' && this.eventHub) {
183
-            this.eventHub.emit('sync', {
184
-                event: 'changeIndex',
185
-                id: this.id,
186
-                target: 'whiteboard',
187
-                data: nextPageIndex
188
-            });
189
-        }
190
-    };
191
-    Whiteboard.prototype.emitSnapshot = function () {
192
-        var _this = this;
193
-        var innerFunc = function () {
194
-            if (_this.eventHub) {
195
-                _this.eventHub.emit('sync', {
196
-                    event: 'snap',
197
-                    id: _this.id,
198
-                    target: 'whiteboard',
199
-                    data: _this.snap()
200
-                });
201
-            }
202
-        };
203
-        this.emitInterval = setInterval(function () {
204
-            innerFunc();
205
-        }, 5 * 1000);
206
-        setTimeout(innerFunc, 500);
207
-    };
208
-    Whiteboard.prototype.onSnapshot = function (snap) {
209
-        var _this = this;
210
-        var id = snap.id, sources = snap.sources, pageIds = snap.pageIds, visiblePageIndex = snap.visiblePageIndex;
211
-        if (!this.isInitialized && !this.isSyncing) {
212
-            this.id = id;
213
-            this.sources = sources;
214
-            this.isSyncing = true;
215
-            this.sources.forEach(function (source, i) {
216
-                var page = new index_1.WhitePage({ imgSrc: source }, {
217
-                    mode: _this.mode,
218
-                    eventHub: _this.eventHub,
219
-                    parentContainer: _this.pagesContainer
220
-                });
221
-                page.id = pageIds[i];
222
-                page.container.style.visibility = 'hidden';
223
-                _this.pages.push(page);
224
-                page.open();
225
-            });
226
-            this.initSiema();
227
-        }
228
-        this.isInitialized = true;
229
-        this.isSyncing = false;
230
-        this.onPageChange(visiblePageIndex);
231
-    };
232
-    return Whiteboard;
233
-}());
234
-exports.Whiteboard = Whiteboard;

dist/cjs/board/Baseboard/index.js → dist/cjs/drawboard/Baseboard/index.js View File

6
     function Baseboard(source) {
6
     function Baseboard(source) {
7
         var _this = this;
7
         var _this = this;
8
         this.id = uuid_1.uuid();
8
         this.id = uuid_1.uuid();
9
-        this.initBoard = function () {
9
+        this.isFullscreen = false;
10
+        this.initBoard = function (mountContainer) {
10
             _this.boardHolder = document.createElement('div');
11
             _this.boardHolder = document.createElement('div');
11
             _this.boardHolder.id = "fcw-board-holder-" + _this.id;
12
             _this.boardHolder.id = "fcw-board-holder-" + _this.id;
13
+            _this.boardHolder.className = "fcw-board-holder";
14
+            _this.boardHolder.style.zIndex = '999';
12
             _this.boardHolder.style.setProperty('touch-action', 'none');
15
             _this.boardHolder.style.setProperty('touch-action', 'none');
13
             _this.boardHolder.style.setProperty('-ms-touch-action', 'none');
16
             _this.boardHolder.style.setProperty('-ms-touch-action', 'none');
14
-            document.body.appendChild(_this.boardHolder);
17
+            mountContainer.appendChild(_this.boardHolder);
15
             _this.boardCanvas = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
18
             _this.boardCanvas = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
16
             _this.boardCanvas.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
19
             _this.boardCanvas.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
17
             _this.boardCanvas.setAttribute('width', _this.width.toString());
20
             _this.boardCanvas.setAttribute('width', _this.width.toString());
18
             _this.boardCanvas.setAttribute('height', _this.height.toString());
21
             _this.boardCanvas.setAttribute('height', _this.height.toString());
19
             _this.boardCanvas.setAttribute('viewBox', '0 0 ' + _this.width.toString() + ' ' + _this.height.toString());
22
             _this.boardCanvas.setAttribute('viewBox', '0 0 ' + _this.width.toString() + ' ' + _this.height.toString());
20
-            _this.boardHolder.style.position = 'absolute';
23
+            _this.boardHolder.style.position = 'fixed';
21
             _this.boardHolder.style.width = _this.width + "px";
24
             _this.boardHolder.style.width = _this.width + "px";
22
             _this.boardHolder.style.height = _this.height + "px";
25
             _this.boardHolder.style.height = _this.height + "px";
23
             _this.boardHolder.style.transformOrigin = 'top left';
26
             _this.boardHolder.style.transformOrigin = 'top left';

dist/cjs/board/Drawboard/index.js → dist/cjs/drawboard/Drawboard/index.js View File

13
     };
13
     };
14
 })();
14
 })();
15
 Object.defineProperty(exports, "__esModule", { value: true });
15
 Object.defineProperty(exports, "__esModule", { value: true });
16
+var fc_hotkeys_1 = require("fc-hotkeys");
17
+var debounce = require("lodash.debounce");
16
 var index_1 = require("./../Baseboard/index");
18
 var index_1 = require("./../Baseboard/index");
17
 var toolbar_items_1 = require("./../../toolbar/toolbar-items");
19
 var toolbar_items_1 = require("./../../toolbar/toolbar-items");
18
 var Synthetizer_1 = require("../../renderer/Synthetizer");
20
 var Synthetizer_1 = require("../../renderer/Synthetizer");
19
 var Toolbar_1 = require("../../toolbar/Toolbar");
21
 var Toolbar_1 = require("../../toolbar/Toolbar");
20
 require("./index.less");
22
 require("./index.less");
23
+var layout_1 = require("../../utils/layout");
24
+var index_2 = require("../../markers/RectMarker/index");
25
+var index_3 = require("../../markers/HighlightMarker/index");
26
+var index_4 = require("../../markers/CoverMarker/index");
27
+var index_5 = require("../../markers/LineMarker/index");
28
+var index_6 = require("../../markers/ArrowMarker/index");
29
+var index_7 = require("../../markers/TextMarker/index");
21
 var Drawboard = (function (_super) {
30
 var Drawboard = (function (_super) {
22
     __extends(Drawboard, _super);
31
     __extends(Drawboard, _super);
23
     function Drawboard(source, _a) {
32
     function Drawboard(source, _a) {
24
-        var _b = _a === void 0 ? {} : _a, page = _b.page, onChange = _b.onChange;
33
+        var _b = _a === void 0 ? {} : _a, _c = _b.allowKeyboard, allowKeyboard = _c === void 0 ? true : _c, extraToolbarItems = _b.extraToolbarItems, mountContainer = _b.mountContainer, page = _b.page, zIndex = _b.zIndex, onChange = _b.onChange;
25
         var _this = _super.call(this, source) || this;
34
         var _this = _super.call(this, source) || this;
35
+        _this.mountContainer = document.body;
26
         _this.scale = 1.0;
36
         _this.scale = 1.0;
37
+        _this.zIndex = 999;
38
+        _this.allowKeyboard = true;
27
         _this.onComplete = function () { };
39
         _this.onComplete = function () { };
28
         _this.onChange = function () { };
40
         _this.onChange = function () { };
29
         _this.open = function (onComplete, onCancel) {
41
         _this.open = function (onComplete, onCancel) {
34
                 _this.onCancel = onCancel;
46
                 _this.onCancel = onCancel;
35
             }
47
             }
36
             _this.setTargetRect();
48
             _this.setTargetRect();
37
-            _this.initBoard();
49
+            _this.initBoard(_this.mountContainer);
38
             _this.attachEvents();
50
             _this.attachEvents();
39
             _this.setStyles();
51
             _this.setStyles();
40
             window.addEventListener('resize', _this.adjustUI);
52
             window.addEventListener('resize', _this.adjustUI);
41
-            if (_this.page.mode === 'master') {
53
+            if ((_this.page && _this.page.mode === 'master') || !_this.page) {
42
                 _this.showUI();
54
                 _this.showUI();
43
             }
55
             }
44
         };
56
         };
57
                 _this.target.style.display = 'block';
69
                 _this.target.style.display = 'block';
58
             }
70
             }
59
             _this.boardHolder.style.visibility = 'visible';
71
             _this.boardHolder.style.visibility = 'visible';
60
-            _this.boardHolder.style.zIndex = '9999';
72
+            _this.boardHolder.style.zIndex = "" + _this.zIndex;
61
             if (_this.toolbar) {
73
             if (_this.toolbar) {
62
                 _this.toolbar.show();
74
                 _this.toolbar.show();
63
             }
75
             }
64
         };
76
         };
65
-        _this.close = function () {
77
+        _this.destroy = function () {
66
             if (_this.toolbarUI) {
78
             if (_this.toolbarUI) {
67
-                document.body.removeChild(_this.toolbarUI);
79
+                _this.mountContainer.removeChild(_this.toolbarUI);
68
             }
80
             }
69
             if (_this.boardCanvas) {
81
             if (_this.boardCanvas) {
70
-                document.body.removeChild(_this.boardHolder);
82
+                _this.mountContainer.removeChild(_this.boardHolder);
83
+            }
84
+            if (_this.listener) {
85
+                _this.listener.reset();
71
             }
86
             }
72
         };
87
         };
73
         _this.render = function (onComplete, onCancel) {
88
         _this.render = function (onComplete, onCancel) {
79
             _this.startRender(_this.renderFinished);
94
             _this.startRender(_this.renderFinished);
80
         };
95
         };
81
         _this.addMarker = function (markerType, _a) {
96
         _this.addMarker = function (markerType, _a) {
82
-            var id = (_a === void 0 ? {} : _a).id;
97
+            var _b = _a === void 0 ? {} : _a, id = _b.id, originX = _b.originX, originY = _b.originY;
83
             var marker = markerType.createMarker(_this.page);
98
             var marker = markerType.createMarker(_this.page);
84
             if (id) {
99
             if (id) {
85
                 marker.id = id;
100
                 marker.id = id;
86
             }
101
             }
102
+            marker.drawboard = _this;
87
             marker.onSelected = _this.selectMarker;
103
             marker.onSelected = _this.selectMarker;
88
             marker.onChange = _this.onChange;
104
             marker.onChange = _this.onChange;
89
             if (marker.defs && marker.defs.length > 0) {
105
             if (marker.defs && marker.defs.length > 0) {
90
-                for (var _i = 0, _b = marker.defs; _i < _b.length; _i++) {
91
-                    var d = _b[_i];
106
+                for (var _i = 0, _c = marker.defs; _i < _c.length; _i++) {
107
+                    var d = _c[_i];
92
                     if (d.id && !_this.boardCanvas.getElementById(d.id)) {
108
                     if (d.id && !_this.boardCanvas.getElementById(d.id)) {
93
                         _this.defs.appendChild(d);
109
                         _this.defs.appendChild(d);
94
                     }
110
                     }
95
                 }
111
                 }
96
             }
112
             }
113
+            _this.markers.push(marker);
114
+            _this.selectMarker(marker);
115
+            _this.boardCanvas.appendChild(marker.visual);
116
+            var x;
117
+            var y;
118
+            if (originX && originY) {
119
+                x = originX;
120
+                y = originY;
121
+            }
122
+            else {
123
+                var bbox = marker.visual.getBBox();
124
+                x = _this.width / 2 / _this.scale - bbox.width / 2;
125
+                y = _this.height / 2 / _this.scale - bbox.height / 2;
126
+            }
97
             _this.onChange({
127
             _this.onChange({
98
                 target: 'marker',
128
                 target: 'marker',
99
                 parentId: _this.page ? _this.page.id : _this.id,
129
                 parentId: _this.page ? _this.page.id : _this.id,
100
-                event: 'add',
101
-                data: { type: marker.type, id: marker.id }
130
+                event: 'addMarker',
131
+                marker: { type: marker.type, id: marker.id, dx: x, dy: y }
102
             });
132
             });
103
-            _this.markers.push(marker);
104
-            _this.selectMarker(marker);
105
-            _this.boardCanvas.appendChild(marker.visual);
106
-            var bbox = marker.visual.getBBox();
107
-            var x = _this.width / 2 / _this.scale - bbox.width / 2;
108
-            var y = _this.height / 2 / _this.scale - bbox.height / 2;
109
-            var translate = marker.visual.transform.baseVal.getItem(0);
110
-            translate.setMatrix(translate.matrix.translate(x, y));
111
-            marker.visual.transform.baseVal.replaceItem(translate, 0);
133
+            marker.moveTo(x, y);
134
+            return marker;
112
         };
135
         };
113
         _this.deleteActiveMarker = function () {
136
         _this.deleteActiveMarker = function () {
114
-            if (_this.activeMarker) {
137
+            _this.deleteMarkerWithEvent(_this.activeMarker);
138
+        };
139
+        _this.clearMarkers = function () {
140
+            _this.markers.slice().forEach(function (marker) {
141
+                _this.deleteMarkerWithEvent(marker);
142
+            });
143
+        };
144
+        _this.deleteMarkerWithEvent = function (marker) {
145
+            if (marker) {
115
                 if (_this.onChange) {
146
                 if (_this.onChange) {
116
                     _this.onChange({
147
                     _this.onChange({
117
-                        event: 'remove',
118
-                        id: _this.activeMarker.id,
148
+                        event: 'removeMarker',
149
+                        id: marker.id,
119
                         target: 'marker',
150
                         target: 'marker',
120
-                        data: { id: _this.activeMarker.id }
151
+                        marker: { id: marker.id }
121
                     });
152
                     });
122
                 }
153
                 }
123
-                _this.deleteMarker(_this.activeMarker);
154
+                _this.deleteMarker(marker);
124
             }
155
             }
125
         };
156
         };
126
         _this.setTargetRect = function () {
157
         _this.setTargetRect = function () {
156
                 _this.activeMarker.endManipulation();
187
                 _this.activeMarker.endManipulation();
157
             }
188
             }
158
         };
189
         };
190
+        _this.onKeyboard = function (e, _a) {
191
+            var hotkey = _a.hotkey;
192
+            switch (hotkey) {
193
+                case 'Shift+R':
194
+                    _this.addMarker(index_2.RectMarker);
195
+                    return;
196
+                case 'Shift+H':
197
+                    _this.addMarker(index_3.HighlightMarker);
198
+                    return;
199
+                case 'Shift+C':
200
+                    _this.addMarker(index_4.CoverMarker);
201
+                    return;
202
+                case 'Shift+L':
203
+                    _this.addMarker(index_5.LineMarker);
204
+                    return;
205
+                case 'Shift+A':
206
+                    _this.addMarker(index_6.ArrowMarker);
207
+                    return;
208
+                case 'Shift+T':
209
+                    _this.addMarker(index_7.TextMarker);
210
+                    return;
211
+                case 'ESC':
212
+                    _this.page.whiteboard.rollbackSnap();
213
+                    return;
214
+                default:
215
+                    break;
216
+            }
217
+            if (!_this.activeMarker) {
218
+                return;
219
+            }
220
+            switch (hotkey) {
221
+                case 'UP':
222
+                    _this.activeMarker.move(0, -10);
223
+                    return;
224
+                case 'LEFT':
225
+                    _this.activeMarker.move(-10, 0);
226
+                    return;
227
+                case 'RIGHT':
228
+                    _this.activeMarker.move(10, 0);
229
+                    return;
230
+                case 'DOWN':
231
+                    _this.activeMarker.move(0, 10);
232
+                    return;
233
+                case 'BACKSPACE':
234
+                    _this.deleteActiveMarker();
235
+                    return;
236
+                default:
237
+                    return;
238
+            }
239
+        };
159
         _this.adjustUI = function (ev) {
240
         _this.adjustUI = function (ev) {
160
             _this.adjustSize();
241
             _this.adjustSize();
161
             _this.positionUI();
242
             _this.positionUI();
177
             _this.positionToolbar();
258
             _this.positionToolbar();
178
         };
259
         };
179
         _this.positionToolbar = function () {
260
         _this.positionToolbar = function () {
180
-            _this.toolbarUI.style.left = _this.targetRect.left +
181
-                _this.target.offsetWidth -
182
-                _this.toolbarUI.clientWidth + "px";
183
-            _this.toolbarUI.style.top = _this.targetRect.top - _this.toolbarUI.clientHeight + "px";
261
+            if (_this.toolbarUI && _this.targetRect) {
262
+                _this.toolbarUI.style.left = _this.targetRect.left +
263
+                    _this.target.offsetWidth -
264
+                    _this.toolbarUI.clientWidth + "px";
265
+                _this.toolbarUI.style.top = _this.targetRect.top - _this.toolbarUI.clientHeight + "px";
266
+            }
184
         };
267
         };
185
         _this.showUI = function () {
268
         _this.showUI = function () {
186
-            _this.toolbar = new Toolbar_1.Toolbar(_this.toolbars, _this.toolbarClick);
187
-            _this.toolbarUI = _this.toolbar.getUI();
188
-            document.body.appendChild(_this.toolbarUI);
269
+            _this.toolbar = new Toolbar_1.Toolbar(_this.toolbarItems, _this.toolbarClick);
270
+            _this.toolbar.zIndex = _this.zIndex + 1;
271
+            _this.toolbarUI = _this.toolbar.getUI(_this);
272
+            _this.boardHolder.appendChild(_this.toolbarUI);
189
             _this.toolbarUI.style.position = 'absolute';
273
             _this.toolbarUI.style.position = 'absolute';
190
             _this.positionToolbar();
274
             _this.positionToolbar();
275
+            _this.toolbar.show();
276
+            _this.toolbar.toolbarButtons.forEach(function (button) {
277
+                if (button.toolbarItem.draggable) {
278
+                    button.container.draggable = true;
279
+                    button.container.ondragstart = function (ev) {
280
+                        if (ev) {
281
+                            ev.dataTransfer.setData('id', button.id);
282
+                        }
283
+                    };
284
+                }
285
+            });
286
+            _this.boardCanvas.ondragover = function (ev) {
287
+                ev.preventDefault();
288
+            };
289
+            _this.boardCanvas.ondrop = function (ev) {
290
+                var markerX = ev.x;
291
+                var markerY = ev.y;
292
+                var rect = _this.boardHolder.getBoundingClientRect();
293
+                if (layout_1.rectContains(rect, { x: markerX, y: markerY })) {
294
+                    var buttonId = ev.dataTransfer.getData('id');
295
+                    var button = _this.toolbar.toolbarButtonMap[buttonId];
296
+                    if (button.toolbarItem && button.toolbarItem.markerType) {
297
+                        _this.addMarker(button.toolbarItem.markerType, {
298
+                            originX: markerX - rect.left,
299
+                            originY: markerY - rect.top
300
+                        });
301
+                    }
302
+                }
303
+            };
191
         };
304
         };
192
         _this.setStyles = function () {
305
         _this.setStyles = function () {
193
             var editorStyleSheet = document.createElementNS('http://www.w3.org/2000/svg', 'style');
306
             var editorStyleSheet = document.createElementNS('http://www.w3.org/2000/svg', 'style');
195
             _this.boardCanvas.appendChild(editorStyleSheet);
308
             _this.boardCanvas.appendChild(editorStyleSheet);
196
         };
309
         };
197
         _this.toolbarClick = function (ev, toolbarItem) {
310
         _this.toolbarClick = function (ev, toolbarItem) {
198
-            if (toolbarItem.markerType) {
311
+            if (toolbarItem.onClick) {
312
+                toolbarItem.onClick();
313
+            }
314
+            else if (toolbarItem.markerType) {
199
                 _this.addMarker(toolbarItem.markerType);
315
                 _this.addMarker(toolbarItem.markerType);
200
             }
316
             }
201
             else {
317
             else {
241
             _this.startRender(_this.renderFinishedClose);
357
             _this.startRender(_this.renderFinishedClose);
242
         };
358
         };
243
         _this.cancel = function () {
359
         _this.cancel = function () {
244
-            _this.close();
360
+            _this.destroy();
245
             if (_this.onCancel) {
361
             if (_this.onCancel) {
246
                 _this.onCancel();
362
                 _this.onCancel();
247
             }
363
             }
250
             _this.onComplete(dataUrl);
366
             _this.onComplete(dataUrl);
251
         };
367
         };
252
         _this.renderFinishedClose = function (dataUrl) {
368
         _this.renderFinishedClose = function (dataUrl) {
253
-            _this.close();
369
+            _this.destroy();
254
             _this.onComplete(dataUrl);
370
             _this.onComplete(dataUrl);
255
         };
371
         };
256
         if (page) {
372
         if (page) {
257
             _this.page = page;
373
             _this.page = page;
258
         }
374
         }
375
+        if (zIndex) {
376
+            _this.zIndex = zIndex;
377
+        }
378
+        _this.allowKeyboard = allowKeyboard;
259
         _this.markers = [];
379
         _this.markers = [];
260
         _this.activeMarker = null;
380
         _this.activeMarker = null;
261
-        _this.toolbars = toolbar_items_1.getToolbars(page);
381
+        var toolbarItems = toolbar_items_1.getToolbars(page);
382
+        if (extraToolbarItems) {
383
+            toolbarItems.push.apply(toolbarItems, extraToolbarItems);
384
+        }
385
+        _this.toolbarItems = toolbarItems;
262
         if (onChange) {
386
         if (onChange) {
263
             _this.onChange = onChange;
387
             _this.onChange = onChange;
264
         }
388
         }
389
+        if (allowKeyboard && _this.page && _this.page.mode === 'master') {
390
+            _this.listener = new fc_hotkeys_1.HotkeysListener();
391
+            _this.listener.on(fc_hotkeys_1.KEY_ALL, debounce(_this.onKeyboard, 150));
392
+        }
393
+        if (mountContainer) {
394
+            _this.mountContainer = mountContainer;
395
+        }
265
         return _this;
396
         return _this;
266
     }
397
     }
267
     Object.defineProperty(Drawboard.prototype, "markerMap", {
398
     Object.defineProperty(Drawboard.prototype, "markerMap", {

dist/cjs/board/types.js → dist/cjs/event/SyncEvent.js View File


dist/cjs/event/Event.js → dist/cjs/event/border-events.js View File


+ 2
- 0
dist/cjs/event/marker-events.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });

+ 11
- 2
dist/cjs/index.js View File

1
 "use strict";
1
 "use strict";
2
 Object.defineProperty(exports, "__esModule", { value: true });
2
 Object.defineProperty(exports, "__esModule", { value: true });
3
-var Drawboard_1 = require("./board/Drawboard");
3
+var Drawboard_1 = require("./drawboard/Drawboard");
4
 exports.Drawboard = Drawboard_1.Drawboard;
4
 exports.Drawboard = Drawboard_1.Drawboard;
5
-var Whiteboard_1 = require("./board/Whiteboard");
5
+var toolbar_items_1 = require("./toolbar/toolbar-items");
6
+exports.separatorToolbarItem = toolbar_items_1.separatorToolbarItem;
7
+exports.closeToolbarItem = toolbar_items_1.closeToolbarItem;
8
+var EventHub_1 = require("./event/EventHub");
9
+exports.EventHub = EventHub_1.EventHub;
10
+var Whiteboard_1 = require("./whiteboard/Whiteboard");
6
 exports.Whiteboard = Whiteboard_1.Whiteboard;
11
 exports.Whiteboard = Whiteboard_1.Whiteboard;
12
+var MirrorWhiteboard_1 = require("./whiteboard/MirrorWhiteboard");
13
+exports.MirrorWhiteboard = MirrorWhiteboard_1.MirrorWhiteboard;
14
+var ReplayWhiteboard_1 = require("./whiteboard/ReplayWhiteboard");
15
+exports.ReplayWhiteboard = ReplayWhiteboard_1.ReplayWhiteboard;

+ 3
- 3
dist/cjs/markers/ArrowMarker/index.js View File

23
         _this.ARROW_SIZE = 6;
23
         _this.ARROW_SIZE = 6;
24
         return _this;
24
         return _this;
25
     }
25
     }
26
-    ArrowMarker.prototype.setup = function () {
27
-        _super.prototype.setup.call(this);
26
+    ArrowMarker.prototype.init = function () {
27
+        _super.prototype.init.call(this);
28
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'arrow-marker']]);
28
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'arrow-marker']]);
29
         var tip = SvgHelper_1.SvgHelper.createPolygon("0,0 " + this.ARROW_SIZE + "," + this.ARROW_SIZE / 2 + " 0," + this.ARROW_SIZE, [['class', 'arrow-marker-tip']]);
29
         var tip = SvgHelper_1.SvgHelper.createPolygon("0,0 " + this.ARROW_SIZE + "," + this.ARROW_SIZE / 2 + " 0," + this.ARROW_SIZE, [['class', 'arrow-marker-tip']]);
30
         this.defs.push(SvgHelper_1.SvgHelper.createMarker('arrow-marker-head', 'auto', this.ARROW_SIZE, this.ARROW_SIZE, this.ARROW_SIZE - 1, this.ARROW_SIZE / 2, tip));
30
         this.defs.push(SvgHelper_1.SvgHelper.createMarker('arrow-marker-head', 'auto', this.ARROW_SIZE, this.ARROW_SIZE, this.ARROW_SIZE - 1, this.ARROW_SIZE / 2, tip));
33
     ArrowMarker.createMarker = function (page) {
33
     ArrowMarker.createMarker = function (page) {
34
         var marker = new ArrowMarker();
34
         var marker = new ArrowMarker();
35
         marker.page = page;
35
         marker.page = page;
36
-        marker.setup();
36
+        marker.init();
37
         return marker;
37
         return marker;
38
     };
38
     };
39
     return ArrowMarker;
39
     return ArrowMarker;

+ 93
- 62
dist/cjs/markers/BaseMarker/index.js View File

1
 "use strict";
1
 "use strict";
2
+var __extends = (this && this.__extends) || (function () {
3
+    var extendStatics = function (d, b) {
4
+        extendStatics = Object.setPrototypeOf ||
5
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+        return extendStatics(d, b);
8
+    };
9
+    return function (d, b) {
10
+        extendStatics(d, b);
11
+        function __() { this.constructor = d; }
12
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+    };
14
+})();
2
 Object.defineProperty(exports, "__esModule", { value: true });
15
 Object.defineProperty(exports, "__esModule", { value: true });
3
 var uuid = require("uuid/v1");
16
 var uuid = require("uuid/v1");
4
 var SvgHelper_1 = require("../../renderer/SvgHelper");
17
 var SvgHelper_1 = require("../../renderer/SvgHelper");
5
-var BaseMarker = (function () {
18
+var index_1 = require("../../renderer/DomEventAware/index");
19
+var types_1 = require("../../utils/types");
20
+var BaseMarker = (function (_super) {
21
+    __extends(BaseMarker, _super);
6
     function BaseMarker() {
22
     function BaseMarker() {
7
-        var _this = this;
8
-        this.id = uuid();
9
-        this.type = 'base';
10
-        this.onChange = function () { };
11
-        this.defs = [];
12
-        this.width = 200;
13
-        this.height = 50;
14
-        this.isActive = true;
15
-        this.isDragging = false;
16
-        this.isResizing = false;
17
-        this.previousMouseX = 0;
18
-        this.previousMouseY = 0;
19
-        this.manipulate = function (ev) {
23
+        var _this = _super !== null && _super.apply(this, arguments) || this;
24
+        _this.id = uuid();
25
+        _this.type = 'base';
26
+        _this.onChange = function () { };
27
+        _this.defs = [];
28
+        _this.width = 200;
29
+        _this.height = 50;
30
+        _this.isActive = true;
31
+        _this.isDragging = false;
32
+        _this.isResizing = false;
33
+        _this.manipulate = function (ev) {
20
             var scale = _this.visual.getScreenCTM().a;
34
             var scale = _this.visual.getScreenCTM().a;
21
             var dx = (ev.screenX - _this.previousMouseX) / scale;
35
             var dx = (ev.screenX - _this.previousMouseX) / scale;
22
             var dy = (ev.screenY - _this.previousMouseY) / scale;
36
             var dy = (ev.screenY - _this.previousMouseY) / scale;
23
             if (_this.isDragging) {
37
             if (_this.isDragging) {
24
-                _this.onChange({ target: 'marker', id: _this.id, event: 'move', data: { dx: dx, dy: dy } });
25
                 _this.move(dx, dy);
38
                 _this.move(dx, dy);
26
             }
39
             }
27
             if (_this.isResizing) {
40
             if (_this.isResizing) {
28
                 _this.resize(dx, dy, function (pos) {
41
                 _this.resize(dx, dy, function (pos) {
29
-                    _this.onChange({ target: 'marker', id: _this.id, event: 'resize', data: { dx: dx, dy: dy, pos: pos } });
42
+                    _this.onChange({
43
+                        target: 'marker',
44
+                        id: _this.id,
45
+                        event: 'resizeMarker',
46
+                        marker: { dx: dx, dy: dy, pos: pos }
47
+                    });
30
                 });
48
                 });
31
             }
49
             }
32
             _this.previousMouseX = ev.screenX;
50
             _this.previousMouseX = ev.screenX;
33
             _this.previousMouseY = ev.screenY;
51
             _this.previousMouseY = ev.screenY;
34
         };
52
         };
35
-        this.addToVisual = function (el) {
53
+        _this.move = function (dx, dy) {
54
+            var translate = _this.visual.transform.baseVal.getItem(0);
55
+            translate.setMatrix(translate.matrix.translate(dx, dy));
56
+            _this.visual.transform.baseVal.replaceItem(translate, 0);
57
+            _this.x += dx;
58
+            _this.y += dy;
59
+            _this.onChange({ target: 'marker', id: _this.id, event: 'moveMarker', marker: { dx: dx, dy: dy } });
60
+        };
61
+        _this.moveTo = function (x, y) {
62
+            var translate = _this.visual.transform.baseVal.getItem(0);
63
+            translate.setMatrix(translate.matrix.translate(x - _this.x, y - _this.y));
64
+            _this.visual.transform.baseVal.replaceItem(translate, 0);
65
+            _this.x = x;
66
+            _this.y = y;
67
+        };
68
+        _this.addToVisual = function (el) {
36
             _this.visual.appendChild(el);
69
             _this.visual.appendChild(el);
37
         };
70
         };
38
-        this.addToRenderVisual = function (el) {
71
+        _this.addToRenderVisual = function (el) {
39
             _this.renderVisual.appendChild(el);
72
             _this.renderVisual.appendChild(el);
40
         };
73
         };
41
-        this.mouseDown = function (ev) {
74
+        _this.onMouseDown = function (ev) {
42
             ev.stopPropagation();
75
             ev.stopPropagation();
43
             if (_this.page && _this.page.mode === 'mirror') {
76
             if (_this.page && _this.page.mode === 'mirror') {
44
                 return;
77
                 return;
48
             _this.previousMouseX = ev.screenX;
81
             _this.previousMouseX = ev.screenX;
49
             _this.previousMouseY = ev.screenY;
82
             _this.previousMouseY = ev.screenY;
50
         };
83
         };
51
-        this.mouseUp = function (ev) {
84
+        _this.onMouseUp = function (ev) {
52
             ev.stopPropagation();
85
             ev.stopPropagation();
53
             _this.endManipulation();
86
             _this.endManipulation();
54
         };
87
         };
55
-        this.mouseMove = function (ev) {
88
+        _this.onMouseMove = function (ev) {
56
             ev.stopPropagation();
89
             ev.stopPropagation();
57
             _this.manipulate(ev);
90
             _this.manipulate(ev);
58
         };
91
         };
59
-        this.move = function (dx, dy) {
60
-            var translate = _this.visual.transform.baseVal.getItem(0);
61
-            translate.setMatrix(translate.matrix.translate(dx, dy));
62
-            _this.visual.transform.baseVal.replaceItem(translate, 0);
63
-        };
92
+        return _this;
64
     }
93
     }
65
     BaseMarker.prototype.reactToManipulation = function (type, _a) {
94
     BaseMarker.prototype.reactToManipulation = function (type, _a) {
66
-        var dx = _a.dx, dy = _a.dy, pos = _a.pos;
67
-        if (type === 'move') {
95
+        var _b = _a === void 0 ? {} : _a, dx = _b.dx, dy = _b.dy, pos = _b.pos;
96
+        if (type === 'moveMarker') {
97
+            if (types_1.isNil(dx) || types_1.isNil(dy)) {
98
+                return;
99
+            }
68
             this.move(dx, dy);
100
             this.move(dx, dy);
69
         }
101
         }
70
-        if (type === 'resize') {
102
+        if (type === 'resizeMarker') {
103
+            if (types_1.isNil(dx) || types_1.isNil(dy)) {
104
+                return;
105
+            }
71
             this.resizeByEvent(dx, dy, pos);
106
             this.resizeByEvent(dx, dy, pos);
72
         }
107
         }
73
     };
108
     };
87
         this.endManipulation();
122
         this.endManipulation();
88
         return;
123
         return;
89
     };
124
     };
90
-    BaseMarker.prototype.setup = function () {
91
-        this.visual = SvgHelper_1.SvgHelper.createGroup();
92
-        this.visual.transform.baseVal.appendItem(SvgHelper_1.SvgHelper.createTransform());
93
-        this.visual.addEventListener('mousedown', this.mouseDown);
94
-        this.visual.addEventListener('mouseup', this.mouseUp);
95
-        this.visual.addEventListener('mousemove', this.mouseMove);
96
-        this.visual.addEventListener('touchstart', this.onTouch, { passive: false });
97
-        this.visual.addEventListener('touchend', this.onTouch, { passive: false });
98
-        this.visual.addEventListener('touchmove', this.onTouch, { passive: false });
99
-        this.renderVisual = SvgHelper_1.SvgHelper.createGroup([['class', 'render-visual']]);
100
-        this.visual.appendChild(this.renderVisual);
125
+    BaseMarker.prototype.captureSnap = function () {
126
+        return {
127
+            id: this.id,
128
+            type: this.type,
129
+            isActive: this.isActive,
130
+            x: this.x,
131
+            y: this.y
132
+        };
133
+    };
134
+    BaseMarker.prototype.applySnap = function (snap) {
135
+        this.id = snap.id;
136
+        this.type = snap.type;
137
+        if (snap.x && snap.y) {
138
+            this.moveTo(snap.x, snap.y);
139
+        }
140
+        if (this.isActive) {
141
+            this.select();
142
+        }
143
+    };
144
+    BaseMarker.prototype.destroy = function () {
145
+        this.visual.style.display = 'none';
101
     };
146
     };
102
     BaseMarker.prototype.resize = function (x, y, cb) {
147
     BaseMarker.prototype.resize = function (x, y, cb) {
103
         return;
148
         return;
105
     BaseMarker.prototype.resizeByEvent = function (x, y, pos) {
150
     BaseMarker.prototype.resizeByEvent = function (x, y, pos) {
106
         return;
151
         return;
107
     };
152
     };
108
-    BaseMarker.prototype.onTouch = function (ev) {
109
-        ev.preventDefault();
110
-        var newEvt = document.createEvent('MouseEvents');
111
-        var touch = ev.changedTouches[0];
112
-        var type = null;
113
-        switch (ev.type) {
114
-            case 'touchstart':
115
-                type = 'mousedown';
116
-                break;
117
-            case 'touchmove':
118
-                type = 'mousemove';
119
-                break;
120
-            case 'touchend':
121
-                type = 'mouseup';
122
-                break;
123
-            default:
124
-                break;
125
-        }
126
-        newEvt.initMouseEvent(type, true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey, 0, null);
127
-        ev.target.dispatchEvent(newEvt);
153
+    BaseMarker.prototype.init = function () {
154
+        this.visual = SvgHelper_1.SvgHelper.createGroup();
155
+        this.visual.transform.baseVal.appendItem(SvgHelper_1.SvgHelper.createTransform());
156
+        _super.prototype.init.call(this, this.visual);
157
+        this.renderVisual = SvgHelper_1.SvgHelper.createGroup([['class', 'render-visual']]);
158
+        this.visual.appendChild(this.renderVisual);
128
     };
159
     };
129
     BaseMarker.createMarker = function (page) {
160
     BaseMarker.createMarker = function (page) {
130
         var marker = new BaseMarker();
161
         var marker = new BaseMarker();
131
         marker.page = page;
162
         marker.page = page;
132
-        marker.setup();
163
+        marker.init();
133
         return marker;
164
         return marker;
134
     };
165
     };
135
     return BaseMarker;
166
     return BaseMarker;
136
-}());
167
+}(index_1.DomEventAware));
137
 exports.BaseMarker = BaseMarker;
168
 exports.BaseMarker = BaseMarker;

+ 3
- 3
dist/cjs/markers/CoverMarker/index.js View File

22
         _this.type = 'cover';
22
         _this.type = 'cover';
23
         return _this;
23
         return _this;
24
     }
24
     }
25
-    CoverMarker.prototype.setup = function () {
26
-        _super.prototype.setup.call(this);
25
+    CoverMarker.prototype.init = function () {
26
+        _super.prototype.init.call(this);
27
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'cover-marker']]);
27
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'cover-marker']]);
28
     };
28
     };
29
     CoverMarker.createMarker = function (page) {
29
     CoverMarker.createMarker = function (page) {
30
         var marker = new CoverMarker();
30
         var marker = new CoverMarker();
31
         marker.page = page;
31
         marker.page = page;
32
-        marker.setup();
32
+        marker.init();
33
         return marker;
33
         return marker;
34
     };
34
     };
35
     return CoverMarker;
35
     return CoverMarker;

+ 3
- 3
dist/cjs/markers/HighlightMarker/index.js View File

22
         _this.type = 'highlight';
22
         _this.type = 'highlight';
23
         return _this;
23
         return _this;
24
     }
24
     }
25
-    HighlightMarker.prototype.setup = function () {
26
-        _super.prototype.setup.call(this);
25
+    HighlightMarker.prototype.init = function () {
26
+        _super.prototype.init.call(this);
27
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'highlight-marker']]);
27
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'highlight-marker']]);
28
     };
28
     };
29
     HighlightMarker.createMarker = function (page) {
29
     HighlightMarker.createMarker = function (page) {
30
         var marker = new HighlightMarker();
30
         var marker = new HighlightMarker();
31
         marker.page = page;
31
         marker.page = page;
32
-        marker.setup();
32
+        marker.init();
33
         return marker;
33
         return marker;
34
     };
34
     };
35
     return HighlightMarker;
35
     return HighlightMarker;

+ 3
- 3
dist/cjs/markers/LineMarker/index.js View File

22
         _this.type = 'line';
22
         _this.type = 'line';
23
         return _this;
23
         return _this;
24
     }
24
     }
25
-    LineMarker.prototype.setup = function () {
26
-        _super.prototype.setup.call(this);
25
+    LineMarker.prototype.init = function () {
26
+        _super.prototype.init.call(this);
27
         index_1.SvgHelper.setAttributes(this.visual, [['class', 'line-marker']]);
27
         index_1.SvgHelper.setAttributes(this.visual, [['class', 'line-marker']]);
28
     };
28
     };
29
     LineMarker.createMarker = function (page) {
29
     LineMarker.createMarker = function (page) {
30
         var marker = new LineMarker();
30
         var marker = new LineMarker();
31
         marker.page = page;
31
         marker.page = page;
32
-        marker.setup();
32
+        marker.init();
33
         return marker;
33
         return marker;
34
     };
34
     };
35
     return LineMarker;
35
     return LineMarker;

+ 46
- 17
dist/cjs/markers/LinearMarker/index.js View File

55
             grip.visual.addEventListener('touchstart', _this.onTouch, { passive: false });
55
             grip.visual.addEventListener('touchstart', _this.onTouch, { passive: false });
56
             grip.visual.addEventListener('touchend', _this.onTouch, { passive: false });
56
             grip.visual.addEventListener('touchend', _this.onTouch, { passive: false });
57
             grip.visual.addEventListener('touchmove', _this.onTouch, { passive: false });
57
             grip.visual.addEventListener('touchmove', _this.onTouch, { passive: false });
58
+            if (_this.page && _this.page.mode === 'mirror') {
59
+                grip.visual.style.visibility = 'hidden';
60
+            }
58
             return grip;
61
             return grip;
59
         };
62
         };
60
-        _this.positionGrips = function () {
61
-            var gripSize = _this.controlGrips.left.GRIP_SIZE;
62
-            var x1 = _this.x1 - gripSize / 2;
63
-            var y1 = _this.y1 - gripSize / 2;
64
-            var x2 = _this.x2 - gripSize / 2;
65
-            var y2 = _this.y2 - gripSize / 2;
66
-            _this.positionGrip(_this.controlGrips.left.visual, x1, y1);
67
-            _this.positionGrip(_this.controlGrips.right.visual, x2, y2);
68
-        };
69
-        _this.positionGrip = function (grip, x, y) {
70
-            var translate = grip.transform.baseVal.getItem(0);
71
-            translate.setTranslate(x, y);
72
-            grip.transform.baseVal.replaceItem(translate, 0);
73
-        };
74
         _this.gripMouseDown = function (ev) {
63
         _this.gripMouseDown = function (ev) {
75
             _this.isResizing = true;
64
             _this.isResizing = true;
76
             _this.activeGrip =
65
             _this.activeGrip =
91
                 _this.resize(ev.movementX, ev.movementY);
80
                 _this.resize(ev.movementX, ev.movementY);
92
             }
81
             }
93
         };
82
         };
83
+        _this.positionLine = function (bound) {
84
+            _this.x1 = bound.x1;
85
+            _this.y1 = bound.y1;
86
+            _this.x2 = bound.x2;
87
+            _this.y2 = bound.y2;
88
+            _this.markerBgLine.setAttribute('x1', _this.x1.toString());
89
+            _this.markerBgLine.setAttribute('y1', _this.y1.toString());
90
+            _this.markerLine.setAttribute('x2', _this.x2.toString());
91
+            _this.markerLine.setAttribute('y2', _this.y2.toString());
92
+        };
93
+        _this.positionGrips = function () {
94
+            var gripSize = _this.controlGrips.left.GRIP_SIZE;
95
+            var x1 = _this.x1 - gripSize / 2;
96
+            var y1 = _this.y1 - gripSize / 2;
97
+            var x2 = _this.x2 - gripSize / 2;
98
+            var y2 = _this.y2 - gripSize / 2;
99
+            _this.positionGrip(_this.controlGrips.left.visual, x1, y1);
100
+            _this.positionGrip(_this.controlGrips.right.visual, x2, y2);
101
+        };
102
+        _this.positionGrip = function (grip, x, y) {
103
+            var translate = grip.transform.baseVal.getItem(0);
104
+            translate.setTranslate(x, y);
105
+            grip.transform.baseVal.replaceItem(translate, 0);
106
+        };
94
         return _this;
107
         return _this;
95
     }
108
     }
109
+    LinearMarker.prototype.captureSnap = function () {
110
+        var baseSnap = _super.prototype.captureSnap.call(this);
111
+        baseSnap.linearSnap = {
112
+            x1: this.x1,
113
+            y1: this.y1,
114
+            x2: this.x2,
115
+            y2: this.y2
116
+        };
117
+        return baseSnap;
118
+    };
119
+    LinearMarker.prototype.applySnap = function (snap) {
120
+        _super.prototype.applySnap.call(this, snap);
121
+        if (snap.linearSnap) {
122
+            this.positionLine(snap.linearSnap);
123
+        }
124
+    };
96
     LinearMarker.prototype.endManipulation = function () {
125
     LinearMarker.prototype.endManipulation = function () {
97
         _super.prototype.endManipulation.call(this);
126
         _super.prototype.endManipulation.call(this);
98
         this.isResizing = false;
127
         this.isResizing = false;
106
         _super.prototype.deselect.call(this);
135
         _super.prototype.deselect.call(this);
107
         this.controlBox.style.display = 'none';
136
         this.controlBox.style.display = 'none';
108
     };
137
     };
109
-    LinearMarker.prototype.setup = function () {
110
-        _super.prototype.setup.call(this);
138
+    LinearMarker.prototype.init = function () {
139
+        _super.prototype.init.call(this);
111
         this.markerBgLine = SvgHelper_1.SvgHelper.createLine(0, 0, this.x2, 0, [
140
         this.markerBgLine = SvgHelper_1.SvgHelper.createLine(0, 0, this.x2, 0, [
112
             ['stroke', 'transparent'],
141
             ['stroke', 'transparent'],
113
             ['stroke-width', '30']
142
             ['stroke-width', '30']
161
     LinearMarker.createMarker = function (page) {
190
     LinearMarker.createMarker = function (page) {
162
         var marker = new LinearMarker();
191
         var marker = new LinearMarker();
163
         marker.page = page;
192
         marker.page = page;
164
-        marker.setup();
193
+        marker.init();
165
         return marker;
194
         return marker;
166
     };
195
     };
167
     return LinearMarker;
196
     return LinearMarker;

+ 10
- 3
dist/cjs/markers/RectMarker/RectBaseMarker.js View File

20
     function RectBaseMarker() {
20
     function RectBaseMarker() {
21
         return _super !== null && _super.apply(this, arguments) || this;
21
         return _super !== null && _super.apply(this, arguments) || this;
22
     }
22
     }
23
-    RectBaseMarker.prototype.setup = function () {
24
-        _super.prototype.setup.call(this);
23
+    RectBaseMarker.prototype.applySnap = function (snap) {
24
+        _super.prototype.applySnap.call(this, snap);
25
+        if (snap.rectSnap) {
26
+            this.markerRect.setAttribute('width', this.width.toString());
27
+            this.markerRect.setAttribute('height', this.height.toString());
28
+        }
29
+    };
30
+    RectBaseMarker.prototype.init = function () {
31
+        _super.prototype.init.call(this);
25
         this.markerRect = SvgHelper_1.SvgHelper.createRect(this.width, this.height);
32
         this.markerRect = SvgHelper_1.SvgHelper.createRect(this.width, this.height);
26
         this.addToRenderVisual(this.markerRect);
33
         this.addToRenderVisual(this.markerRect);
27
     };
34
     };
33
     RectBaseMarker.createMarker = function (page) {
40
     RectBaseMarker.createMarker = function (page) {
34
         var marker = new RectBaseMarker();
41
         var marker = new RectBaseMarker();
35
         marker.page = page;
42
         marker.page = page;
36
-        marker.setup();
43
+        marker.init();
37
         return marker;
44
         return marker;
38
     };
45
     };
39
     return RectBaseMarker;
46
     return RectBaseMarker;

+ 3
- 3
dist/cjs/markers/RectMarker/index.js View File

22
         _this.type = 'rect';
22
         _this.type = 'rect';
23
         return _this;
23
         return _this;
24
     }
24
     }
25
-    RectMarker.prototype.setup = function () {
26
-        _super.prototype.setup.call(this);
25
+    RectMarker.prototype.init = function () {
26
+        _super.prototype.init.call(this);
27
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'rect-marker']]);
27
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'rect-marker']]);
28
     };
28
     };
29
     RectMarker.createMarker = function (page) {
29
     RectMarker.createMarker = function (page) {
30
         var marker = new RectMarker();
30
         var marker = new RectMarker();
31
         marker.page = page;
31
         marker.page = page;
32
-        marker.setup();
32
+        marker.init();
33
         return marker;
33
         return marker;
34
     };
34
     };
35
     return RectMarker;
35
     return RectMarker;

+ 66
- 41
dist/cjs/markers/RectangularMarker/index.js View File

62
             grip.visual.addEventListener('touchmove', _this.onTouch, { passive: false });
62
             grip.visual.addEventListener('touchmove', _this.onTouch, { passive: false });
63
             return grip;
63
             return grip;
64
         };
64
         };
65
+        _this.gripMouseDown = function (ev) {
66
+            _this.isResizing = true;
67
+            _this.activeGrip = _this.controlGrips.findGripByVisual(ev.target) || null;
68
+            _this.previousMouseX = ev.screenX;
69
+            _this.previousMouseY = ev.screenY;
70
+            ev.stopPropagation();
71
+        };
72
+        _this.gripMouseUp = function (ev) {
73
+            _this.isResizing = false;
74
+            _this.activeGrip = null;
75
+            ev.stopPropagation();
76
+        };
77
+        _this.gripMouseMove = function (ev) {
78
+            if (_this.isResizing) {
79
+                _this.manipulate(ev);
80
+            }
81
+        };
65
         _this.positionGrips = function () {
82
         _this.positionGrips = function () {
66
             var gripSize = _this.controlGrips.topLeft.GRIP_SIZE;
83
             var gripSize = _this.controlGrips.topLeft.GRIP_SIZE;
67
             var left = -gripSize / 2;
84
             var left = -gripSize / 2;
84
             translate.setTranslate(x, y);
101
             translate.setTranslate(x, y);
85
             grip.transform.baseVal.replaceItem(translate, 0);
102
             grip.transform.baseVal.replaceItem(translate, 0);
86
         };
103
         };
87
-        _this.gripMouseDown = function (ev) {
88
-            _this.isResizing = true;
89
-            _this.activeGrip = _this.controlGrips.findGripByVisual(ev.target) || null;
90
-            _this.previousMouseX = ev.screenX;
91
-            _this.previousMouseY = ev.screenY;
92
-            ev.stopPropagation();
93
-        };
94
-        _this.gripMouseUp = function (ev) {
95
-            _this.isResizing = false;
96
-            _this.activeGrip = null;
97
-            ev.stopPropagation();
98
-        };
99
-        _this.gripMouseMove = function (ev) {
100
-            if (_this.isResizing) {
101
-                _this.manipulate(ev);
102
-            }
103
-        };
104
         return _this;
104
         return _this;
105
     }
105
     }
106
+    RectangularMarker.prototype.captureSnap = function () {
107
+        var snap = _super.prototype.captureSnap.call(this);
108
+        snap.rectSnap = {
109
+            width: this.width,
110
+            height: this.height
111
+        };
112
+        return snap;
113
+    };
114
+    RectangularMarker.prototype.applySnap = function (snap) {
115
+        _super.prototype.applySnap.call(this, snap);
116
+        if (snap.rectSnap) {
117
+            var _a = snap.rectSnap, width = _a.width, height = _a.height;
118
+            if (width && height) {
119
+                this.width = width;
120
+                this.height = height;
121
+                this.adjustControlBox();
122
+            }
123
+        }
124
+    };
106
     RectangularMarker.prototype.endManipulation = function () {
125
     RectangularMarker.prototype.endManipulation = function () {
107
         _super.prototype.endManipulation.call(this);
126
         _super.prototype.endManipulation.call(this);
108
         this.isResizing = false;
127
         this.isResizing = false;
116
         _super.prototype.deselect.call(this);
135
         _super.prototype.deselect.call(this);
117
         this.controlBox.style.display = 'none';
136
         this.controlBox.style.display = 'none';
118
     };
137
     };
119
-    RectangularMarker.prototype.setup = function () {
120
-        _super.prototype.setup.call(this);
138
+    RectangularMarker.prototype.init = function () {
139
+        _super.prototype.init.call(this);
121
         this.addControlBox();
140
         this.addControlBox();
122
         if (this.page && this.page.mode === 'mirror') {
141
         if (this.page && this.page.mode === 'mirror') {
123
             this.controlBox.style.display = 'none';
142
             this.controlBox.style.display = 'none';
124
         }
143
         }
125
     };
144
     };
126
-    RectangularMarker.prototype.resizeByEvent = function (x, y, pos) {
145
+    RectangularMarker.prototype.resizeByEvent = function (dx, dy, pos) {
127
         this.activeGrip = this.controlGrips[pos];
146
         this.activeGrip = this.controlGrips[pos];
128
-        this.resize(x, y);
147
+        this.resize(dx, dy);
129
     };
148
     };
130
-    RectangularMarker.prototype.resize = function (x, y, onPosition) {
149
+    RectangularMarker.prototype.resize = function (dx, dy, onPosition) {
131
         var translateX = 0;
150
         var translateX = 0;
132
         var translateY = 0;
151
         var translateY = 0;
133
         switch (this.activeGrip) {
152
         switch (this.activeGrip) {
134
             case this.controlGrips.topLeft:
153
             case this.controlGrips.topLeft:
135
-                this.width -= x;
136
-                this.height -= y;
137
-                translateX += x;
138
-                translateY += y;
154
+                this.width -= dx;
155
+                this.height -= dy;
156
+                translateX += dx;
157
+                translateY += dy;
158
+                this.x += dx;
159
+                this.y += dy;
139
                 if (onPosition) {
160
                 if (onPosition) {
140
                     onPosition('topLeft');
161
                     onPosition('topLeft');
141
                 }
162
                 }
142
                 break;
163
                 break;
143
             case this.controlGrips.bottomLeft:
164
             case this.controlGrips.bottomLeft:
144
-                this.width -= x;
145
-                this.height += y;
146
-                translateX += x;
165
+                this.width -= dx;
166
+                this.height += dy;
167
+                translateX += dx;
168
+                this.x += dx;
147
                 if (onPosition) {
169
                 if (onPosition) {
148
                     onPosition('bottomLeft');
170
                     onPosition('bottomLeft');
149
                 }
171
                 }
150
                 break;
172
                 break;
151
             case this.controlGrips.topRight:
173
             case this.controlGrips.topRight:
152
-                this.width += x;
153
-                this.height -= y;
154
-                translateY += y;
174
+                this.width += dx;
175
+                this.height -= dy;
176
+                translateY += dy;
177
+                this.y += dy;
155
                 if (onPosition) {
178
                 if (onPosition) {
156
                     onPosition('topRight');
179
                     onPosition('topRight');
157
                 }
180
                 }
158
                 break;
181
                 break;
159
             case this.controlGrips.bottomRight:
182
             case this.controlGrips.bottomRight:
160
-                this.width += x;
161
-                this.height += y;
183
+                this.width += dx;
184
+                this.height += dy;
162
                 if (onPosition) {
185
                 if (onPosition) {
163
                     onPosition('bottomRight');
186
                     onPosition('bottomRight');
164
                 }
187
                 }
165
                 break;
188
                 break;
166
             case this.controlGrips.centerLeft:
189
             case this.controlGrips.centerLeft:
167
-                this.width -= x;
168
-                translateX += x;
190
+                this.width -= dx;
191
+                translateX += dx;
192
+                this.x += dx;
169
                 if (onPosition) {
193
                 if (onPosition) {
170
                     onPosition('centerLeft');
194
                     onPosition('centerLeft');
171
                 }
195
                 }
172
                 break;
196
                 break;
173
             case this.controlGrips.centerRight:
197
             case this.controlGrips.centerRight:
174
-                this.width += x;
198
+                this.width += dx;
175
                 if (onPosition) {
199
                 if (onPosition) {
176
                     onPosition('centerRight');
200
                     onPosition('centerRight');
177
                 }
201
                 }
178
                 break;
202
                 break;
179
             case this.controlGrips.topCenter:
203
             case this.controlGrips.topCenter:
180
-                this.height -= y;
181
-                translateY += y;
204
+                this.height -= dy;
205
+                translateY += dy;
206
+                this.y += dy;
182
                 if (onPosition) {
207
                 if (onPosition) {
183
                     onPosition('topCenter');
208
                     onPosition('topCenter');
184
                 }
209
                 }
185
                 break;
210
                 break;
186
             case this.controlGrips.bottomCenter:
211
             case this.controlGrips.bottomCenter:
187
-                this.height += y;
212
+                this.height += dy;
188
                 if (onPosition) {
213
                 if (onPosition) {
189
                     onPosition('bottomCenter');
214
                     onPosition('bottomCenter');
190
                 }
215
                 }
219
     RectangularMarker.createMarker = function (page) {
244
     RectangularMarker.createMarker = function (page) {
220
         var marker = new RectangularMarker();
245
         var marker = new RectangularMarker();
221
         marker.page = page;
246
         marker.page = page;
222
-        marker.setup();
247
+        marker.init();
223
         return marker;
248
         return marker;
224
     };
249
     };
225
     return RectangularMarker;
250
     return RectangularMarker;

+ 20
- 4
dist/cjs/markers/TextMarker/index.js View File

102
             else {
102
             else {
103
                 _this.text = _this.DEFAULT_TEXT;
103
                 _this.text = _this.DEFAULT_TEXT;
104
             }
104
             }
105
-            _this.onChange({ target: 'marker', id: _this.id, event: 'changeText', data: _this.text });
105
+            _this.onChange({
106
+                target: 'marker',
107
+                id: _this.id,
108
+                event: 'inputMarker',
109
+                marker: { text: _this.text }
110
+            });
106
             _this.renderText();
111
             _this.renderText();
107
             _this.closeEditor();
112
             _this.closeEditor();
108
         };
113
         };
121
         this.text = text;
126
         this.text = text;
122
         this.renderText();
127
         this.renderText();
123
     };
128
     };
124
-    TextMarker.prototype.setup = function () {
125
-        _super.prototype.setup.call(this);
129
+    TextMarker.prototype.captureSnap = function () {
130
+        var baseSnap = _super.prototype.captureSnap.call(this);
131
+        baseSnap.textSnap = { text: this.text };
132
+        return baseSnap;
133
+    };
134
+    TextMarker.prototype.applySnap = function (snap) {
135
+        _super.prototype.applySnap.call(this, snap);
136
+        if (snap.textSnap && snap.textSnap.text !== this.text) {
137
+            this.setText(snap.textSnap.text);
138
+        }
139
+    };
140
+    TextMarker.prototype.init = function () {
141
+        _super.prototype.init.call(this);
126
         this.textElement = SvgHelper_1.SvgHelper.createText();
142
         this.textElement = SvgHelper_1.SvgHelper.createText();
127
         this.addToRenderVisual(this.textElement);
143
         this.addToRenderVisual(this.textElement);
128
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'text-marker']]);
144
         SvgHelper_1.SvgHelper.setAttributes(this.visual, [['class', 'text-marker']]);
139
     TextMarker.createMarker = function (page) {
155
     TextMarker.createMarker = function (page) {
140
         var marker = new TextMarker();
156
         var marker = new TextMarker();
141
         marker.page = page;
157
         marker.page = page;
142
-        marker.setup();
158
+        marker.init();
143
         return marker;
159
         return marker;
144
     };
160
     };
145
     return TextMarker;
161
     return TextMarker;

+ 41
- 0
dist/cjs/renderer/DomEventAware/index.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var DomEventAware = (function () {
4
+    function DomEventAware() {
5
+        this.x = 0;
6
+        this.y = 0;
7
+        this.previousMouseX = 0;
8
+        this.previousMouseY = 0;
9
+    }
10
+    DomEventAware.prototype.init = function (ele) {
11
+        ele.addEventListener('mousedown', this.onMouseDown);
12
+        ele.addEventListener('mouseup', this.onMouseUp);
13
+        ele.addEventListener('mousemove', this.onMouseMove);
14
+        ele.addEventListener('touchstart', this.onTouch, { passive: false });
15
+        ele.addEventListener('touchend', this.onTouch, { passive: false });
16
+        ele.addEventListener('touchmove', this.onTouch, { passive: false });
17
+    };
18
+    DomEventAware.prototype.onTouch = function (ev) {
19
+        ev.preventDefault();
20
+        var newEvt = document.createEvent('MouseEvents');
21
+        var touch = ev.changedTouches[0];
22
+        var type = null;
23
+        switch (ev.type) {
24
+            case 'touchstart':
25
+                type = 'mousedown';
26
+                break;
27
+            case 'touchmove':
28
+                type = 'mousemove';
29
+                break;
30
+            case 'touchend':
31
+                type = 'mouseup';
32
+                break;
33
+            default:
34
+                break;
35
+        }
36
+        newEvt.initMouseEvent(type, true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, ev.ctrlKey, ev.altKey, ev.shiftKey, ev.metaKey, 0, null);
37
+        ev.target.dispatchEvent(newEvt);
38
+    };
39
+    return DomEventAware;
40
+}());
41
+exports.DomEventAware = DomEventAware;

+ 1
- 1
dist/cjs/renderer/Synthetizer/index.js View File

6
     }
6
     }
7
     Synthetizer.prototype.rasterize = function (target, markerImage, done) {
7
     Synthetizer.prototype.rasterize = function (target, markerImage, done) {
8
         if (!validator_1.isHTMLImageElement(target)) {
8
         if (!validator_1.isHTMLImageElement(target)) {
9
-            throw new Error('Error: only support export HTMLImageElement');
9
+            throw new Error('Error: only support export to HTMLImageElement');
10
         }
10
         }
11
         var canvas = document.createElement('canvas');
11
         var canvas = document.createElement('canvas');
12
         canvas.width = markerImage.width.baseVal.value;
12
         canvas.width = markerImage.width.baseVal.value;

+ 58
- 8
dist/cjs/toolbar/Toolbar.js View File

1
 "use strict";
1
 "use strict";
2
+var __extends = (this && this.__extends) || (function () {
3
+    var extendStatics = function (d, b) {
4
+        extendStatics = Object.setPrototypeOf ||
5
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+        return extendStatics(d, b);
8
+    };
9
+    return function (d, b) {
10
+        extendStatics(d, b);
11
+        function __() { this.constructor = d; }
12
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+    };
14
+})();
2
 Object.defineProperty(exports, "__esModule", { value: true });
15
 Object.defineProperty(exports, "__esModule", { value: true });
16
+var interactjs_1 = require("interactjs");
3
 var ToolbarButton_1 = require("./ToolbarButton");
17
 var ToolbarButton_1 = require("./ToolbarButton");
4
 var uuid_1 = require("../utils/uuid");
18
 var uuid_1 = require("../utils/uuid");
5
-var Toolbar = (function () {
19
+require("./index.less");
20
+var index_1 = require("../renderer/DomEventAware/index");
21
+var toolbar_items_1 = require("./toolbar-items");
22
+var Toolbar = (function (_super) {
23
+    __extends(Toolbar, _super);
6
     function Toolbar(toolbarItems, clickHandler) {
24
     function Toolbar(toolbarItems, clickHandler) {
7
-        var _this = this;
8
-        this.id = uuid_1.uuid();
9
-        this.getUI = function () {
25
+        var _this = _super.call(this) || this;
26
+        _this.id = uuid_1.uuid();
27
+        _this.zIndex = 999;
28
+        _this.toolbarButtons = [];
29
+        _this.getUI = function (drawboard) {
10
             _this.toolbarUI = document.createElement('div');
30
             _this.toolbarUI = document.createElement('div');
11
             _this.toolbarUI.id = "fcw-toolbar-" + _this.id;
31
             _this.toolbarUI.id = "fcw-toolbar-" + _this.id;
12
             _this.toolbarUI.className = 'fc-whiteboard-toolbar';
32
             _this.toolbarUI.className = 'fc-whiteboard-toolbar';
13
             for (var _i = 0, _a = _this.toolbarItems; _i < _a.length; _i++) {
33
             for (var _i = 0, _a = _this.toolbarItems; _i < _a.length; _i++) {
14
                 var toolbarItem = _a[_i];
34
                 var toolbarItem = _a[_i];
15
                 var toolbarButton = new ToolbarButton_1.ToolbarButton(toolbarItem, _this.clickHandler);
35
                 var toolbarButton = new ToolbarButton_1.ToolbarButton(toolbarItem, _this.clickHandler);
36
+                toolbarButton.drawboard = drawboard;
16
                 _this.toolbarUI.appendChild(toolbarButton.getElement());
37
                 _this.toolbarUI.appendChild(toolbarButton.getElement());
38
+                _this.toolbarButtons.push(toolbarButton);
17
             }
39
             }
40
+            _super.prototype.init.call(_this, _this.toolbarUI);
41
+            interactjs_1.default('#drag-handler').draggable({
42
+                onmove: _this.onDragMove
43
+            });
18
             return _this.toolbarUI;
44
             return _this.toolbarUI;
19
         };
45
         };
20
-        this.toolbarItems = toolbarItems;
21
-        this.clickHandler = clickHandler;
46
+        _this.onMouseDown = function (downEv) { };
47
+        _this.onMouseUp = function (ev) { };
48
+        _this.onMouseMove = function (ev) { };
49
+        _this.onDragMove = function (event) {
50
+            var target = _this.toolbarUI;
51
+            var x = ((parseFloat(target.getAttribute('data-x')) || 0) + event.dx);
52
+            var y = ((parseFloat(target.getAttribute('data-y')) || 0) + event.dy);
53
+            target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
54
+            target.style.zIndex = "" + _this.zIndex;
55
+            target.setAttribute('data-x', x);
56
+            target.setAttribute('data-y', y);
57
+        };
58
+        _this.toolbarItems = [toolbar_items_1.dragToolbarItem].concat(toolbarItems);
59
+        _this.clickHandler = clickHandler;
60
+        return _this;
22
     }
61
     }
62
+    Object.defineProperty(Toolbar.prototype, "toolbarButtonMap", {
63
+        get: function () {
64
+            var buttonMap = {};
65
+            this.toolbarButtons.forEach(function (b) {
66
+                buttonMap[b.id] = b;
67
+            });
68
+            return buttonMap;
69
+        },
70
+        enumerable: true,
71
+        configurable: true
72
+    });
23
     Toolbar.prototype.hide = function () {
73
     Toolbar.prototype.hide = function () {
24
         this.toolbarUI.style.visibility = 'hidden';
74
         this.toolbarUI.style.visibility = 'hidden';
25
         this.toolbarUI.style.zIndex = '-1';
75
         this.toolbarUI.style.zIndex = '-1';
26
     };
76
     };
27
     Toolbar.prototype.show = function () {
77
     Toolbar.prototype.show = function () {
28
         this.toolbarUI.style.visibility = 'visible';
78
         this.toolbarUI.style.visibility = 'visible';
29
-        this.toolbarUI.style.zIndex = '999';
79
+        this.toolbarUI.style.zIndex = "" + this.zIndex;
30
     };
80
     };
31
     return Toolbar;
81
     return Toolbar;
32
-}());
82
+}(index_1.DomEventAware));
33
 exports.Toolbar = Toolbar;
83
 exports.Toolbar = Toolbar;

+ 18
- 2
dist/cjs/toolbar/ToolbarButton.js View File

1
 "use strict";
1
 "use strict";
2
 Object.defineProperty(exports, "__esModule", { value: true });
2
 Object.defineProperty(exports, "__esModule", { value: true });
3
+var tippy_js_1 = require("tippy.js");
4
+var uuid_1 = require("../utils/uuid");
3
 var ToolbarButton = (function () {
5
 var ToolbarButton = (function () {
4
     function ToolbarButton(toolbarItem, clickHandler) {
6
     function ToolbarButton(toolbarItem, clickHandler) {
5
         var _this = this;
7
         var _this = this;
8
+        this.id = uuid_1.uuid();
6
         this.getElement = function () {
9
         this.getElement = function () {
10
+            if (_this.toolbarItem.onRender) {
11
+                _this.container = _this.toolbarItem.onRender().cloneNode(true);
12
+                return _this.container;
13
+            }
7
             var div = document.createElement('div');
14
             var div = document.createElement('div');
8
             if (_this.toolbarItem.name !== 'separator') {
15
             if (_this.toolbarItem.name !== 'separator') {
9
                 div.className = 'fc-whiteboard-toolbar-button';
16
                 div.className = 'fc-whiteboard-toolbar-button';
15
                     });
22
                     });
16
                 }
23
                 }
17
                 if (_this.toolbarItem.icon) {
24
                 if (_this.toolbarItem.icon) {
18
-                    div.title = _this.toolbarItem.tooltipText;
25
+                    div.title = _this.toolbarItem.tooltipText || '';
19
                     div.innerHTML = _this.toolbarItem.icon;
26
                     div.innerHTML = _this.toolbarItem.icon;
20
                 }
27
                 }
21
                 else {
28
                 else {
22
-                    div.innerText = _this.toolbarItem.tooltipText;
29
+                    div.innerText = _this.toolbarItem.tooltipText || '';
30
+                }
31
+                if (_this.toolbarItem.tooltipText) {
32
+                    tippy_js_1.default(div, {
33
+                        content: _this.toolbarItem.shortcut
34
+                            ? _this.toolbarItem.tooltipText + " " + _this.toolbarItem.shortcut
35
+                            : _this.toolbarItem.tooltipText
36
+                    });
23
                 }
37
                 }
24
             }
38
             }
25
             else {
39
             else {
26
                 div.className = 'fc-whiteboard-toolbar-separator';
40
                 div.className = 'fc-whiteboard-toolbar-separator';
27
             }
41
             }
42
+            div.id = "fc-whiteboard-toolbar-" + _this.toolbarItem.name;
43
+            _this.container = div;
28
             return div;
44
             return div;
29
         };
45
         };
30
         this.toolbarItem = toolbarItem;
46
         this.toolbarItem = toolbarItem;

+ 8
- 1
dist/cjs/toolbar/ToolbarItem.js View File

2
 Object.defineProperty(exports, "__esModule", { value: true });
2
 Object.defineProperty(exports, "__esModule", { value: true });
3
 var ToolbarItem = (function () {
3
 var ToolbarItem = (function () {
4
     function ToolbarItem(_a) {
4
     function ToolbarItem(_a) {
5
-        var name = _a.name, tooltipText = _a.tooltipText, icon = _a.icon, markerType = _a.markerType;
5
+        var name = _a.name, tooltipText = _a.tooltipText, shortcut = _a.shortcut, icon = _a.icon, draggable = _a.draggable, markerType = _a.markerType, onRender = _a.onRender, onClick = _a.onClick;
6
+        if (!name) {
7
+            throw new Error('Invalid params');
8
+        }
6
         this.name = name;
9
         this.name = name;
7
         this.tooltipText = tooltipText;
10
         this.tooltipText = tooltipText;
11
+        this.shortcut = shortcut;
8
         this.icon = icon;
12
         this.icon = icon;
9
         this.markerType = markerType;
13
         this.markerType = markerType;
14
+        this.draggable = draggable;
15
+        this.onClick = onClick;
16
+        this.onRender = onRender;
10
     }
17
     }
11
     return ToolbarItem;
18
     return ToolbarItem;
12
 }());
19
 }());

+ 31
- 27
dist/cjs/toolbar/toolbar-items.js View File

9
 var LineMarker_1 = require("../markers/LineMarker");
9
 var LineMarker_1 = require("../markers/LineMarker");
10
 var OkIcon = require('../assets/check.svg');
10
 var OkIcon = require('../assets/check.svg');
11
 var DeleteIcon = require('../assets/eraser.svg');
11
 var DeleteIcon = require('../assets/eraser.svg');
12
-var PointerIcon = require('../assets/mouse-pointer.svg');
13
 var CloseIcon = require('../assets/times.svg');
12
 var CloseIcon = require('../assets/times.svg');
13
+exports.dragToolbarItem = new ToolbarItem_1.ToolbarItem({
14
+    name: 'drag',
15
+    tooltipText: 'Drag',
16
+    icon: require('../assets/drag.svg')
17
+});
14
 exports.highlightMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
18
 exports.highlightMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
15
     name: 'cover-marker',
19
     name: 'cover-marker',
16
-    tooltipText: 'Cover',
20
+    tooltipText: 'Hightlight',
21
+    shortcut: 'Shift+H',
17
     icon: require('../assets/highlight.svg'),
22
     icon: require('../assets/highlight.svg'),
18
-    markerType: index_5.HighlightMarker
23
+    markerType: index_5.HighlightMarker,
24
+    draggable: true
19
 });
25
 });
20
 exports.arrowMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
26
 exports.arrowMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
21
     name: 'arrow-marker',
27
     name: 'arrow-marker',
22
     tooltipText: 'Arrow',
28
     tooltipText: 'Arrow',
29
+    shortcut: 'Shift+A',
23
     icon: require('../assets/arrow.svg'),
30
     icon: require('../assets/arrow.svg'),
24
-    markerType: index_4.ArrowMarker
31
+    markerType: index_4.ArrowMarker,
32
+    draggable: true
25
 });
33
 });
26
 exports.textMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
34
 exports.textMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
27
     name: 'text-marker',
35
     name: 'text-marker',
28
     tooltipText: 'Text',
36
     tooltipText: 'Text',
37
+    shortcut: 'Shift+T',
29
     icon: require('../assets/text.svg'),
38
     icon: require('../assets/text.svg'),
30
-    markerType: index_3.TextMarker
39
+    markerType: index_3.TextMarker,
40
+    draggable: true
31
 });
41
 });
32
 exports.coverMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
42
 exports.coverMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
33
     name: 'cover-marker',
43
     name: 'cover-marker',
34
     tooltipText: 'Cover',
44
     tooltipText: 'Cover',
45
+    shortcut: 'Shift+C',
35
     icon: require('../assets/cover.svg'),
46
     icon: require('../assets/cover.svg'),
36
-    markerType: index_2.CoverMarker
47
+    markerType: index_2.CoverMarker,
48
+    draggable: true
37
 });
49
 });
38
 exports.rectMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
50
 exports.rectMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
39
     name: 'rect-marker',
51
     name: 'rect-marker',
40
     tooltipText: 'Rectangle',
52
     tooltipText: 'Rectangle',
53
+    shortcut: 'Shift+R',
41
     icon: require('../assets/rect.svg'),
54
     icon: require('../assets/rect.svg'),
42
-    markerType: index_1.RectMarker
55
+    markerType: index_1.RectMarker,
56
+    draggable: true
43
 });
57
 });
44
 exports.lineMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
58
 exports.lineMarkerToolbarItem = new ToolbarItem_1.ToolbarItem({
45
     name: 'line-marker',
59
     name: 'line-marker',
46
     tooltipText: 'Line',
60
     tooltipText: 'Line',
61
+    shortcut: 'Shift+L',
47
     icon: require('../assets/line.svg'),
62
     icon: require('../assets/line.svg'),
48
-    markerType: LineMarker_1.LineMarker
63
+    markerType: LineMarker_1.LineMarker,
64
+    draggable: true
49
 });
65
 });
66
+exports.closeToolbarItem = new ToolbarItem_1.ToolbarItem({
67
+    icon: CloseIcon,
68
+    name: 'close',
69
+    tooltipText: 'Close'
70
+});
71
+exports.separatorToolbarItem = new ToolbarItem_1.ToolbarItem({ name: 'separator', tooltipText: '' });
50
 function getToolbars(page) {
72
 function getToolbars(page) {
51
     var toolbars = [
73
     var toolbars = [
52
-        {
53
-            icon: PointerIcon,
54
-            name: 'pointer',
55
-            tooltipText: 'Pointer'
56
-        },
57
         {
74
         {
58
             icon: DeleteIcon,
75
             icon: DeleteIcon,
59
             name: 'delete',
76
             name: 'delete',
60
             tooltipText: 'Delete'
77
             tooltipText: 'Delete'
61
         },
78
         },
62
-        {
63
-            name: 'separator',
64
-            tooltipText: ''
65
-        },
66
         exports.rectMarkerToolbarItem,
79
         exports.rectMarkerToolbarItem,
67
         exports.coverMarkerToolbarItem,
80
         exports.coverMarkerToolbarItem,
68
         exports.highlightMarkerToolbarItem,
81
         exports.highlightMarkerToolbarItem,
69
         exports.lineMarkerToolbarItem,
82
         exports.lineMarkerToolbarItem,
70
         exports.arrowMarkerToolbarItem,
83
         exports.arrowMarkerToolbarItem,
71
-        exports.textMarkerToolbarItem,
72
-        {
73
-            name: 'separator',
74
-            tooltipText: ''
75
-        }
84
+        exports.textMarkerToolbarItem
76
     ];
85
     ];
77
     if (!page) {
86
     if (!page) {
78
         toolbars.push.apply(toolbars, [
87
         toolbars.push.apply(toolbars, [
83
             }
92
             }
84
         ]);
93
         ]);
85
     }
94
     }
86
-    toolbars.push({
87
-        icon: CloseIcon,
88
-        name: 'close',
89
-        tooltipText: 'Close'
90
-    });
91
     return toolbars;
95
     return toolbars;
92
 }
96
 }
93
 exports.getToolbars = getToolbars;
97
 exports.getToolbars = getToolbars;

+ 10
- 0
dist/cjs/utils/layout.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+function rectContains(rect, _a) {
4
+    var x = _a.x, y = _a.y;
5
+    if (x < rect.left || x > rect.left + rect.width || y < rect.top || y > rect.top + rect.height) {
6
+        return false;
7
+    }
8
+    return true;
9
+}
10
+exports.rectContains = rectContains;

+ 6
- 0
dist/cjs/utils/types.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+function isNil(mayBeNil) {
4
+    return mayBeNil === null || mayBeNil === undefined;
5
+}
6
+exports.isNil = isNil;

+ 206
- 0
dist/cjs/whiteboard/AbstractWhiteboard/index.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var index_1 = require("../WhitePage/index");
4
+var uuid_1 = require("../../utils/uuid");
5
+var dom_1 = require("../../utils/dom");
6
+require("./index.less");
7
+var Siema = require("siema");
8
+var prefix = 'fcw-board';
9
+var AbstractWhiteboard = (function () {
10
+    function AbstractWhiteboard(target, _a) {
11
+        var _b = _a === void 0 ? {} : _a, sources = _b.sources, eventHub = _b.eventHub, visiblePageIndex = _b.visiblePageIndex, allowRollback = _b.allowRollback, onlyEmitSnap = _b.onlyEmitSnap;
12
+        this.id = uuid_1.uuid();
13
+        this.sources = [];
14
+        this.imgEles = [];
15
+        this.allowRollback = false;
16
+        this.onlyEmitSnap = false;
17
+        this.snapInterval = 15 * 1000;
18
+        this.mode = 'master';
19
+        this.isFullscreen = false;
20
+        this.pages = [];
21
+        this.snapHistory = [];
22
+        this.isInitialized = false;
23
+        this.isSyncing = false;
24
+        this.visiblePageIndex = 0;
25
+        if (target) {
26
+            this.target = target;
27
+        }
28
+        else {
29
+            this.target = document.createElement('div');
30
+            document.body.appendChild(this.target);
31
+        }
32
+        if (!this.target.id) {
33
+            this.target.id = this.id;
34
+        }
35
+        dom_1.addClassName(this.target, prefix);
36
+        if (sources) {
37
+            this.sources = sources;
38
+        }
39
+        this.eventHub = eventHub;
40
+        if (typeof visiblePageIndex !== 'undefined') {
41
+            this.visiblePageIndex = visiblePageIndex;
42
+        }
43
+        this.onlyEmitSnap = !!onlyEmitSnap;
44
+        if (typeof allowRollback !== 'undefined') {
45
+            this.allowRollback = !!allowRollback;
46
+        }
47
+        this.init();
48
+    }
49
+    Object.defineProperty(AbstractWhiteboard.prototype, "activePage", {
50
+        get: function () {
51
+            return this.pages[this.visiblePageIndex];
52
+        },
53
+        enumerable: true,
54
+        configurable: true
55
+    });
56
+    Object.defineProperty(AbstractWhiteboard.prototype, "pageMap", {
57
+        get: function () {
58
+            var map = {};
59
+            this.pages.forEach(function (p) { return (map[p.id] = p); });
60
+            return map;
61
+        },
62
+        enumerable: true,
63
+        configurable: true
64
+    });
65
+    AbstractWhiteboard.prototype.open = function () {
66
+        var _this = this;
67
+        this.pages.forEach(function (page, i) {
68
+            page.open();
69
+            if (i !== _this.visiblePageIndex) {
70
+                page.hide();
71
+            }
72
+        });
73
+    };
74
+    AbstractWhiteboard.prototype.close = function () {
75
+        if (this.emitInterval) {
76
+            clearInterval(this.emitInterval);
77
+        }
78
+    };
79
+    AbstractWhiteboard.prototype.show = function () {
80
+        if (this.activePage) {
81
+            this.activePage.show();
82
+        }
83
+    };
84
+    AbstractWhiteboard.prototype.hide = function () {
85
+        if (this.activePage) {
86
+            this.activePage.hide();
87
+        }
88
+    };
89
+    AbstractWhiteboard.prototype.emit = function (borderEvent) {
90
+        if (this.mode !== 'master' || !this.eventHub) {
91
+            return;
92
+        }
93
+        if (this.onlyEmitSnap) {
94
+            if (borderEvent.event !== 'borderSnap') {
95
+                return;
96
+            }
97
+        }
98
+        if (this.allowRollback &&
99
+            (borderEvent.event === 'addMarker' || borderEvent.event === 'removeMarker')) {
100
+            if (this.snapHistory.length > 20) {
101
+                this.snapHistory.shift();
102
+            }
103
+            this.snapHistory.push(this.captureSnap(false));
104
+        }
105
+        borderEvent.timestamp = Math.floor(Date.now() / 1000);
106
+        this.eventHub.emit('sync', borderEvent);
107
+    };
108
+    AbstractWhiteboard.prototype.captureSnap = function (shadow) {
109
+        if (shadow === void 0) { shadow = true; }
110
+        if (shadow) {
111
+            return {
112
+                id: this.id,
113
+                sources: this.sources,
114
+                pageIds: this.pages.map(function (page) { return page.id; }),
115
+                visiblePageIndex: this.visiblePageIndex
116
+            };
117
+        }
118
+        return {
119
+            id: this.id,
120
+            sources: this.sources,
121
+            pageIds: this.pages.map(function (page) { return page.id; }),
122
+            visiblePageIndex: this.visiblePageIndex,
123
+            pages: this.pages.map(function (p) { return p.captureSnap(); })
124
+        };
125
+    };
126
+    AbstractWhiteboard.prototype.rollbackSnap = function () {
127
+        if (this.snapHistory.length === 0) {
128
+            return;
129
+        }
130
+        this.snapHistory.pop();
131
+        var snap = this.snapHistory[this.snapHistory.length - 1];
132
+        if (snap) {
133
+            this.applySnap(snap);
134
+        }
135
+    };
136
+    AbstractWhiteboard.prototype.destroy = function () {
137
+        if (this.emitInterval) {
138
+            clearInterval(this.emitInterval);
139
+        }
140
+        if (this.eventHub) {
141
+            this.eventHub.removeAllListeners();
142
+        }
143
+        if (this.siema) {
144
+            this.siema.destroy();
145
+        }
146
+        this.imgsContainer.remove();
147
+        this.pagesContainer.remove();
148
+        this.pages.forEach(function (page) {
149
+            page.destroy();
150
+        });
151
+    };
152
+    AbstractWhiteboard.prototype.initSiema = function () {
153
+        var _this = this;
154
+        this.sources.forEach(function (source) {
155
+            var imgEle = document.createElement('div');
156
+            dom_1.addClassName(imgEle, prefix + "-img-wrapper");
157
+            imgEle.style.backgroundImage = "url(" + source + ")";
158
+            _this.imgEles.push(imgEle);
159
+            _this.imgsContainer.appendChild(imgEle);
160
+        });
161
+        this.siema = new Siema({
162
+            selector: this.imgsContainer,
163
+            duration: 200,
164
+            easing: 'ease-out',
165
+            perPage: 1,
166
+            startIndex: 0,
167
+            draggable: false,
168
+            multipleDrag: true,
169
+            threshold: 20,
170
+            loop: false,
171
+            rtl: false
172
+        });
173
+    };
174
+    AbstractWhiteboard.prototype.applySnap = function (snap) {
175
+        var _this = this;
176
+        var id = snap.id, sources = snap.sources, pageIds = snap.pageIds;
177
+        if (!this.isInitialized && !this.isSyncing) {
178
+            this.id = id;
179
+            this.sources = sources;
180
+            this.isSyncing = true;
181
+            this.sources.forEach(function (source, i) {
182
+                var page = new index_1.WhitePage({ imgSrc: source }, {
183
+                    mode: _this.mode,
184
+                    whiteboard: _this,
185
+                    parentContainer: _this.pagesContainer
186
+                });
187
+                page.id = pageIds[i];
188
+                page.container.style.visibility = 'hidden';
189
+                _this.pages.push(page);
190
+                page.open();
191
+            });
192
+            this.initSiema();
193
+            this.isInitialized = true;
194
+            this.isSyncing = false;
195
+        }
196
+        this.onPageChange(snap.visiblePageIndex);
197
+        (snap.pages || []).forEach(function (pageSnap) {
198
+            var page = _this.pageMap[pageSnap.id];
199
+            if (page) {
200
+                page.applySnap(pageSnap);
201
+            }
202
+        });
203
+    };
204
+    return AbstractWhiteboard;
205
+}());
206
+exports.AbstractWhiteboard = AbstractWhiteboard;

+ 20
- 0
dist/cjs/whiteboard/AbstractWhiteboard/snap.js View File

1
+"use strict";
2
+Object.defineProperty(exports, "__esModule", { value: true });
3
+var WhiteboardSnap = (function () {
4
+    function WhiteboardSnap() {
5
+    }
6
+    return WhiteboardSnap;
7
+}());
8
+exports.WhiteboardSnap = WhiteboardSnap;
9
+var WhitepageSnap = (function () {
10
+    function WhitepageSnap() {
11
+    }
12
+    return WhitepageSnap;
13
+}());
14
+exports.WhitepageSnap = WhitepageSnap;
15
+var MarkerSnap = (function () {
16
+    function MarkerSnap() {
17
+    }
18
+    return MarkerSnap;
19
+}());
20
+exports.MarkerSnap = MarkerSnap;

+ 76
- 0
dist/cjs/whiteboard/MirrorWhiteboard/index.js View File

1
+"use strict";
2
+var __extends = (this && this.__extends) || (function () {
3
+    var extendStatics = function (d, b) {
4
+        extendStatics = Object.setPrototypeOf ||
5
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+        return extendStatics(d, b);
8
+    };
9
+    return function (d, b) {
10
+        extendStatics(d, b);
11
+        function __() { this.constructor = d; }
12
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+    };
14
+})();
15
+Object.defineProperty(exports, "__esModule", { value: true });
16
+var dom_1 = require("../../utils/dom");
17
+var index_1 = require("../AbstractWhiteboard/index");
18
+var prefix = 'fcw-board';
19
+var MirrorWhiteboard = (function (_super) {
20
+    __extends(MirrorWhiteboard, _super);
21
+    function MirrorWhiteboard() {
22
+        var _this = _super !== null && _super.apply(this, arguments) || this;
23
+        _this.mode = 'mirror';
24
+        return _this;
25
+    }
26
+    MirrorWhiteboard.prototype.init = function () {
27
+        var _this = this;
28
+        this.imgsContainer = dom_1.createDivWithClassName(prefix + "-imgs", this.target);
29
+        this.pagesContainer = dom_1.createDivWithClassName(prefix + "-pages", this.target);
30
+        if (!this.eventHub) {
31
+            throw new Error('Invalid eventHub');
32
+        }
33
+        this.eventHub.on('sync', function (ev) {
34
+            if (ev.target !== 'whiteboard' || !ev.border) {
35
+                return;
36
+            }
37
+            if (ev.event === 'borderSnap') {
38
+                _this.applySnap(ev.border);
39
+            }
40
+            if (ev.event === 'borderChangePage' && ev.id === _this.id) {
41
+                if (_this.isInitialized) {
42
+                    _this.onPageChange(ev.border.visiblePageIndex);
43
+                }
44
+            }
45
+            if (ev.event === 'finish' && ev.id === _this.id) {
46
+                _this.destroy();
47
+            }
48
+        });
49
+    };
50
+    MirrorWhiteboard.prototype.destroy = function () {
51
+        _super.prototype.destroy.call(this);
52
+    };
53
+    MirrorWhiteboard.prototype.onPageChange = function (nextPageIndex) {
54
+        if (this.visiblePageIndex === nextPageIndex) {
55
+            return;
56
+        }
57
+        this.siema.goTo(nextPageIndex);
58
+        this.visiblePageIndex = nextPageIndex;
59
+        this.pages.forEach(function (page, i) {
60
+            if (nextPageIndex === i) {
61
+                page.show();
62
+            }
63
+            else {
64
+                page.hide();
65
+            }
66
+        });
67
+        this.emit({
68
+            event: 'borderChangePage',
69
+            id: this.id,
70
+            target: 'whiteboard',
71
+            border: this.captureSnap()
72
+        });
73
+    };
74
+    return MirrorWhiteboard;
75
+}(index_1.AbstractWhiteboard));
76
+exports.MirrorWhiteboard = MirrorWhiteboard;

+ 103
- 0
dist/cjs/whiteboard/ReplayWhiteboard/index.js View File

1
+"use strict";
2
+var __extends = (this && this.__extends) || (function () {
3
+    var extendStatics = function (d, b) {
4
+        extendStatics = Object.setPrototypeOf ||
5
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+        return extendStatics(d, b);
8
+    };
9
+    return function (d, b) {
10
+        extendStatics(d, b);
11
+        function __() { this.constructor = d; }
12
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+    };
14
+})();
15
+Object.defineProperty(exports, "__esModule", { value: true });
16
+var MirrorWhiteboard_1 = require("../MirrorWhiteboard");
17
+var EventHub_1 = require("../../event/EventHub");
18
+var windowSize = 60 * 1000;
19
+var duration = 0.05;
20
+var ReplayWhiteboard = (function (_super) {
21
+    __extends(ReplayWhiteboard, _super);
22
+    function ReplayWhiteboard() {
23
+        var _this = _super !== null && _super.apply(this, arguments) || this;
24
+        _this.leftEvents = [];
25
+        _this.currentRelativeTime = 0;
26
+        _this.loadedRelativeTime = -1;
27
+        _this.loadingLock = false;
28
+        _this.seekingLock = false;
29
+        _this.seek = function () {
30
+            if (_this.seekingLock) {
31
+                return;
32
+            }
33
+            _this.seekingLock = true;
34
+            if (_this.loadedRelativeTime < _this.currentRelativeTime) {
35
+                _this.loadEvents();
36
+            }
37
+            var waitingEvents = [];
38
+            var leftEvents = [];
39
+            _this.leftEvents.forEach(function (e, i) {
40
+                if (e.timestamp && e.timestamp < _this.currentRelativeTime + _this.recordStartTime) {
41
+                    waitingEvents.push(e);
42
+                }
43
+                else {
44
+                    leftEvents.push(e);
45
+                }
46
+            });
47
+            _this.leftEvents = leftEvents;
48
+            waitingEvents.forEach(function (e) {
49
+                _this.perform(e);
50
+            });
51
+            _this.currentRelativeTime += duration;
52
+            _this.seekingLock = false;
53
+        };
54
+        _this.perform = function (e) {
55
+            _this.eventHub.emit('sync', e);
56
+        };
57
+        return _this;
58
+    }
59
+    ReplayWhiteboard.prototype.setContext = function (recordStartTime, onLoad) {
60
+        var _this = this;
61
+        this.recordStartTime = recordStartTime;
62
+        this.onLoad = onLoad;
63
+        if (this.interval) {
64
+            clearInterval(this.interval);
65
+        }
66
+        this.interval = setInterval(function () {
67
+            _this.seek();
68
+        }, duration * 1000);
69
+    };
70
+    ReplayWhiteboard.prototype.setCurrentRelativeTime = function (time) {
71
+        this.currentRelativeTime = time;
72
+        this.loadedRelativeTime = this.currentRelativeTime - 1;
73
+    };
74
+    ReplayWhiteboard.prototype.close = function () {
75
+        _super.prototype.close.call(this);
76
+        if (this.interval) {
77
+            clearInterval(this.interval);
78
+        }
79
+    };
80
+    ReplayWhiteboard.prototype.init = function () {
81
+        this.eventHub = new EventHub_1.EventHub();
82
+        _super.prototype.init.call(this);
83
+    };
84
+    ReplayWhiteboard.prototype.loadEvents = function () {
85
+        var _this = this;
86
+        if (this.onLoad && !this.loadingLock) {
87
+            this.loadingLock = true;
88
+            var startTime = this.recordStartTime + this.currentRelativeTime;
89
+            var endTime = startTime + windowSize;
90
+            this.onLoad(startTime, endTime)
91
+                .then(function (events) {
92
+                var _a;
93
+                _this.loadedRelativeTime = _this.currentRelativeTime;
94
+                (_a = _this.leftEvents).push.apply(_a, (events || []));
95
+            })
96
+                .finally(function () {
97
+                _this.loadingLock = false;
98
+            });
99
+        }
100
+    };
101
+    return ReplayWhiteboard;
102
+}(MirrorWhiteboard_1.MirrorWhiteboard));
103
+exports.ReplayWhiteboard = ReplayWhiteboard;

dist/cjs/board/WhitePage/index.js → dist/cjs/whiteboard/WhitePage/index.js View File

1
 "use strict";
1
 "use strict";
2
 Object.defineProperty(exports, "__esModule", { value: true });
2
 Object.defineProperty(exports, "__esModule", { value: true });
3
-var index_1 = require("./../Drawboard/index");
4
-var uuid_1 = require("./../../utils/uuid");
3
+var index_1 = require("./../../drawboard/Drawboard/index");
4
+var uuid_1 = require("../../utils/uuid");
5
 var types_1 = require("../../markers/types");
5
 var types_1 = require("../../markers/types");
6
-require("./index.less");
7
 var dom_1 = require("../../utils/dom");
6
 var dom_1 = require("../../utils/dom");
7
+require("./index.less");
8
 var prefix = 'fcw-page';
8
 var prefix = 'fcw-page';
9
 var WhitePage = (function () {
9
 var WhitePage = (function () {
10
     function WhitePage(source, _a) {
10
     function WhitePage(source, _a) {
11
-        var _b = _a === void 0 ? {} : _a, mode = _b.mode, eventHub = _b.eventHub, parentContainer = _b.parentContainer;
11
+        var _b = _a === void 0 ? {} : _a, mode = _b.mode, whiteboard = _b.whiteboard, parentContainer = _b.parentContainer, extraToolbarItems = _b.extraToolbarItems;
12
         this.id = uuid_1.uuid();
12
         this.id = uuid_1.uuid();
13
         this.mode = 'master';
13
         this.mode = 'master';
14
         if (mode) {
14
         if (mode) {
15
             this.mode = mode;
15
             this.mode = mode;
16
         }
16
         }
17
-        this.eventHub = eventHub;
18
         this.parentContainer = parentContainer;
17
         this.parentContainer = parentContainer;
18
+        this.whiteboard = whiteboard;
19
         this.initSource(source);
19
         this.initSource(source);
20
         if (this.mode === 'master') {
20
         if (this.mode === 'master') {
21
-            this.initMaster();
21
+            this.initMaster(extraToolbarItems);
22
         }
22
         }
23
         if (this.mode === 'mirror') {
23
         if (this.mode === 'mirror') {
24
             this.initMirror();
24
             this.initMirror();
33
     WhitePage.prototype.show = function () {
33
     WhitePage.prototype.show = function () {
34
         this.drawboard.show();
34
         this.drawboard.show();
35
     };
35
     };
36
-    WhitePage.prototype.close = function () {
37
-        this.drawboard.close();
36
+    WhitePage.prototype.destroy = function () {
37
+        this.drawboard.destroy();
38
+    };
39
+    WhitePage.prototype.captureSnap = function () {
40
+        var markerSnaps = this.drawboard.markers.map(function (m) { return m.captureSnap(); });
41
+        return {
42
+            id: this.id,
43
+            markers: markerSnaps
44
+        };
45
+    };
46
+    WhitePage.prototype.applySnap = function (snap) {
47
+        var _this = this;
48
+        var markerIdsSet = new Set();
49
+        snap.markers.forEach(function (markerSnap) {
50
+            var marker = _this.drawboard.markerMap[markerSnap.id];
51
+            markerIdsSet.add(markerSnap.id);
52
+            if (marker) {
53
+                marker.applySnap(markerSnap);
54
+            }
55
+            else {
56
+                var newMarker = _this.drawboard.addMarker(types_1.getMarkerByType(markerSnap.type), {
57
+                    id: markerSnap.id
58
+                });
59
+                newMarker.applySnap(markerSnap);
60
+            }
61
+        });
62
+        this.drawboard.markers.forEach(function (marker) {
63
+            if (!markerIdsSet.has(marker.id)) {
64
+                _this.drawboard.deleteMarkerWithEvent(marker);
65
+            }
66
+        });
38
     };
67
     };
39
     WhitePage.prototype.initSource = function (source) {
68
     WhitePage.prototype.initSource = function (source) {
40
         if (typeof source.imgSrc === 'string' && !this.parentContainer) {
69
         if (typeof source.imgSrc === 'string' && !this.parentContainer) {
53
             this.container.appendChild(this.target);
82
             this.container.appendChild(this.target);
54
         }
83
         }
55
     };
84
     };
56
-    WhitePage.prototype.initMaster = function () {
85
+    WhitePage.prototype.initMaster = function (extraToolbarItems) {
57
         var _this = this;
86
         var _this = this;
58
-        if (this.eventHub) {
87
+        if (this.whiteboard) {
59
             this.drawboard = new index_1.Drawboard({ imgEle: this.target }, {
88
             this.drawboard = new index_1.Drawboard({ imgEle: this.target }, {
89
+                extraToolbarItems: extraToolbarItems,
90
+                mountContainer: this.whiteboard.target,
60
                 page: this,
91
                 page: this,
61
-                onChange: function (ev) { return _this.eventHub.emit('sync', ev); }
92
+                onChange: function (ev) { return _this.whiteboard.emit(ev); }
62
             });
93
             });
63
         }
94
         }
64
         else {
95
         else {
65
-            this.drawboard = new index_1.Drawboard({ imgEle: this.target }, { page: this });
96
+            this.drawboard = new index_1.Drawboard({ imgEle: this.target }, { page: this, mountContainer: this.whiteboard.target });
66
         }
97
         }
67
     };
98
     };
68
     WhitePage.prototype.initMirror = function () {
99
     WhitePage.prototype.initMirror = function () {
69
         var _this = this;
100
         var _this = this;
70
-        if (!this.eventHub) {
71
-            throw new Error('Invalid eventHub');
101
+        if (!this.whiteboard) {
102
+            throw new Error('Invalid whiteboard');
72
         }
103
         }
73
-        this.drawboard = new index_1.Drawboard({ imgEle: this.target }, { page: this });
74
-        this.eventHub.on('sync', function (ev) {
104
+        this.drawboard = new index_1.Drawboard({ imgEle: this.target }, { page: this, mountContainer: this.whiteboard.target });
105
+        this.whiteboard.eventHub.on('sync', function (ev) {
75
             try {
106
             try {
76
                 if (ev.target === 'page' && ev.id === _this.id) {
107
                 if (ev.target === 'page' && ev.id === _this.id) {
77
                     _this.onPageSync();
108
                     _this.onPageSync();
87
     };
118
     };
88
     WhitePage.prototype.onPageSync = function () { };
119
     WhitePage.prototype.onPageSync = function () { };
89
     WhitePage.prototype.onMarkerSync = function (ev) {
120
     WhitePage.prototype.onMarkerSync = function (ev) {
90
-        if (ev.event === 'add' && ev.parentId === this.id) {
91
-            var data = ev.data;
92
-            var marker = this.drawboard.markerMap[data.id];
121
+        if (!ev.marker) {
122
+            return;
123
+        }
124
+        var id = ev.id;
125
+        if (ev.event === 'addMarker' && ev.parentId === this.id) {
126
+            var marker = this.drawboard.markerMap[id];
93
             if (!marker) {
127
             if (!marker) {
94
-                this.drawboard.addMarker(types_1.getMarkerByType(data.type), { id: data.id });
128
+                this.drawboard.addMarker(types_1.getMarkerByType(ev.marker.type), {
129
+                    id: ev.marker.id,
130
+                    originX: ev.marker.dx,
131
+                    originY: ev.marker.dy
132
+                });
95
             }
133
             }
96
         }
134
         }
97
-        if (!ev.id) {
135
+        if (!id) {
98
             return;
136
             return;
99
         }
137
         }
100
-        if (ev.event === 'remove') {
101
-            var data = ev.data;
102
-            var marker = this.drawboard.markerMap[data.id];
138
+        if (ev.event === 'removeMarker') {
139
+            var marker = this.drawboard.markerMap[id];
103
             if (marker) {
140
             if (marker) {
104
                 this.drawboard.deleteMarker(marker);
141
                 this.drawboard.deleteMarker(marker);
105
             }
142
             }
106
         }
143
         }
107
-        if (ev.event === 'move' || ev.event === 'resize') {
108
-            var marker = this.drawboard.markerMap[ev.id];
144
+        if (ev.event === 'moveMarker' || ev.event === 'resizeMarker') {
145
+            var marker = this.drawboard.markerMap[id];
109
             if (marker) {
146
             if (marker) {
110
-                marker.reactToManipulation(ev.event, ev.data);
147
+                marker.reactToManipulation(ev.event, ev.marker);
111
             }
148
             }
112
         }
149
         }
113
-        if (ev.event === 'changeText') {
114
-            var marker = this.drawboard.markerMap[ev.id];
150
+        if (ev.event === 'inputMarker') {
151
+            var marker = this.drawboard.markerMap[id];
115
             if (marker) {
152
             if (marker) {
116
-                marker.setText(ev.data);
153
+                marker.setText(ev.marker.text);
117
             }
154
             }
118
         }
155
         }
119
     };
156
     };

+ 159
- 0
dist/cjs/whiteboard/Whiteboard/index.js View File

1
+"use strict";
2
+var __extends = (this && this.__extends) || (function () {
3
+    var extendStatics = function (d, b) {
4
+        extendStatics = Object.setPrototypeOf ||
5
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+        return extendStatics(d, b);
8
+    };
9
+    return function (d, b) {
10
+        extendStatics(d, b);
11
+        function __() { this.constructor = d; }
12
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+    };
14
+})();
15
+Object.defineProperty(exports, "__esModule", { value: true });
16
+var index_1 = require("../WhitePage/index");
17
+var dom_1 = require("../../utils/dom");
18
+var index_2 = require("../AbstractWhiteboard/index");
19
+var toolbar_items_1 = require("../../toolbar/toolbar-items");
20
+var LeftArrowIcon = require('../../assets/bx-left-arrow.svg');
21
+var RightArrowIcon = require('../../assets/bx-right-arrow.svg');
22
+var FinishIcon = require('../../assets/finish.svg');
23
+var RollbackIcon = require('../../assets/rollback.svg');
24
+var prefix = 'fcw-board';
25
+var Whiteboard = (function (_super) {
26
+    __extends(Whiteboard, _super);
27
+    function Whiteboard() {
28
+        var _this = _super !== null && _super.apply(this, arguments) || this;
29
+        _this.mode = 'master';
30
+        return _this;
31
+    }
32
+    Whiteboard.prototype.destroy = function () {
33
+        _super.prototype.destroy.call(this);
34
+    };
35
+    Whiteboard.prototype.init = function () {
36
+        this.imgsContainer = dom_1.createDivWithClassName(prefix + "-imgs", this.target);
37
+        this.pagesContainer = dom_1.createDivWithClassName(prefix + "-pages", this.target);
38
+        this.initMaster();
39
+        this.snapHistory.push(this.captureSnap(false));
40
+        this.emitSnapshot();
41
+    };
42
+    Whiteboard.prototype.initMaster = function () {
43
+        var _this = this;
44
+        this.isInitialized = true;
45
+        var prevToolbarItem = {
46
+            icon: LeftArrowIcon,
47
+            name: 'prev-flip-arrow',
48
+            tooltipText: 'Prev',
49
+            onClick: function () {
50
+                var nextPageIndex = _this.visiblePageIndex - 1 < 0 ? _this.pages.length - 1 : _this.visiblePageIndex - 1;
51
+                document.querySelectorAll('.fc-whiteboard-indicator-current').forEach(function (e) {
52
+                    e.innerHTML = "" + (nextPageIndex + 1);
53
+                });
54
+                _this.onPageChange(nextPageIndex);
55
+            }
56
+        };
57
+        var indicatorContainer = document.createElement('div');
58
+        indicatorContainer.className = 'fc-whiteboard-indicator-container';
59
+        var indicatorCurrent = document.createElement('span');
60
+        indicatorCurrent.className = 'fc-whiteboard-indicator-current';
61
+        indicatorCurrent.innerHTML = "" + (this.visiblePageIndex + 1);
62
+        indicatorContainer.appendChild(indicatorCurrent);
63
+        indicatorContainer.appendChild(document.createTextNode("/" + this.sources.length));
64
+        var indicatorItem = {
65
+            name: 'indicator',
66
+            onRender: function () { return indicatorContainer; }
67
+        };
68
+        var nextToolbarItem = {
69
+            icon: RightArrowIcon,
70
+            name: 'next-flip-arrow',
71
+            tooltipText: 'Next',
72
+            onClick: function () {
73
+                var nextPageIndex = _this.visiblePageIndex + 1 > _this.pages.length - 1 ? 0 : _this.visiblePageIndex + 1;
74
+                document.querySelectorAll('.fc-whiteboard-indicator-current').forEach(function (e) {
75
+                    e.innerHTML = "" + (nextPageIndex + 1);
76
+                });
77
+                _this.onPageChange(nextPageIndex);
78
+            }
79
+        };
80
+        var finishItem = {
81
+            icon: FinishIcon,
82
+            name: 'finish',
83
+            tooltipText: 'Finish',
84
+            onClick: function () {
85
+                _this.emit({
86
+                    event: 'finish',
87
+                    id: _this.id,
88
+                    target: 'whiteboard'
89
+                });
90
+            }
91
+        };
92
+        var rollbackItem = {
93
+            icon: RollbackIcon,
94
+            name: 'rollback',
95
+            tooltipText: 'Rollback',
96
+            shortcut: 'ESC',
97
+            onClick: function () {
98
+                _this.rollbackSnap();
99
+            }
100
+        };
101
+        this.sources.forEach(function (source) {
102
+            var page = new index_1.WhitePage({ imgSrc: source }, {
103
+                mode: _this.mode,
104
+                whiteboard: _this,
105
+                parentContainer: _this.pagesContainer,
106
+                extraToolbarItems: [
107
+                    toolbar_items_1.separatorToolbarItem,
108
+                    prevToolbarItem,
109
+                    indicatorItem,
110
+                    nextToolbarItem,
111
+                    toolbar_items_1.separatorToolbarItem,
112
+                    finishItem,
113
+                    rollbackItem
114
+                ]
115
+            });
116
+            page.container.style.visibility = 'hidden';
117
+            _this.pages.push(page);
118
+        });
119
+        this.initSiema();
120
+    };
121
+    Whiteboard.prototype.onPageChange = function (nextPageIndex) {
122
+        if (this.visiblePageIndex === nextPageIndex) {
123
+            return;
124
+        }
125
+        this.siema.goTo(nextPageIndex);
126
+        this.visiblePageIndex = nextPageIndex;
127
+        this.pages.forEach(function (page, i) {
128
+            if (nextPageIndex === i) {
129
+                page.show();
130
+            }
131
+            else {
132
+                page.hide();
133
+            }
134
+        });
135
+        this.emit({
136
+            event: 'borderChangePage',
137
+            id: this.id,
138
+            target: 'whiteboard',
139
+            border: this.captureSnap()
140
+        });
141
+    };
142
+    Whiteboard.prototype.emitSnapshot = function () {
143
+        var _this = this;
144
+        var innerFunc = function () {
145
+            _this.emit({
146
+                event: 'borderSnap',
147
+                id: _this.id,
148
+                target: 'whiteboard',
149
+                border: _this.captureSnap(false)
150
+            });
151
+        };
152
+        this.emitInterval = setInterval(function () {
153
+            innerFunc();
154
+        }, this.snapInterval);
155
+        setTimeout(innerFunc, 500);
156
+    };
157
+    return Whiteboard;
158
+}(index_2.AbstractWhiteboard));
159
+exports.Whiteboard = Whiteboard;

+ 18921
- 2825
dist/index.js
File diff suppressed because it is too large
View File


+ 1
- 1
dist/index.js.map
File diff suppressed because it is too large
View File


+ 0
- 53
dist/types/board/Drawboard/index.d.ts View File

1
-import { WhitePageSource } from './../types';
2
-import { Baseboard } from './../Baseboard/index';
3
-import { BaseMarker } from './../../markers/BaseMarker/index';
4
-import { WhitePage } from './../WhitePage/index';
5
-import { onSyncFunc } from './../../event/Event';
6
-import './index.less';
7
-export declare class Drawboard extends Baseboard {
8
-    private scale;
9
-    page: WhitePage;
10
-    private markers;
11
-    readonly markerMap: {
12
-        [key: string]: BaseMarker;
13
-    };
14
-    private activeMarker;
15
-    private toolbar;
16
-    private toolbars;
17
-    private toolbarUI;
18
-    private onComplete;
19
-    private onChange;
20
-    private onCancel;
21
-    constructor(source: WhitePageSource, { page, onChange }?: {
22
-        page?: WhitePage;
23
-        onChange?: onSyncFunc;
24
-    });
25
-    open: (onComplete?: ((dataUrl: string) => void) | undefined, onCancel?: (() => void) | undefined) => void;
26
-    hide: () => void;
27
-    show: () => void;
28
-    close: () => void;
29
-    render: (onComplete: (dataUrl: string) => void, onCancel?: (() => void) | undefined) => void;
30
-    addMarker: (markerType: typeof BaseMarker, { id }?: {
31
-        id?: string | undefined;
32
-    }) => void;
33
-    deleteActiveMarker: () => void;
34
-    private setTargetRect;
35
-    private startRender;
36
-    private attachEvents;
37
-    private mouseDown;
38
-    private mouseMove;
39
-    private mouseUp;
40
-    private adjustUI;
41
-    private adjustSize;
42
-    private positionUI;
43
-    private positionToolbar;
44
-    private showUI;
45
-    private setStyles;
46
-    private toolbarClick;
47
-    private selectMarker;
48
-    deleteMarker: (marker: BaseMarker) => void;
49
-    private complete;
50
-    private cancel;
51
-    private renderFinished;
52
-    private renderFinishedClose;
53
-}

+ 0
- 28
dist/types/board/WhitePage/index.d.ts View File

1
-import { EventHub } from '../../event/EventHub';
2
-import { WhiteboardMode, WhitePageSource } from './../types';
3
-import { Drawboard } from './../Drawboard/index';
4
-import './index.less';
5
-export declare class WhitePage {
6
-    id: string;
7
-    source: WhitePageSource;
8
-    target: HTMLImageElement;
9
-    container: HTMLDivElement;
10
-    parentContainer?: HTMLDivElement;
11
-    mode: WhiteboardMode;
12
-    drawboard: Drawboard;
13
-    eventHub?: EventHub;
14
-    constructor(source: WhitePageSource, { mode, eventHub, parentContainer }?: {
15
-        mode?: WhiteboardMode;
16
-        eventHub?: EventHub;
17
-        parentContainer?: HTMLDivElement;
18
-    });
19
-    open(): void;
20
-    hide(): void;
21
-    show(): void;
22
-    close(): void;
23
-    private initSource;
24
-    protected initMaster(): void;
25
-    protected initMirror(): void;
26
-    private onPageSync;
27
-    private onMarkerSync;
28
-}

+ 0
- 45
dist/types/board/Whiteboard/index.d.ts View File

1
-import { WhiteboardMode } from '../types';
2
-import { WhitePage } from '../WhitePage/index';
3
-import { EventHub } from '../../event/EventHub';
4
-import './index.less';
5
-export declare class SerializableWhiteboard {
6
-    id: string;
7
-    sources: string[];
8
-    pageIds: string[];
9
-    visiblePageIndex: number;
10
-}
11
-export declare class Whiteboard {
12
-    id: string;
13
-    sources: string[];
14
-    target: HTMLDivElement;
15
-    imgsContainer: HTMLDivElement;
16
-    pagesContainer: HTMLDivElement;
17
-    eventHub?: EventHub;
18
-    mode: WhiteboardMode;
19
-    isFullscreen: boolean;
20
-    pages: WhitePage[];
21
-    readonly activePage: WhitePage;
22
-    siema: any;
23
-    isInitialized: boolean;
24
-    isSyncing: boolean;
25
-    visiblePageIndex: number;
26
-    emitInterval: any;
27
-    constructor(target: HTMLDivElement, { sources, eventHub, mode, visiblePageIndex }?: {
28
-        sources?: string[];
29
-        eventHub?: EventHub;
30
-        mode?: WhiteboardMode;
31
-        visiblePageIndex?: number;
32
-    });
33
-    open(): void;
34
-    close(): void;
35
-    show(): void;
36
-    hide(): void;
37
-    snap(): SerializableWhiteboard;
38
-    private init;
39
-    private initMaster;
40
-    private initMirror;
41
-    private initSiema;
42
-    private onPageChange;
43
-    private emitSnapshot;
44
-    private onSnapshot;
45
-}

+ 0
- 5
dist/types/board/types.d.ts View File

1
-export declare type WhiteboardMode = 'master' | 'mirror';
2
-export declare type WhitePageSource = {
3
-    imgEle?: HTMLImageElement;
4
-    imgSrc?: string;
5
-};

dist/types/board/Baseboard/index.d.ts → dist/types/drawboard/Baseboard/index.d.ts View File

1
-import { WhitePageSource } from './../types';
1
+import { Source } from './../../utils/types';
2
 export declare class Baseboard {
2
 export declare class Baseboard {
3
     id: string;
3
     id: string;
4
-    source: WhitePageSource;
4
+    isFullscreen: boolean;
5
+    source: Source;
5
     target: HTMLImageElement;
6
     target: HTMLImageElement;
6
     targetRect: ClientRect;
7
     targetRect: ClientRect;
7
     boardCanvas: SVGSVGElement;
8
     boardCanvas: SVGSVGElement;
9
     defs: SVGDefsElement;
10
     defs: SVGDefsElement;
10
     width: number;
11
     width: number;
11
     height: number;
12
     height: number;
12
-    constructor(source: WhitePageSource);
13
-    protected initBoard: () => void;
13
+    constructor(source: Source);
14
+    protected initBoard: (mountContainer: HTMLElement) => void;
14
     protected positionBoard: () => void;
15
     protected positionBoard: () => void;
15
 }
16
 }

+ 64
- 0
dist/types/drawboard/Drawboard/index.d.ts View File

1
+import { HotkeysListener } from 'fc-hotkeys';
2
+import { Source } from './../../utils/types';
3
+import { Baseboard } from './../Baseboard/index';
4
+import { BaseMarker } from './../../markers/BaseMarker/index';
5
+import { WhitePage } from '../../whiteboard/WhitePage';
6
+import { onSyncFunc } from '../../event/SyncEvent';
7
+import { Toolbar } from '../../toolbar/Toolbar';
8
+import { ToolbarItem } from '../../toolbar/ToolbarItem';
9
+import './index.less';
10
+export declare class Drawboard extends Baseboard {
11
+    mountContainer: HTMLElement;
12
+    scale: number;
13
+    zIndex: number;
14
+    allowKeyboard?: boolean | undefined;
15
+    page: WhitePage;
16
+    listener: HotkeysListener;
17
+    markers: BaseMarker[];
18
+    readonly markerMap: {
19
+        [key: string]: BaseMarker;
20
+    };
21
+    activeMarker: BaseMarker | null;
22
+    toolbarItems: ToolbarItem[];
23
+    toolbar: Toolbar;
24
+    toolbarUI: HTMLElement;
25
+    onComplete: (dataUrl: string) => void;
26
+    onChange: onSyncFunc;
27
+    onCancel: () => void;
28
+    constructor(source: Source, { allowKeyboard, extraToolbarItems, mountContainer, page, zIndex, onChange }?: Partial<Drawboard> & {
29
+        extraToolbarItems?: ToolbarItem[];
30
+    });
31
+    open: (onComplete?: ((dataUrl: string) => void) | undefined, onCancel?: (() => void) | undefined) => void;
32
+    hide: () => void;
33
+    show: () => void;
34
+    destroy: () => void;
35
+    render: (onComplete: (dataUrl: string) => void, onCancel?: (() => void) | undefined) => void;
36
+    addMarker: (markerType: typeof BaseMarker, { id, originX, originY }?: {
37
+        id?: string | undefined;
38
+        originX?: number | undefined;
39
+        originY?: number | undefined;
40
+    }) => BaseMarker;
41
+    deleteActiveMarker: () => void;
42
+    clearMarkers: () => void;
43
+    deleteMarkerWithEvent: (marker: BaseMarker | null) => void;
44
+    private setTargetRect;
45
+    private startRender;
46
+    private attachEvents;
47
+    private mouseDown;
48
+    private mouseMove;
49
+    private mouseUp;
50
+    private onKeyboard;
51
+    private adjustUI;
52
+    private adjustSize;
53
+    private positionUI;
54
+    private positionToolbar;
55
+    private showUI;
56
+    private setStyles;
57
+    private toolbarClick;
58
+    private selectMarker;
59
+    deleteMarker: (marker: BaseMarker) => void;
60
+    private complete;
61
+    private cancel;
62
+    private renderFinished;
63
+    private renderFinishedClose;
64
+}

+ 0
- 11
dist/types/event/Event.d.ts View File

1
-export declare type TargetType = 'whiteboard' | 'page' | 'marker';
2
-export declare type EventType = 'snap' | 'add' | 'resize' | 'move' | 'remove' | 'changeIndex' | 'changeText';
3
-export declare type PositionType = 'left' | 'right' | 'topLeft' | 'bottomLeft' | 'topRight' | 'bottomRight' | 'centerLeft' | 'centerRight' | 'topCenter' | 'bottomCenter';
4
-export interface SyncEvent {
5
-    target: TargetType;
6
-    id?: string;
7
-    parentId?: string;
8
-    event: EventType;
9
-    data?: object | string | number;
10
-}
11
-export declare type onSyncFunc = (ev: SyncEvent) => void;

+ 15
- 0
dist/types/event/SyncEvent.d.ts View File

1
+import { BorderEventType } from './border-events';
2
+import { MarkerEventType, MarkerData } from './marker-events';
3
+import { WhiteboardSnap } from '../whiteboard/AbstractWhiteboard/snap';
4
+export declare type TargetType = 'whiteboard' | 'page' | 'marker';
5
+export declare type EventType = MarkerEventType | BorderEventType;
6
+export declare type onSyncFunc = (ev: SyncEvent) => void;
7
+export interface SyncEvent {
8
+    target: TargetType;
9
+    id?: string;
10
+    parentId?: string;
11
+    event: EventType;
12
+    marker?: MarkerData;
13
+    border?: WhiteboardSnap;
14
+    timestamp?: number;
15
+}

+ 1
- 0
dist/types/event/border-events.d.ts View File

1
+export declare type BorderEventType = 'borderSnap' | 'borderChangePage' | 'finish';

+ 11
- 0
dist/types/event/marker-events.d.ts View File

1
+import { MarkerType } from './../markers/types';
2
+import { PositionType } from '../utils/layout';
3
+export declare type MarkerEventType = 'addMarker' | 'resizeMarker' | 'moveMarker' | 'removeMarker' | 'inputMarker';
4
+export interface MarkerData {
5
+    id?: string;
6
+    type?: MarkerType;
7
+    text?: string;
8
+    dx?: number;
9
+    dy?: number;
10
+    pos?: PositionType;
11
+}

+ 8
- 3
dist/types/index.d.ts View File

1
-export { Drawboard } from './board/Drawboard';
2
-export { Whiteboard } from './board/Whiteboard';
3
-export { WhiteboardMode } from './board/types';
1
+export { Drawboard } from './drawboard/Drawboard';
2
+export { separatorToolbarItem, closeToolbarItem } from './toolbar/toolbar-items';
3
+export { Mode } from './utils/types';
4
+export { SyncEvent } from './event/SyncEvent';
5
+export { EventHub } from './event/EventHub';
6
+export { Whiteboard } from './whiteboard/Whiteboard';
7
+export { MirrorWhiteboard } from './whiteboard/MirrorWhiteboard';
8
+export { ReplayWhiteboard } from './whiteboard/ReplayWhiteboard';

+ 2
- 2
dist/types/markers/ArrowMarker/index.d.ts View File

1
 import { MarkerType } from './../types';
1
 import { MarkerType } from './../types';
2
 import { LinearMarker } from '../LinearMarker';
2
 import { LinearMarker } from '../LinearMarker';
3
-import { WhitePage } from '../../board/WhitePage';
3
+import { WhitePage } from '../../whiteboard/WhitePage';
4
 export declare class ArrowMarker extends LinearMarker {
4
 export declare class ArrowMarker extends LinearMarker {
5
     type: MarkerType;
5
     type: MarkerType;
6
     static createMarker: (page?: WhitePage | undefined) => LinearMarker;
6
     static createMarker: (page?: WhitePage | undefined) => LinearMarker;
7
     private readonly ARROW_SIZE;
7
     private readonly ARROW_SIZE;
8
-    protected setup(): void;
8
+    protected init(): void;
9
 }
9
 }

+ 28
- 23
dist/types/markers/BaseMarker/index.d.ts View File

1
-import { WhitePage } from './../../board/WhitePage/index';
2
-import { PositionType } from '../../event/Event';
3
-import { onSyncFunc, EventType } from '../../event/Event';
1
+import { WhitePage } from '../../whiteboard/WhitePage/index';
2
+import { PositionType } from '../../utils/layout';
3
+import { onSyncFunc, EventType } from '../../event/SyncEvent';
4
 import { MarkerType } from '../types';
4
 import { MarkerType } from '../types';
5
-export declare class BaseMarker {
5
+import { MarkerSnap } from '../../whiteboard/AbstractWhiteboard/snap';
6
+import { Drawboard } from '../../drawboard/Drawboard/index';
7
+import { DomEventAware } from '../../renderer/DomEventAware/index';
8
+export declare class BaseMarker extends DomEventAware {
6
     id: string;
9
     id: string;
7
     type: MarkerType;
10
     type: MarkerType;
8
     page?: WhitePage;
11
     page?: WhitePage;
12
+    drawboard?: Drawboard;
9
     onChange: onSyncFunc;
13
     onChange: onSyncFunc;
10
     static createMarker: (page?: WhitePage | undefined) => BaseMarker;
14
     static createMarker: (page?: WhitePage | undefined) => BaseMarker;
11
     visual: SVGGElement;
15
     visual: SVGGElement;
12
     renderVisual: SVGGElement;
16
     renderVisual: SVGGElement;
13
     onSelected: (marker: BaseMarker) => void;
17
     onSelected: (marker: BaseMarker) => void;
14
     defs: SVGElement[];
18
     defs: SVGElement[];
15
-    protected width: number;
16
-    protected height: number;
17
-    protected isActive: boolean;
18
-    protected isDragging: boolean;
19
-    protected isResizing: boolean;
20
-    protected previousMouseX: number;
21
-    protected previousMouseY: number;
22
-    reactToManipulation(type: EventType, { dx, dy, pos }: {
23
-        dx: number;
24
-        dy: number;
25
-        pos: PositionType;
19
+    width: number;
20
+    height: number;
21
+    isActive: boolean;
22
+    isDragging: boolean;
23
+    isResizing: boolean;
24
+    reactToManipulation(type: EventType, { dx, dy, pos }?: {
25
+        dx?: number;
26
+        dy?: number;
27
+        pos?: PositionType;
26
     }): void;
28
     }): void;
27
     manipulate: (ev: MouseEvent) => void;
29
     manipulate: (ev: MouseEvent) => void;
28
     endManipulation(): void;
30
     endManipulation(): void;
29
     select(): void;
31
     select(): void;
30
     deselect(): void;
32
     deselect(): void;
31
-    protected setup(): void;
32
-    protected addToVisual: (el: SVGElement) => void;
33
-    protected addToRenderVisual: (el: SVGElement) => void;
33
+    captureSnap(): MarkerSnap;
34
+    applySnap(snap: MarkerSnap): void;
35
+    destroy(): void;
34
     protected resize(x: number, y: number, cb?: Function): void;
36
     protected resize(x: number, y: number, cb?: Function): void;
35
     protected resizeByEvent(x: number, y: number, pos?: PositionType): void;
37
     protected resizeByEvent(x: number, y: number, pos?: PositionType): void;
36
-    protected onTouch(ev: TouchEvent): void;
37
-    private mouseDown;
38
-    private mouseUp;
39
-    private mouseMove;
40
-    private move;
38
+    move: (dx: number, dy: number) => void;
39
+    moveTo: (x: number, y: number) => void;
40
+    protected init(): void;
41
+    protected addToVisual: (el: SVGElement) => void;
42
+    protected addToRenderVisual: (el: SVGElement) => void;
43
+    protected onMouseDown: (ev: MouseEvent) => void;
44
+    protected onMouseUp: (ev: MouseEvent) => void;
45
+    protected onMouseMove: (ev: MouseEvent) => void;
41
 }
46
 }

+ 2
- 2
dist/types/markers/CoverMarker/index.d.ts View File

1
 import { MarkerType } from './../types';
1
 import { MarkerType } from './../types';
2
 import { RectBaseMarker } from '../RectMarker/RectBaseMarker';
2
 import { RectBaseMarker } from '../RectMarker/RectBaseMarker';
3
-import { WhitePage } from '../../board/WhitePage';
3
+import { WhitePage } from '../../whiteboard/WhitePage';
4
 export declare class CoverMarker extends RectBaseMarker {
4
 export declare class CoverMarker extends RectBaseMarker {
5
     type: MarkerType;
5
     type: MarkerType;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
7
-    protected setup(): void;
7
+    protected init(): void;
8
 }
8
 }

+ 2
- 2
dist/types/markers/HighlightMarker/index.d.ts View File

1
 import { MarkerType } from './../types';
1
 import { MarkerType } from './../types';
2
 import { RectBaseMarker } from '../RectMarker/RectBaseMarker';
2
 import { RectBaseMarker } from '../RectMarker/RectBaseMarker';
3
-import { WhitePage } from '../../board/WhitePage';
3
+import { WhitePage } from '../../whiteboard/WhitePage';
4
 export declare class HighlightMarker extends RectBaseMarker {
4
 export declare class HighlightMarker extends RectBaseMarker {
5
     type: MarkerType;
5
     type: MarkerType;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
7
-    protected setup(): void;
7
+    protected init(): void;
8
 }
8
 }

+ 2
- 2
dist/types/markers/LineMarker/index.d.ts View File

1
 import { MarkerType } from './../types';
1
 import { MarkerType } from './../types';
2
 import { LinearMarker } from '../LinearMarker';
2
 import { LinearMarker } from '../LinearMarker';
3
-import { WhitePage } from '../../board/WhitePage';
3
+import { WhitePage } from '../../whiteboard/WhitePage';
4
 export declare class LineMarker extends LinearMarker {
4
 export declare class LineMarker extends LinearMarker {
5
     type: MarkerType;
5
     type: MarkerType;
6
     static createMarker: (page?: WhitePage | undefined) => LinearMarker;
6
     static createMarker: (page?: WhitePage | undefined) => LinearMarker;
7
-    protected setup(): void;
7
+    protected init(): void;
8
 }
8
 }

+ 17
- 12
dist/types/markers/LinearMarker/index.d.ts View File

1
-import { WhitePage } from './../../board/WhitePage/index';
1
+import { WhitePage } from '../../whiteboard/WhitePage/index';
2
 import { BaseMarker } from '../BaseMarker';
2
 import { BaseMarker } from '../BaseMarker';
3
-import { PositionType } from '../../event/Event';
4
-export declare class LinearMarker extends BaseMarker {
3
+import { PositionType } from '../../utils/layout';
4
+import { MarkerSnap } from '../../whiteboard/AbstractWhiteboard/snap';
5
+import { LinearBound } from '../types';
6
+export declare class LinearMarker extends BaseMarker implements LinearBound {
5
     static createMarker: (page?: WhitePage | undefined) => LinearMarker;
7
     static createMarker: (page?: WhitePage | undefined) => LinearMarker;
6
-    protected markerLine: SVGLineElement;
7
     private readonly MIN_LENGTH;
8
     private readonly MIN_LENGTH;
9
+    x1: number;
10
+    y1: number;
11
+    x2: number;
12
+    y2: number;
13
+    protected markerLine: SVGLineElement;
8
     private markerBgLine;
14
     private markerBgLine;
9
     private controlBox;
15
     private controlBox;
10
     private controlGrips;
16
     private controlGrips;
11
     private activeGrip;
17
     private activeGrip;
12
-    private x1;
13
-    private y1;
14
-    private x2;
15
-    private y2;
18
+    getLineLength: (x1: number, y1: number, x2: number, y2: number) => number;
19
+    captureSnap(): MarkerSnap;
20
+    applySnap(snap: MarkerSnap): void;
16
     endManipulation(): void;
21
     endManipulation(): void;
17
     select(): void;
22
     select(): void;
18
     deselect(): void;
23
     deselect(): void;
19
-    protected setup(): void;
24
+    protected init(): void;
20
     protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
25
     protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
21
     protected resizeByEvent(x: number, y: number, pos?: PositionType): void;
26
     protected resizeByEvent(x: number, y: number, pos?: PositionType): void;
22
-    private getLineLength;
23
     private addControlBox;
27
     private addControlBox;
24
     private adjustControlBox;
28
     private adjustControlBox;
25
     private addControlGrips;
29
     private addControlGrips;
26
     private createGrip;
30
     private createGrip;
27
-    private positionGrips;
28
-    private positionGrip;
29
     private gripMouseDown;
31
     private gripMouseDown;
30
     private gripMouseUp;
32
     private gripMouseUp;
31
     private gripMouseMove;
33
     private gripMouseMove;
34
+    private positionLine;
35
+    private positionGrips;
36
+    private positionGrip;
32
 }
37
 }

+ 5
- 3
dist/types/markers/RectMarker/RectBaseMarker.d.ts View File

1
-import { PositionType } from '../../event/Event';
1
+import { PositionType } from '../../utils/layout';
2
 import { RectangularMarker } from '../RectangularMarker';
2
 import { RectangularMarker } from '../RectangularMarker';
3
-import { WhitePage } from '../../board/WhitePage';
3
+import { WhitePage } from '../../whiteboard/WhitePage';
4
+import { MarkerSnap } from '../../whiteboard/AbstractWhiteboard/snap';
4
 export declare class RectBaseMarker extends RectangularMarker {
5
 export declare class RectBaseMarker extends RectangularMarker {
5
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
6
     private markerRect;
7
     private markerRect;
7
-    protected setup(): void;
8
+    applySnap(snap: MarkerSnap): void;
9
+    protected init(): void;
8
     protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
10
     protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
9
 }
11
 }

+ 2
- 2
dist/types/markers/RectMarker/index.d.ts View File

1
-import { WhitePage } from './../../board/WhitePage/index';
1
+import { WhitePage } from '../../whiteboard/WhitePage/index';
2
 import { MarkerType } from './../types';
2
 import { MarkerType } from './../types';
3
 import { RectBaseMarker } from './RectBaseMarker';
3
 import { RectBaseMarker } from './RectBaseMarker';
4
 export declare class RectMarker extends RectBaseMarker {
4
 export declare class RectMarker extends RectBaseMarker {
5
     type: MarkerType;
5
     type: MarkerType;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
6
     static createMarker: (page?: WhitePage | undefined) => RectBaseMarker;
7
-    protected setup(): void;
7
+    protected init(): void;
8
 }
8
 }

+ 11
- 8
dist/types/markers/RectangularMarker/index.d.ts View File

1
 import { BaseMarker } from '../BaseMarker';
1
 import { BaseMarker } from '../BaseMarker';
2
-import { PositionType } from '../../event/Event';
3
-import { WhitePage } from '../../board/WhitePage';
2
+import { WhitePage } from '../../whiteboard/WhitePage';
3
+import { PositionType } from '../../utils/layout';
4
+import { MarkerSnap } from '../../whiteboard/AbstractWhiteboard/snap';
4
 export declare class RectangularMarker extends BaseMarker {
5
 export declare class RectangularMarker extends BaseMarker {
5
     static createMarker: (page?: WhitePage | undefined) => RectangularMarker;
6
     static createMarker: (page?: WhitePage | undefined) => RectangularMarker;
6
     protected MIN_SIZE: number;
7
     protected MIN_SIZE: number;
9
     private controlRect;
10
     private controlRect;
10
     private controlGrips;
11
     private controlGrips;
11
     private activeGrip;
12
     private activeGrip;
13
+    captureSnap(): MarkerSnap;
14
+    applySnap(snap: MarkerSnap): void;
12
     endManipulation(): void;
15
     endManipulation(): void;
13
     select(): void;
16
     select(): void;
14
     deselect(): void;
17
     deselect(): void;
15
-    protected setup(): void;
16
-    protected resizeByEvent(x: number, y: number, pos: PositionType): void;
17
-    protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
18
-    protected onTouch(ev: TouchEvent): void;
18
+    protected init(): void;
19
+    protected resizeByEvent(dx: number, dy: number, pos: PositionType): void;
20
+    protected resize(dx: number, dy: number, onPosition?: (pos: PositionType) => void): void;
19
     private addControlBox;
21
     private addControlBox;
20
     private adjustControlBox;
22
     private adjustControlBox;
21
     private addControlGrips;
23
     private addControlGrips;
22
     private createGrip;
24
     private createGrip;
23
-    private positionGrips;
24
-    private positionGrip;
25
+    protected onTouch(ev: TouchEvent): void;
25
     private gripMouseDown;
26
     private gripMouseDown;
26
     private gripMouseUp;
27
     private gripMouseUp;
27
     private gripMouseMove;
28
     private gripMouseMove;
29
+    private positionGrips;
30
+    private positionGrip;
28
 }
31
 }

+ 8
- 5
dist/types/markers/TextMarker/index.d.ts View File

1
 import { MarkerType } from '../types';
1
 import { MarkerType } from '../types';
2
 import { RectangularMarker } from '../RectangularMarker';
2
 import { RectangularMarker } from '../RectangularMarker';
3
-import { PositionType } from '../../event/Event';
4
-import { WhitePage } from '../../board/WhitePage';
3
+import { WhitePage } from '../../whiteboard/WhitePage';
4
+import { PositionType } from '../../utils/layout';
5
+import { MarkerSnap } from '../../whiteboard/AbstractWhiteboard/snap';
5
 export declare class TextMarker extends RectangularMarker {
6
 export declare class TextMarker extends RectangularMarker {
6
     type: MarkerType;
7
     type: MarkerType;
7
     static createMarker: (page?: WhitePage | undefined) => TextMarker;
8
     static createMarker: (page?: WhitePage | undefined) => TextMarker;
8
-    setText(text: string): void;
9
     protected readonly MIN_SIZE = 50;
9
     protected readonly MIN_SIZE = 50;
10
     private readonly DEFAULT_TEXT;
10
     private readonly DEFAULT_TEXT;
11
     private text;
11
     private text;
12
-    private textElement;
13
     private inDoubleTap;
12
     private inDoubleTap;
13
+    private textElement;
14
     private editor;
14
     private editor;
15
     private editorTextArea;
15
     private editorTextArea;
16
-    protected setup(): void;
16
+    setText(text: string): void;
17
+    captureSnap(): MarkerSnap;
18
+    applySnap(snap: MarkerSnap): void;
19
+    protected init(): void;
17
     protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
20
     protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void): void;
18
     private renderText;
21
     private renderText;
19
     private sizeText;
22
     private sizeText;

+ 6
- 0
dist/types/markers/types.d.ts View File

1
 import { BaseMarker } from './BaseMarker/index';
1
 import { BaseMarker } from './BaseMarker/index';
2
 export declare type MarkerType = 'base' | 'arrow' | 'cover' | 'line' | 'rect' | 'text' | 'highlight';
2
 export declare type MarkerType = 'base' | 'arrow' | 'cover' | 'line' | 'rect' | 'text' | 'highlight';
3
+export interface LinearBound {
4
+    x1: number;
5
+    y1: number;
6
+    x2: number;
7
+    y2: number;
8
+}
3
 export declare function getMarkerByType(type: MarkerType): typeof BaseMarker;
9
 export declare function getMarkerByType(type: MarkerType): typeof BaseMarker;

+ 11
- 0
dist/types/renderer/DomEventAware/index.d.ts View File

1
+export declare abstract class DomEventAware {
2
+    x: number;
3
+    y: number;
4
+    previousMouseX: number;
5
+    previousMouseY: number;
6
+    protected init(ele: Element): void;
7
+    protected onTouch(ev: TouchEvent): void;
8
+    protected abstract onMouseDown(ev: MouseEvent): void;
9
+    protected abstract onMouseUp(ev: MouseEvent): void;
10
+    protected abstract onMouseMove(ev: MouseEvent): void;
11
+}

+ 1
- 1
dist/types/renderer/Synthetizer/index.d.ts View File

1
 export declare class Synthetizer {
1
 export declare class Synthetizer {
2
-    rasterize(target: HTMLImageElement | HTMLDivElement, markerImage: SVGSVGElement, done: (dataUrl: string) => void): void;
2
+    rasterize(target: HTMLImageElement, markerImage: SVGSVGElement, done: (dataUrl: string) => void): void;
3
 }
3
 }

+ 17
- 5
dist/types/toolbar/Toolbar.d.ts View File

1
+import { ToolbarButton } from './ToolbarButton';
1
 import { ToolbarItem } from './ToolbarItem';
2
 import { ToolbarItem } from './ToolbarItem';
2
-export declare class Toolbar {
3
+import './index.less';
4
+import { DomEventAware } from '../renderer/DomEventAware/index';
5
+import { Drawboard } from '../drawboard/Drawboard/index';
6
+export declare type MouseHandler = (ev: MouseEvent) => void;
7
+export declare class Toolbar extends DomEventAware {
3
     id: string;
8
     id: string;
4
-    private toolbarItems;
5
-    private toolbarUI;
6
-    private clickHandler;
9
+    zIndex: number;
10
+    toolbarItems: ToolbarItem[];
11
+    toolbarUI: HTMLElement;
12
+    toolbarButtons: ToolbarButton[];
13
+    readonly toolbarButtonMap: Record<string, ToolbarButton>;
14
+    clickHandler: (ev: MouseEvent, toolbarItem: ToolbarItem) => void;
7
     constructor(toolbarItems: ToolbarItem[], clickHandler: (ev: MouseEvent, toolbarItem: ToolbarItem) => void);
15
     constructor(toolbarItems: ToolbarItem[], clickHandler: (ev: MouseEvent, toolbarItem: ToolbarItem) => void);
8
-    getUI: () => HTMLElement;
16
+    getUI: (drawboard: Drawboard) => HTMLElement;
9
     hide(): void;
17
     hide(): void;
10
     show(): void;
18
     show(): void;
19
+    protected onMouseDown: (downEv: MouseEvent) => void;
20
+    protected onMouseUp: (ev: MouseEvent) => void;
21
+    protected onMouseMove: (ev: MouseEvent) => void;
22
+    protected onDragMove: (event: any) => void;
11
 }
23
 }

+ 6
- 2
dist/types/toolbar/ToolbarButton.d.ts View File

1
 import { ToolbarItem } from './ToolbarItem';
1
 import { ToolbarItem } from './ToolbarItem';
2
+import { Drawboard } from '../drawboard/Drawboard';
2
 export declare class ToolbarButton {
3
 export declare class ToolbarButton {
3
-    private toolbarItem;
4
-    private clickHandler;
4
+    id: string;
5
+    drawboard: Drawboard;
6
+    toolbarItem: ToolbarItem;
7
+    container: HTMLDivElement;
8
+    clickHandler: (ev: MouseEvent, toolbarItem: ToolbarItem) => void;
5
     constructor(toolbarItem: ToolbarItem, clickHandler?: (ev: MouseEvent, toolbarItem: ToolbarItem) => void);
9
     constructor(toolbarItem: ToolbarItem, clickHandler?: (ev: MouseEvent, toolbarItem: ToolbarItem) => void);
6
     getElement: () => HTMLElement;
10
     getElement: () => HTMLElement;
7
 }
11
 }

+ 6
- 7
dist/types/toolbar/ToolbarItem.d.ts View File

1
 import { BaseMarker } from './../markers/BaseMarker/index';
1
 import { BaseMarker } from './../markers/BaseMarker/index';
2
 export declare class ToolbarItem {
2
 export declare class ToolbarItem {
3
     name: string;
3
     name: string;
4
-    tooltipText: string;
4
+    tooltipText?: string;
5
+    shortcut?: string;
5
     icon?: string;
6
     icon?: string;
6
     markerType?: typeof BaseMarker;
7
     markerType?: typeof BaseMarker;
7
-    constructor({ name, tooltipText, icon, markerType }: {
8
-        name: string;
9
-        tooltipText: string;
10
-        icon?: string;
11
-        markerType?: typeof BaseMarker;
12
-    });
8
+    onRender?: () => HTMLDivElement;
9
+    onClick?: () => void;
10
+    draggable?: boolean;
11
+    constructor({ name, tooltipText, shortcut, icon, draggable, markerType, onRender, onClick }: Partial<ToolbarItem>);
13
 }
12
 }

+ 4
- 1
dist/types/toolbar/toolbar-items.d.ts View File

1
-import { WhitePage } from './../board/WhitePage/index';
1
+import { WhitePage } from '../whiteboard/WhitePage/index';
2
 import { ToolbarItem } from './ToolbarItem';
2
 import { ToolbarItem } from './ToolbarItem';
3
+export declare const dragToolbarItem: ToolbarItem;
3
 export declare const highlightMarkerToolbarItem: ToolbarItem;
4
 export declare const highlightMarkerToolbarItem: ToolbarItem;
4
 export declare const arrowMarkerToolbarItem: ToolbarItem;
5
 export declare const arrowMarkerToolbarItem: ToolbarItem;
5
 export declare const textMarkerToolbarItem: ToolbarItem;
6
 export declare const textMarkerToolbarItem: ToolbarItem;
6
 export declare const coverMarkerToolbarItem: ToolbarItem;
7
 export declare const coverMarkerToolbarItem: ToolbarItem;
7
 export declare const rectMarkerToolbarItem: ToolbarItem;
8
 export declare const rectMarkerToolbarItem: ToolbarItem;
8
 export declare const lineMarkerToolbarItem: ToolbarItem;
9
 export declare const lineMarkerToolbarItem: ToolbarItem;
10
+export declare const closeToolbarItem: ToolbarItem;
11
+export declare const separatorToolbarItem: ToolbarItem;
9
 export declare function getToolbars(page?: WhitePage): (ToolbarItem | {
12
 export declare function getToolbars(page?: WhitePage): (ToolbarItem | {
10
     icon: any;
13
     icon: any;
11
     name: string;
14
     name: string;

+ 5
- 0
dist/types/utils/layout.d.ts View File

1
+export declare type PositionType = 'left' | 'right' | 'topLeft' | 'bottomLeft' | 'topRight' | 'bottomRight' | 'centerLeft' | 'centerRight' | 'topCenter' | 'bottomCenter';
2
+export declare function rectContains(rect: ClientRect, { x, y }: {
3
+    x: number;
4
+    y: number;
5
+}): boolean;

+ 6
- 0
dist/types/utils/types.d.ts View File

1
+export declare type Mode = 'master' | 'mirror' | 'replay';
2
+export declare type Source = {
3
+    imgEle?: HTMLImageElement;
4
+    imgSrc?: string;
5
+};
6
+export declare function isNil(mayBeNil: any): boolean;

+ 42
- 0
dist/types/whiteboard/AbstractWhiteboard/index.d.ts View File

1
+import { Mode } from './../../utils/types';
2
+import { SyncEvent } from '../../event/SyncEvent';
3
+import { WhitePage } from '../WhitePage/index';
4
+import { EventHub } from '../../event/EventHub';
5
+import './index.less';
6
+import { WhiteboardSnap } from '../AbstractWhiteboard/snap';
7
+export declare abstract class AbstractWhiteboard {
8
+    id: string;
9
+    sources: string[];
10
+    target: HTMLDivElement;
11
+    imgEles: HTMLDivElement[];
12
+    imgsContainer: HTMLDivElement;
13
+    pagesContainer: HTMLDivElement;
14
+    allowRollback: boolean;
15
+    onlyEmitSnap: boolean;
16
+    snapInterval: number;
17
+    eventHub?: EventHub;
18
+    mode: Mode;
19
+    isFullscreen: boolean;
20
+    pages: WhitePage[];
21
+    readonly activePage: WhitePage;
22
+    readonly pageMap: Record<string, WhitePage>;
23
+    siema: any;
24
+    snapHistory: WhiteboardSnap[];
25
+    isInitialized: boolean;
26
+    isSyncing: boolean;
27
+    visiblePageIndex: number;
28
+    emitInterval: any;
29
+    constructor(target: HTMLDivElement, { sources, eventHub, visiblePageIndex, allowRollback, onlyEmitSnap }?: Partial<AbstractWhiteboard>);
30
+    open(): void;
31
+    close(): void;
32
+    show(): void;
33
+    hide(): void;
34
+    emit(borderEvent: SyncEvent): void;
35
+    captureSnap(shadow?: boolean): WhiteboardSnap;
36
+    rollbackSnap(): void;
37
+    destroy(): void;
38
+    protected abstract init(): void;
39
+    protected initSiema(): void;
40
+    protected abstract onPageChange(nextPageIndex: number): void;
41
+    protected applySnap(snap: WhiteboardSnap): void;
42
+}

+ 32
- 0
dist/types/whiteboard/AbstractWhiteboard/snap.d.ts View File

1
+import { MarkerType } from '../../markers/types';
2
+export declare class WhiteboardSnap {
3
+    id: string;
4
+    sources: string[];
5
+    pageIds: string[];
6
+    visiblePageIndex: number;
7
+    pages?: WhitepageSnap[];
8
+}
9
+export declare class WhitepageSnap {
10
+    id: string;
11
+    markers: MarkerSnap[];
12
+}
13
+export declare class MarkerSnap {
14
+    id: string;
15
+    type: MarkerType;
16
+    isActive: boolean;
17
+    x: number;
18
+    y: number;
19
+    linearSnap?: {
20
+        x1: number;
21
+        y1: number;
22
+        x2: number;
23
+        y2: number;
24
+    };
25
+    rectSnap?: {
26
+        width: number;
27
+        height: number;
28
+    };
29
+    textSnap?: {
30
+        text: string;
31
+    };
32
+}

+ 8
- 0
dist/types/whiteboard/MirrorWhiteboard/index.d.ts View File

1
+import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
2
+import { Mode } from '../../utils/types';
3
+export declare class MirrorWhiteboard extends AbstractWhiteboard {
4
+    mode: Mode;
5
+    protected init(): void;
6
+    destroy(): void;
7
+    onPageChange(nextPageIndex: number): void;
8
+}

+ 20
- 0
dist/types/whiteboard/ReplayWhiteboard/index.d.ts View File

1
+import { MirrorWhiteboard } from '../MirrorWhiteboard';
2
+import { SyncEvent } from '../../event/SyncEvent';
3
+export declare type onLoadFunc = (startTime: number, endTime: number) => Promise<SyncEvent[]>;
4
+export declare class ReplayWhiteboard extends MirrorWhiteboard {
5
+    leftEvents: SyncEvent[];
6
+    recordStartTime: number;
7
+    currentRelativeTime: number;
8
+    loadedRelativeTime: number;
9
+    interval: any;
10
+    loadingLock: boolean;
11
+    seekingLock: boolean;
12
+    onLoad: onLoadFunc;
13
+    setContext(recordStartTime: number, onLoad: onLoadFunc): void;
14
+    setCurrentRelativeTime(time: number): void;
15
+    close(): void;
16
+    protected init(): void;
17
+    private loadEvents;
18
+    private seek;
19
+    private perform;
20
+}

+ 30
- 0
dist/types/whiteboard/WhitePage/index.d.ts View File

1
+import { Source, Mode } from './../../utils/types';
2
+import { Drawboard } from './../../drawboard/Drawboard/index';
3
+import { WhitepageSnap } from '../AbstractWhiteboard/snap';
4
+import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
5
+import './index.less';
6
+import { ToolbarItem } from '../../toolbar/ToolbarItem';
7
+export declare class WhitePage {
8
+    id: string;
9
+    source: Source;
10
+    target: HTMLImageElement;
11
+    container: HTMLDivElement;
12
+    parentContainer?: HTMLDivElement;
13
+    mode: Mode;
14
+    drawboard: Drawboard;
15
+    whiteboard?: AbstractWhiteboard;
16
+    constructor(source: Source, { mode, whiteboard, parentContainer, extraToolbarItems }?: Partial<WhitePage> & {
17
+        extraToolbarItems?: ToolbarItem[];
18
+    });
19
+    open(): void;
20
+    hide(): void;
21
+    show(): void;
22
+    destroy(): void;
23
+    captureSnap(): WhitepageSnap;
24
+    applySnap(snap: WhitepageSnap): void;
25
+    private initSource;
26
+    protected initMaster(extraToolbarItems?: ToolbarItem[]): void;
27
+    protected initMirror(): void;
28
+    private onPageSync;
29
+    private onMarkerSync;
30
+}

+ 10
- 0
dist/types/whiteboard/Whiteboard/index.d.ts View File

1
+import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
2
+import { Mode } from '../../utils/types';
3
+export declare class Whiteboard extends AbstractWhiteboard {
4
+    mode: Mode;
5
+    destroy(): void;
6
+    protected init(): void;
7
+    private initMaster;
8
+    onPageChange(nextPageIndex: number): void;
9
+    private emitSnapshot;
10
+}

+ 0
- 0
example/drawboard-fullscreen/index.ts View File


+ 0
- 0
example/drawboard/index.ts View File


+ 0
- 27
example/index.ts View File

1
-import { EventHub } from './../src/event/EventHub';
2
-import { Whiteboard } from './../src/board/Whiteboard/index';
3
-
4
-const eventHub = new EventHub();
5
-
6
-eventHub.on('sync', (changeEv: SyncEvent) => {});
7
-
8
-const images = [
9
-  'https://upload-images.jianshu.io/upload_images/1647496-6bede989c09af527.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
10
-  'http://upload-images.jianshu.io/upload_images/1647496-d281090a702045e5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
11
-  'http://upload-images.jianshu.io/upload_images/1647496-611a416be07d7ca3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'
12
-];
13
-
14
-const whiteboard = new Whiteboard(document.getElementById('root') as HTMLDivElement, {
15
-  sources: images,
16
-  eventHub
17
-});
18
-
19
-whiteboard.open();
20
-
21
-const mirrorWhiteboard = new Whiteboard(document.getElementById('root-mirror') as HTMLDivElement, {
22
-  sources: images,
23
-  eventHub,
24
-  mode: 'mirror'
25
-});
26
-
27
-mirrorWhiteboard.open();

+ 0
- 0
example/mirror-whiteboard/index.ts View File


+ 0
- 0
example/mirror/index.less View File


+ 0
- 32
example/mirror/index.ts View File

1
-import { EventHub } from './../../src/event/EventHub';
2
-import { WhitePage } from '../../src/board/WhitePage/index';
3
-import { SyncEvent } from '../../src/event/Event';
4
-
5
-const eventHub = new EventHub();
6
-
7
-eventHub.on('sync', (changeEv: SyncEvent) => {
8
-  console.log(changeEv);
9
-});
10
-
11
-const page1 = new WhitePage(
12
-  { imgEle: document.getElementById('image1') as HTMLImageElement },
13
-  { eventHub }
14
-);
15
-
16
-page1.drawboard.open((dataUrl: string) => {
17
-  const res = document.getElementById('resultImage') as HTMLImageElement;
18
-  res.src = dataUrl;
19
-});
20
-
21
-const page2 = new WhitePage(
22
-  { imgEle: document.getElementById('image2') as HTMLImageElement },
23
-  {
24
-    mode: 'mirror',
25
-    eventHub
26
-  }
27
-);
28
-
29
-page2.drawboard.open((dataUrl: string) => {
30
-  const res = document.getElementById('resultImage') as HTMLImageElement;
31
-  res.src = dataUrl;
32
-});

+ 0
- 13
example/whiteboard/index.ts View File

1
-import { Whiteboard } from '../../src/board/Whiteboard/index';
2
-
3
-const images = [
4
-  'https://upload-images.jianshu.io/upload_images/1647496-6bede989c09af527.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
5
-  'http://upload-images.jianshu.io/upload_images/1647496-d281090a702045e5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
6
-  'http://upload-images.jianshu.io/upload_images/1647496-611a416be07d7ca3.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'
7
-];
8
-
9
-const whiteboard = new Whiteboard(document.getElementById('root') as HTMLDivElement, {
10
-  sources: images
11
-});
12
-
13
-whiteboard.open();

+ 4
- 0
package.json View File

29
   },
29
   },
30
   "dependencies": {
30
   "dependencies": {
31
     "eventemitter3": "^3.1.0",
31
     "eventemitter3": "^3.1.0",
32
+    "fc-hotkeys": "^0.0.1-alpha.1",
33
+    "interactjs": "^1.4.9",
34
+    "lodash.debounce": "^4.0.8",
32
     "prop-types": "^15.6.2",
35
     "prop-types": "^15.6.2",
33
     "react": "^16.8.0",
36
     "react": "^16.8.0",
34
     "react-dom": "^16.8.0",
37
     "react-dom": "^16.8.0",
35
     "siema": "^1.5.1",
38
     "siema": "^1.5.1",
39
+    "tippy.js": "^4.3.4",
36
     "uuid": "^3.3.2"
40
     "uuid": "^3.3.2"
37
   },
41
   },
38
   "devDependencies": {
42
   "devDependencies": {

+ 27
- 0
src/assets/finish.svg View File

1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<svg width="20px" height="20px" style="height:20px;" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+    <!-- Generator: Sketch 52.3 (67297) - http://www.bohemiancoding.com/sketch -->
4
+    <title>teacher_ppt_bar_btn_finish</title>
5
+    <desc>Created with Sketch.</desc>
6
+    <g id="Demo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" fill-opacity="0.776211504">
7
+        <g id="教师端_白板" transform="translate(-957.000000, -578.000000)" fill="#FF3366">
8
+            <g id="分组-6" transform="translate(484.000000, 569.000000)">
9
+                <g id="Group-29">
10
+                    <g id="teacher_ppt_bar_bj">
11
+                        <g id="分组-10" transform="translate(382.000000, 9.000000)">
12
+                            <g id="分组-5">
13
+                                <g id="teacher_ppt_bar_btn_finish" transform="translate(91.000000, 0.000000)">
14
+                                    <g id="icon/ppt/结束">
15
+                                        <g id="结束" transform="translate(3.000000, 3.000000)">
16
+                                            <path d="M6.13493151,13 C5.30684932,13 4.50547945,12.839726 3.77534247,12.5191781 C3.03630137,12.1986301 2.38630137,11.7534247 1.83424658,11.210274 C1.28219178,10.6671233 0.845890411,10.0082192 0.525342466,9.27808219 C0.204794521,8.5390411 0.0445205479,7.73767123 0.0445205479,6.90068493 C0.0445205479,6.41986301 0.0979452055,5.94794521 0.21369863,5.48493151 C0.329452055,5.02191781 0.489726027,4.57671233 0.694520548,4.15821918 C0.899315068,3.73972603 1.16643836,3.34794521 1.46917808,2.99178082 C1.78082192,2.62671233 2.12808219,2.29726027 2.5109589,2.00342466 C2.64452055,1.90547945 2.77808219,1.8609589 2.92945205,1.8609589 C2.96506849,1.8609589 3.00068493,1.8609589 3.04520548,1.86986301 C3.24109589,1.89657534 3.39246575,1.99452055 3.51712329,2.15479452 C3.64178082,2.31506849 3.67739726,2.48424658 3.65068493,2.68013699 C3.6239726,2.8760274 3.5260274,3.03630137 3.36575342,3.15205479 C2.76027397,3.58835616 2.27945205,4.14041096 1.95890411,4.79041096 C1.63835616,5.44041096 1.46917808,6.14383562 1.46917808,6.89178082 C1.46917808,7.53287671 1.59383562,8.13835616 1.83424658,8.70821918 C2.07465753,9.27808219 2.4130137,9.77671233 2.83150685,10.1952055 C3.25,10.6136986 3.74863014,10.9520548 4.31849315,11.2013699 C4.88835616,11.4506849 5.49383562,11.5753425 6.13493151,11.5753425 C6.7760274,11.5753425 7.39041096,11.4506849 7.95136986,11.2013699 C8.51232877,10.9520548 9.01986301,10.6136986 9.43835616,10.1952055 C9.85684932,9.77671233 10.1952055,9.27808219 10.4445205,8.70821918 C10.6938356,8.13835616 10.8184932,7.53287671 10.8184932,6.89178082 C10.8184932,6.13493151 10.640411,5.41369863 10.2931507,4.7369863 C9.94589041,4.06027397 9.44726027,3.49931507 8.81506849,3.0630137 C8.64589041,2.94726027 8.54794521,2.79589041 8.52123288,2.6 C8.48561644,2.40410959 8.53013699,2.2260274 8.6369863,2.05684932 C8.74383562,1.90547945 8.89520548,1.80753425 9.09109589,1.77191781 C9.13561644,1.7630137 9.18013699,1.7630137 9.22465753,1.7630137 C9.36712329,1.7630137 9.50068493,1.80753425 9.63424658,1.89657534 C10.0349315,2.18150685 10.4089041,2.51986301 10.7205479,2.88493151 C11.0410959,3.25 11.3171233,3.65068493 11.539726,4.07808219 C11.7623288,4.50547945 11.940411,4.95958904 12.0561644,5.43150685 C12.1719178,5.90342466 12.2342466,6.39315068 12.2342466,6.88287671 C12.2342466,7.71986301 12.0739726,8.52123288 11.7534247,9.26027397 C11.4328767,9.99931507 10.9876712,10.6493151 10.4445205,11.2013699 C9.90136986,11.7445205 9.24246575,12.189726 8.50342466,12.510274 C7.78219178,12.839726 6.98082192,13 6.13493151,13 Z M6.13493151,6.75821918 C5.9390411,6.75821918 5.77876712,6.6869863 5.63630137,6.55342466 C5.50273973,6.4109589 5.43150685,6.25068493 5.43150685,6.05479452 L5.43150685,0.721232877 C5.43150685,0.525342466 5.50273973,0.356164384 5.63630137,0.21369863 C5.77876712,0.0712328767 5.9390411,0 6.13493151,0 C6.33972603,0 6.50890411,0.0712328767 6.64246575,0.21369863 C6.78493151,0.356164384 6.84726027,0.525342466 6.84726027,0.721232877 L6.84726027,6.05479452 C6.84726027,6.25068493 6.7760274,6.4109589 6.64246575,6.55342466 C6.50890411,6.6869863 6.33972603,6.75821918 6.13493151,6.75821918 Z" id="Shape" fill-rule="nonzero"></path>
17
+                                        </g>
18
+                                    </g>
19
+                                </g>
20
+                            </g>
21
+                        </g>
22
+                    </g>
23
+                </g>
24
+            </g>
25
+        </g>
26
+    </g>
27
+</svg>

+ 1
- 0
src/assets/rollback-disable.svg View File

1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1560078592996" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2653" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M811.488 424.512Q722.976 336 597.984 336h-336l114.016-114.016q12-12 12-28.512t-12-28-28.512-11.488-28.512 12l-183.008 183.008q-12 12-12 28.512t12 28.512l178.016 178.016q12 12 28.512 12t28-11.488 11.488-28-11.008-28.512l-112.992-112h340q92 0 156.992 64.992t64.992 156.992v192q0 16.992 12 28.512t28.512 11.488 28-11.488 11.488-28.512v-192q0-124.992-88.512-213.504z" p-id="2654" fill="#cdcdcd"></path></svg>

+ 1
- 0
src/assets/rollback.svg View File

1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1560078592996" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2653" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M811.488 424.512Q722.976 336 597.984 336h-336l114.016-114.016q12-12 12-28.512t-12-28-28.512-11.488-28.512 12l-183.008 183.008q-12 12-12 28.512t12 28.512l178.016 178.016q12 12 28.512 12t28-11.488 11.488-28-11.008-28.512l-112.992-112h340q92 0 156.992 64.992t64.992 156.992v192q0 16.992 12 28.512t28.512 11.488 28-11.488 11.488-28.512v-192q0-124.992-88.512-213.504z" p-id="2654" fill="#2c2c2c"></path></svg>

+ 6
- 3
src/drawboard/Baseboard/index.ts View File

37
     // 如果仅传入图片地址或者 Blob,则必须为全屏模式
37
     // 如果仅传入图片地址或者 Blob,则必须为全屏模式
38
   }
38
   }
39
 
39
 
40
-  protected initBoard = () => {
40
+  protected initBoard = (mountContainer: HTMLElement) => {
41
     // init holder
41
     // init holder
42
     this.boardHolder = document.createElement('div');
42
     this.boardHolder = document.createElement('div');
43
     this.boardHolder.id = `fcw-board-holder-${this.id}`;
43
     this.boardHolder.id = `fcw-board-holder-${this.id}`;
44
+    this.boardHolder.className = `fcw-board-holder`;
45
+    this.boardHolder.style.zIndex = '999';
44
     // fix for Edge's touch behavior
46
     // fix for Edge's touch behavior
45
     this.boardHolder.style.setProperty('touch-action', 'none');
47
     this.boardHolder.style.setProperty('touch-action', 'none');
46
     this.boardHolder.style.setProperty('-ms-touch-action', 'none');
48
     this.boardHolder.style.setProperty('-ms-touch-action', 'none');
47
-    document.body.appendChild(this.boardHolder);
49
+
50
+    mountContainer.appendChild(this.boardHolder);
48
 
51
 
49
     // init canvas
52
     // init canvas
50
     this.boardCanvas = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
53
     this.boardCanvas = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
56
       '0 0 ' + this.width.toString() + ' ' + this.height.toString()
59
       '0 0 ' + this.width.toString() + ' ' + this.height.toString()
57
     );
60
     );
58
 
61
 
59
-    this.boardHolder.style.position = 'absolute';
62
+    this.boardHolder.style.position = 'fixed';
60
     this.boardHolder.style.width = `${this.width}px`;
63
     this.boardHolder.style.width = `${this.width}px`;
61
     this.boardHolder.style.height = `${this.height}px`;
64
     this.boardHolder.style.height = `${this.height}px`;
62
     this.boardHolder.style.transformOrigin = 'top left';
65
     this.boardHolder.style.transformOrigin = 'top left';

+ 153
- 29
src/drawboard/Drawboard/index.ts View File

1
+import { HotkeysListener, KEY_ALL } from 'fc-hotkeys';
2
+import * as debounce from 'lodash.debounce';
3
+
1
 import { Source } from './../../utils/types';
4
 import { Source } from './../../utils/types';
2
 import { Baseboard } from './../Baseboard/index';
5
 import { Baseboard } from './../Baseboard/index';
3
 import { BaseMarker } from './../../markers/BaseMarker/index';
6
 import { BaseMarker } from './../../markers/BaseMarker/index';
10
 import { ToolbarItem } from '../../toolbar/ToolbarItem';
13
 import { ToolbarItem } from '../../toolbar/ToolbarItem';
11
 
14
 
12
 import './index.less';
15
 import './index.less';
16
+import { rectContains } from '../../utils/layout';
17
+import { RectMarker } from '../../markers/RectMarker/index';
18
+import { HighlightMarker } from '../../markers/HighlightMarker/index';
19
+import { CoverMarker } from '../../markers/CoverMarker/index';
20
+import { LineMarker } from '../../markers/LineMarker/index';
21
+import { ArrowMarker } from '../../markers/ArrowMarker/index';
22
+import { TextMarker } from '../../markers/TextMarker/index';
13
 
23
 
14
 export class Drawboard extends Baseboard {
24
 export class Drawboard extends Baseboard {
15
   /** Options */
25
   /** Options */
26
+  mountContainer = document.body;
16
   scale = 1.0;
27
   scale = 1.0;
17
   zIndex: number = 999;
28
   zIndex: number = 999;
29
+  allowKeyboard? = true;
18
 
30
 
19
   /** 句柄 */
31
   /** 句柄 */
20
   page: WhitePage;
32
   page: WhitePage;
33
+  listener: HotkeysListener;
21
 
34
 
22
   markers: BaseMarker[];
35
   markers: BaseMarker[];
23
   get markerMap(): { [key: string]: BaseMarker } {
36
   get markerMap(): { [key: string]: BaseMarker } {
42
   constructor(
55
   constructor(
43
     source: Source,
56
     source: Source,
44
     {
57
     {
58
+      allowKeyboard = true,
59
+      extraToolbarItems,
60
+      mountContainer,
45
       page,
61
       page,
46
       zIndex,
62
       zIndex,
47
-      extraToolbarItems,
48
       onChange
63
       onChange
49
     }: Partial<Drawboard> & { extraToolbarItems?: ToolbarItem[] } = {}
64
     }: Partial<Drawboard> & { extraToolbarItems?: ToolbarItem[] } = {}
50
   ) {
65
   ) {
58
       this.zIndex = zIndex;
73
       this.zIndex = zIndex;
59
     }
74
     }
60
 
75
 
76
+    this.allowKeyboard = allowKeyboard;
77
+
61
     this.markers = [];
78
     this.markers = [];
62
     this.activeMarker = null;
79
     this.activeMarker = null;
63
 
80
 
72
     if (onChange) {
89
     if (onChange) {
73
       this.onChange = onChange;
90
       this.onChange = onChange;
74
     }
91
     }
92
+
93
+    if (allowKeyboard && this.page && this.page.mode === 'master') {
94
+      this.listener = new HotkeysListener();
95
+      this.listener.on(KEY_ALL, debounce(this.onKeyboard, 150));
96
+    }
97
+
98
+    if (mountContainer) {
99
+      this.mountContainer = mountContainer;
100
+    }
75
   }
101
   }
76
 
102
 
77
   /** @region LifeCycle open - hide - show - ... - close */
103
   /** @region LifeCycle open - hide - show - ... - close */
87
 
113
 
88
     this.setTargetRect();
114
     this.setTargetRect();
89
 
115
 
90
-    this.initBoard();
116
+    this.initBoard(this.mountContainer);
91
     this.attachEvents();
117
     this.attachEvents();
92
     this.setStyles();
118
     this.setStyles();
93
 
119
 
124
     }
150
     }
125
   };
151
   };
126
 
152
 
127
-  public close = () => {
153
+  public destroy = () => {
128
     if (this.toolbarUI) {
154
     if (this.toolbarUI) {
129
-      document.body.removeChild(this.toolbarUI);
155
+      this.mountContainer.removeChild(this.toolbarUI);
130
     }
156
     }
157
+
131
     if (this.boardCanvas) {
158
     if (this.boardCanvas) {
132
-      document.body.removeChild(this.boardHolder);
159
+      this.mountContainer.removeChild(this.boardHolder);
160
+    }
161
+
162
+    if (this.listener) {
163
+      this.listener.reset();
133
     }
164
     }
134
   };
165
   };
135
 
166
 
145
   };
176
   };
146
 
177
 
147
   /** 添加某个 Marker */
178
   /** 添加某个 Marker */
148
-  public addMarker = (markerType: typeof BaseMarker, { id }: { id?: string } = {}) => {
179
+  public addMarker = (
180
+    markerType: typeof BaseMarker,
181
+    { id, originX, originY }: { id?: string; originX?: number; originY?: number } = {}
182
+  ) => {
149
     // 假如 Drawboard 存在 Page 引用,则传导给 Marker
183
     // 假如 Drawboard 存在 Page 引用,则传导给 Marker
150
     const marker = markerType.createMarker(this.page);
184
     const marker = markerType.createMarker(this.page);
151
 
185
 
165
       }
199
       }
166
     }
200
     }
167
 
201
 
202
+    this.markers.push(marker);
203
+    this.selectMarker(marker);
204
+    this.boardCanvas.appendChild(marker.visual);
205
+
206
+    let x;
207
+    let y;
208
+
209
+    if (originX && originY) {
210
+      x = originX;
211
+      y = originY;
212
+    } else {
213
+      // 默认居中
214
+      const bbox = marker.visual.getBBox();
215
+      x = this.width / 2 / this.scale - bbox.width / 2;
216
+      y = this.height / 2 / this.scale - bbox.height / 2;
217
+    }
218
+
168
     // 触发事件流
219
     // 触发事件流
169
     this.onChange({
220
     this.onChange({
170
       target: 'marker',
221
       target: 'marker',
171
       parentId: this.page ? this.page.id : this.id,
222
       parentId: this.page ? this.page.id : this.id,
172
       event: 'addMarker',
223
       event: 'addMarker',
173
-      marker: { type: marker.type, id: marker.id }
224
+      marker: { type: marker.type, id: marker.id, dx: x, dy: y }
174
     });
225
     });
175
 
226
 
176
-    this.markers.push(marker);
177
-    this.selectMarker(marker);
178
-    this.boardCanvas.appendChild(marker.visual);
179
-
180
-    // 默认居中
181
-    const bbox = marker.visual.getBBox();
182
-    const x = this.width / 2 / this.scale - bbox.width / 2;
183
-    const y = this.height / 2 / this.scale - bbox.height / 2;
184
-
185
     marker.moveTo(x, y);
227
     marker.moveTo(x, y);
186
 
228
 
187
     return marker;
229
     return marker;
188
   };
230
   };
189
 
231
 
190
   public deleteActiveMarker = () => {
232
   public deleteActiveMarker = () => {
191
-    if (this.activeMarker) {
233
+    this.deleteMarkerWithEvent(this.activeMarker);
234
+  };
235
+
236
+  public clearMarkers = () => {
237
+    [...this.markers].forEach(marker => {
238
+      this.deleteMarkerWithEvent(marker);
239
+    });
240
+  };
241
+
242
+  public deleteMarkerWithEvent = (marker: BaseMarker | null) => {
243
+    if (marker) {
192
       // 触发事件
244
       // 触发事件
193
       if (this.onChange) {
245
       if (this.onChange) {
194
         this.onChange({
246
         this.onChange({
195
           event: 'removeMarker',
247
           event: 'removeMarker',
196
-          id: this.activeMarker.id,
248
+          id: marker.id,
197
           target: 'marker',
249
           target: 'marker',
198
-          marker: { id: this.activeMarker.id }
250
+          marker: { id: marker.id }
199
         });
251
         });
200
       }
252
       }
201
-      this.deleteMarker(this.activeMarker);
253
+      this.deleteMarker(marker);
202
     }
254
     }
203
   };
255
   };
204
 
256
 
205
   private setTargetRect = () => {
257
   private setTargetRect = () => {
206
     const targetRect = this.target.getBoundingClientRect() as DOMRect;
258
     const targetRect = this.target.getBoundingClientRect() as DOMRect;
207
     const bodyRect = document.body.parentElement!.getBoundingClientRect();
259
     const bodyRect = document.body.parentElement!.getBoundingClientRect();
260
+
208
     this.targetRect = {
261
     this.targetRect = {
209
       left: targetRect.left - bodyRect.left,
262
       left: targetRect.left - bodyRect.left,
210
       top: targetRect.top - bodyRect.top
263
       top: targetRect.top - bodyRect.top
243
     }
296
     }
244
   };
297
   };
245
 
298
 
299
+  private onKeyboard = (e: any, { hotkey }: { hotkey: string }) => {
300
+    switch (hotkey) {
301
+      case 'Shift+R':
302
+        this.addMarker(RectMarker);
303
+        return;
304
+      case 'Shift+H':
305
+        this.addMarker(HighlightMarker);
306
+        return;
307
+      case 'Shift+C':
308
+        this.addMarker(CoverMarker);
309
+        return;
310
+      case 'Shift+L':
311
+        this.addMarker(LineMarker);
312
+        return;
313
+      case 'Shift+A':
314
+        this.addMarker(ArrowMarker);
315
+        return;
316
+      case 'Shift+T':
317
+        this.addMarker(TextMarker);
318
+        return;
319
+      case 'ESC':
320
+        this.page.whiteboard!.rollbackSnap();
321
+        return;
322
+      default:
323
+        break;
324
+    }
325
+    if (!this.activeMarker) {
326
+      return;
327
+    }
328
+
329
+    switch (hotkey) {
330
+      case 'UP':
331
+        this.activeMarker.move(0, -10);
332
+        return;
333
+      case 'LEFT':
334
+        this.activeMarker.move(-10, 0);
335
+        return;
336
+      case 'RIGHT':
337
+        this.activeMarker.move(10, 0);
338
+        return;
339
+      case 'DOWN':
340
+        this.activeMarker.move(0, 10);
341
+        return;
342
+      case 'BACKSPACE':
343
+        this.deleteActiveMarker();
344
+        return;
345
+      default:
346
+        return;
347
+    }
348
+  };
349
+
246
   private adjustUI = (ev: UIEvent) => {
350
   private adjustUI = (ev: UIEvent) => {
247
     this.adjustSize();
351
     this.adjustSize();
248
     this.positionUI();
352
     this.positionUI();
269
   };
373
   };
270
 
374
 
271
   private positionToolbar = () => {
375
   private positionToolbar = () => {
272
-    this.toolbarUI.style.left = `${this.targetRect.left +
273
-      this.target.offsetWidth -
274
-      this.toolbarUI.clientWidth}px`;
275
-    this.toolbarUI.style.top = `${this.targetRect.top - this.toolbarUI.clientHeight}px`;
376
+    if (this.toolbarUI && this.targetRect) {
377
+      this.toolbarUI.style.left = `${this.targetRect.left +
378
+        this.target.offsetWidth -
379
+        this.toolbarUI.clientWidth}px`;
380
+      this.toolbarUI.style.top = `${this.targetRect.top - this.toolbarUI.clientHeight}px`;
381
+    }
276
   };
382
   };
277
 
383
 
278
   private showUI = () => {
384
   private showUI = () => {
279
     this.toolbar = new Toolbar(this.toolbarItems, this.toolbarClick);
385
     this.toolbar = new Toolbar(this.toolbarItems, this.toolbarClick);
280
-    this.toolbar.zIndex = this.zIndex;
386
+    this.toolbar.zIndex = this.zIndex + 1;
281
 
387
 
282
     this.toolbarUI = this.toolbar.getUI(this);
388
     this.toolbarUI = this.toolbar.getUI(this);
283
 
389
 
284
-    document.body.appendChild(this.toolbarUI);
390
+    this.boardHolder.appendChild(this.toolbarUI);
285
     this.toolbarUI.style.position = 'absolute';
391
     this.toolbarUI.style.position = 'absolute';
286
 
392
 
287
     this.positionToolbar();
393
     this.positionToolbar();
394
+    this.toolbar.show();
288
 
395
 
289
     // 处理元素的拖拽事件
396
     // 处理元素的拖拽事件
290
     this.toolbar.toolbarButtons.forEach(button => {
397
     this.toolbar.toolbarButtons.forEach(button => {
301
     this.boardCanvas.ondragover = ev => {
408
     this.boardCanvas.ondragover = ev => {
302
       ev.preventDefault();
409
       ev.preventDefault();
303
     };
410
     };
411
+
304
     this.boardCanvas.ondrop = ev => {
412
     this.boardCanvas.ondrop = ev => {
305
-      console.log(ev);
413
+      const markerX = ev.x;
414
+      const markerY = ev.y;
415
+
416
+      const rect = this.boardHolder.getBoundingClientRect();
417
+
418
+      if (rectContains(rect, { x: markerX, y: markerY })) {
419
+        const buttonId = ev.dataTransfer!.getData('id');
420
+
421
+        const button = this.toolbar.toolbarButtonMap[buttonId];
422
+
423
+        if (button.toolbarItem && button.toolbarItem.markerType) {
424
+          this.addMarker(button.toolbarItem.markerType, {
425
+            originX: markerX - rect.left,
426
+            originY: markerY - rect.top
427
+          });
428
+        }
429
+      }
306
     };
430
     };
307
   };
431
   };
308
 
432
 
415
   };
539
   };
416
 
540
 
417
   private cancel = () => {
541
   private cancel = () => {
418
-    this.close();
542
+    this.destroy();
419
     if (this.onCancel) {
543
     if (this.onCancel) {
420
       this.onCancel();
544
       this.onCancel();
421
     }
545
     }
426
   };
550
   };
427
 
551
 
428
   private renderFinishedClose = (dataUrl: string) => {
552
   private renderFinishedClose = (dataUrl: string) => {
429
-    this.close();
553
+    this.destroy();
430
     this.onComplete(dataUrl);
554
     this.onComplete(dataUrl);
431
   };
555
   };
432
 }
556
 }

+ 3
- 1
src/event/border-events.ts View File

2
   // 完全的状态同步,FCW 支持两种状态的同步交换:Snapshot(Snap) 与 KeyActions(KA) 方式
2
   // 完全的状态同步,FCW 支持两种状态的同步交换:Snapshot(Snap) 与 KeyActions(KA) 方式
3
   | 'borderSnap'
3
   | 'borderSnap'
4
   // 下标改变
4
   // 下标改变
5
-  | 'borderChangePage';
5
+  | 'borderChangePage'
6
+  // 结束
7
+  | 'finish';

+ 8
- 1
src/markers/BaseMarker/index.ts View File

69
 
69
 
70
     // 如果在拖拽
70
     // 如果在拖拽
71
     if (this.isDragging) {
71
     if (this.isDragging) {
72
-      this.onChange({ target: 'marker', id: this.id, event: 'moveMarker', marker: { dx, dy } });
73
       this.move(dx, dy);
72
       this.move(dx, dy);
74
     }
73
     }
75
 
74
 
135
     }
134
     }
136
   }
135
   }
137
 
136
 
137
+  /** 移除该 Marker */
138
+  public destroy() {
139
+    this.visual.style.display = 'none';
140
+  }
141
+
138
   protected resize(x: number, y: number, cb?: Function) {
142
   protected resize(x: number, y: number, cb?: Function) {
139
     return;
143
     return;
140
   }
144
   }
149
 
153
 
150
     this.x += dx;
154
     this.x += dx;
151
     this.y += dy;
155
     this.y += dy;
156
+
157
+    this.onChange({ target: 'marker', id: this.id, event: 'moveMarker', marker: { dx, dy } });
152
   };
158
   };
153
 
159
 
160
+  /** Move to relative position */
154
   public moveTo = (x: number, y: number) => {
161
   public moveTo = (x: number, y: number) => {
155
     const translate = this.visual.transform.baseVal.getItem(0);
162
     const translate = this.visual.transform.baseVal.getItem(0);
156
     translate.setMatrix(translate.matrix.translate(x - this.x, y - this.y));
163
     translate.setMatrix(translate.matrix.translate(x - this.x, y - this.y));

+ 14
- 4
src/toolbar/Toolbar.ts View File

19
   toolbarUI: HTMLElement;
19
   toolbarUI: HTMLElement;
20
   toolbarButtons: ToolbarButton[] = [];
20
   toolbarButtons: ToolbarButton[] = [];
21
 
21
 
22
+  get toolbarButtonMap(): Record<string, ToolbarButton> {
23
+    const buttonMap = {};
24
+
25
+    this.toolbarButtons.forEach(b => {
26
+      buttonMap[b.id] = b;
27
+    });
28
+
29
+    return buttonMap;
30
+  }
31
+
22
   clickHandler: (ev: MouseEvent, toolbarItem: ToolbarItem) => void;
32
   clickHandler: (ev: MouseEvent, toolbarItem: ToolbarItem) => void;
23
 
33
 
24
   constructor(
34
   constructor(
41
       const toolbarButton = new ToolbarButton(toolbarItem, this.clickHandler);
51
       const toolbarButton = new ToolbarButton(toolbarItem, this.clickHandler);
42
       toolbarButton.drawboard = drawboard;
52
       toolbarButton.drawboard = drawboard;
43
       this.toolbarUI.appendChild(toolbarButton.getElement());
53
       this.toolbarUI.appendChild(toolbarButton.getElement());
44
-
45
       this.toolbarButtons.push(toolbarButton);
54
       this.toolbarButtons.push(toolbarButton);
46
     }
55
     }
47
 
56
 
71
   protected onMouseMove = (ev: MouseEvent) => {};
80
   protected onMouseMove = (ev: MouseEvent) => {};
72
 
81
 
73
   protected onDragMove = (event: any) => {
82
   protected onDragMove = (event: any) => {
74
-    var target = this.toolbarUI;
83
+    let target = this.toolbarUI;
75
 
84
 
76
     // keep the dragged position in the data-x/data-y attributes
85
     // keep the dragged position in the data-x/data-y attributes
77
-    var x = ((parseFloat(target.getAttribute('data-x') as string) || 0) + event.dx) as any;
78
-    var y = ((parseFloat(target.getAttribute('data-y') as string) || 0) + event.dy) as any;
86
+    let x = ((parseFloat(target.getAttribute('data-x') as string) || 0) + event.dx) as any;
87
+    let y = ((parseFloat(target.getAttribute('data-y') as string) || 0) + event.dy) as any;
79
 
88
 
80
     // translate the element
89
     // translate the element
81
     target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
90
     target.style.webkitTransform = target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
91
+    target.style.zIndex = `${this.zIndex}`;
82
 
92
 
83
     // update the posiion attributes
93
     // update the posiion attributes
84
     target.setAttribute('data-x', x);
94
     target.setAttribute('data-x', x);

+ 18
- 1
src/toolbar/ToolbarButton.ts View File

1
-import { uuid } from './../utils/uuid';
1
+import tippy from 'tippy.js';
2
+
2
 import { ToolbarItem } from './ToolbarItem';
3
 import { ToolbarItem } from './ToolbarItem';
4
+import { uuid } from '../utils/uuid';
3
 import { Drawboard } from '../drawboard/Drawboard';
5
 import { Drawboard } from '../drawboard/Drawboard';
4
 
6
 
5
 /** 工作栏按钮 */
7
 /** 工作栏按钮 */
23
   }
25
   }
24
 
26
 
25
   public getElement = (): HTMLElement => {
27
   public getElement = (): HTMLElement => {
28
+    if (this.toolbarItem.onRender) {
29
+      this.container = this.toolbarItem.onRender().cloneNode(true) as HTMLDivElement;
30
+      return this.container;
31
+    }
32
+
26
     const div = document.createElement('div');
33
     const div = document.createElement('div');
27
 
34
 
28
     if (this.toolbarItem.name !== 'separator') {
35
     if (this.toolbarItem.name !== 'separator') {
42
       } else {
49
       } else {
43
         div.innerText = this.toolbarItem.tooltipText || '';
50
         div.innerText = this.toolbarItem.tooltipText || '';
44
       }
51
       }
52
+
53
+      if (this.toolbarItem.tooltipText) {
54
+        tippy(div, {
55
+          content: this.toolbarItem.shortcut
56
+            ? `${this.toolbarItem.tooltipText} ${this.toolbarItem.shortcut}`
57
+            : this.toolbarItem.tooltipText
58
+        });
59
+      }
45
     } else {
60
     } else {
46
       div.className = 'fc-whiteboard-toolbar-separator';
61
       div.className = 'fc-whiteboard-toolbar-separator';
47
     }
62
     }
48
 
63
 
64
+    div.id = `fc-whiteboard-toolbar-${this.toolbarItem.name}`;
65
+
49
     this.container = div;
66
     this.container = div;
50
 
67
 
51
     return div;
68
     return div;

+ 17
- 2
src/toolbar/ToolbarItem.ts View File

4
 export class ToolbarItem {
4
 export class ToolbarItem {
5
   name: string;
5
   name: string;
6
   tooltipText?: string;
6
   tooltipText?: string;
7
+  shortcut?: string;
7
   icon?: string;
8
   icon?: string;
8
   markerType?: typeof BaseMarker;
9
   markerType?: typeof BaseMarker;
10
+  onRender?: () => HTMLDivElement;
9
   onClick?: () => void;
11
   onClick?: () => void;
12
+
10
   draggable?: boolean;
13
   draggable?: boolean;
11
 
14
 
12
-  constructor({ name, tooltipText, icon, markerType, onClick, draggable }: Partial<ToolbarItem>) {
15
+  constructor({
16
+    name,
17
+    tooltipText,
18
+    shortcut,
19
+    icon,
20
+    draggable,
21
+    markerType,
22
+    onRender,
23
+    onClick
24
+  }: Partial<ToolbarItem>) {
13
     if (!name) {
25
     if (!name) {
14
       throw new Error('Invalid params');
26
       throw new Error('Invalid params');
15
     }
27
     }
16
 
28
 
17
     this.name = name;
29
     this.name = name;
18
     this.tooltipText = tooltipText;
30
     this.tooltipText = tooltipText;
31
+    this.shortcut = shortcut;
19
     this.icon = icon;
32
     this.icon = icon;
20
     this.markerType = markerType;
33
     this.markerType = markerType;
21
-    this.onClick = onClick;
22
     this.draggable = draggable;
34
     this.draggable = draggable;
35
+
36
+    this.onClick = onClick;
37
+    this.onRender = onRender;
23
   }
38
   }
24
 }
39
 }

+ 11
- 0
src/toolbar/index.less View File

5
   border-radius: 13px;
5
   border-radius: 13px;
6
   opacity: 0.9;
6
   opacity: 0.9;
7
   border: 1px solid rgba(230, 236, 247, 1);
7
   border: 1px solid rgba(230, 236, 247, 1);
8
+  padding: 0 8px;
8
 
9
 
9
   display: flex;
10
   display: flex;
10
   align-items: center;
11
   align-items: center;
47
 .fc-whiteboard-toolbar-button svg {
48
 .fc-whiteboard-toolbar-button svg {
48
   height: 16px;
49
   height: 16px;
49
 }
50
 }
51
+
52
+.fc-whiteboard-indicator-container {
53
+  font-size: 13px;
54
+  line-height: 27px;
55
+  height: 27px;
56
+  width: 40px;
57
+  display: flex;
58
+  justify-content: center;
59
+  letter-spacing: 2;
60
+}

+ 24
- 14
src/toolbar/toolbar-items.ts View File

9
 
9
 
10
 const OkIcon = require('../assets/check.svg');
10
 const OkIcon = require('../assets/check.svg');
11
 const DeleteIcon = require('../assets/eraser.svg');
11
 const DeleteIcon = require('../assets/eraser.svg');
12
-const PointerIcon = require('../assets/mouse-pointer.svg');
13
 const CloseIcon = require('../assets/times.svg');
12
 const CloseIcon = require('../assets/times.svg');
14
 
13
 
15
 export const dragToolbarItem = new ToolbarItem({
14
 export const dragToolbarItem = new ToolbarItem({
20
 
19
 
21
 export const highlightMarkerToolbarItem = new ToolbarItem({
20
 export const highlightMarkerToolbarItem = new ToolbarItem({
22
   name: 'cover-marker',
21
   name: 'cover-marker',
23
-  tooltipText: 'Cover',
22
+  tooltipText: 'Hightlight',
23
+  shortcut: 'Shift+H',
24
   icon: require('../assets/highlight.svg'),
24
   icon: require('../assets/highlight.svg'),
25
-  markerType: HighlightMarker
25
+  markerType: HighlightMarker,
26
+  draggable: true
26
 });
27
 });
27
 
28
 
28
 export const arrowMarkerToolbarItem = new ToolbarItem({
29
 export const arrowMarkerToolbarItem = new ToolbarItem({
29
   name: 'arrow-marker',
30
   name: 'arrow-marker',
30
   tooltipText: 'Arrow',
31
   tooltipText: 'Arrow',
32
+  shortcut: 'Shift+A',
31
   icon: require('../assets/arrow.svg'),
33
   icon: require('../assets/arrow.svg'),
32
-  markerType: ArrowMarker
34
+  markerType: ArrowMarker,
35
+  draggable: true
33
 });
36
 });
34
 
37
 
35
 export const textMarkerToolbarItem = new ToolbarItem({
38
 export const textMarkerToolbarItem = new ToolbarItem({
36
   name: 'text-marker',
39
   name: 'text-marker',
37
   tooltipText: 'Text',
40
   tooltipText: 'Text',
41
+  shortcut: 'Shift+T',
38
   icon: require('../assets/text.svg'),
42
   icon: require('../assets/text.svg'),
39
-  markerType: TextMarker
43
+  markerType: TextMarker,
44
+  draggable: true
40
 });
45
 });
41
 
46
 
42
 export const coverMarkerToolbarItem = new ToolbarItem({
47
 export const coverMarkerToolbarItem = new ToolbarItem({
43
   name: 'cover-marker',
48
   name: 'cover-marker',
44
   tooltipText: 'Cover',
49
   tooltipText: 'Cover',
50
+  shortcut: 'Shift+C',
45
   icon: require('../assets/cover.svg'),
51
   icon: require('../assets/cover.svg'),
46
-  markerType: CoverMarker
52
+  markerType: CoverMarker,
53
+  draggable: true
47
 });
54
 });
48
 
55
 
49
 export const rectMarkerToolbarItem = new ToolbarItem({
56
 export const rectMarkerToolbarItem = new ToolbarItem({
50
   name: 'rect-marker',
57
   name: 'rect-marker',
51
   tooltipText: 'Rectangle',
58
   tooltipText: 'Rectangle',
59
+  shortcut: 'Shift+R',
52
   icon: require('../assets/rect.svg'),
60
   icon: require('../assets/rect.svg'),
53
-  markerType: RectMarker
61
+  markerType: RectMarker,
62
+  draggable: true
54
 });
63
 });
55
 
64
 
56
 export const lineMarkerToolbarItem = new ToolbarItem({
65
 export const lineMarkerToolbarItem = new ToolbarItem({
57
   name: 'line-marker',
66
   name: 'line-marker',
58
   tooltipText: 'Line',
67
   tooltipText: 'Line',
68
+  shortcut: 'Shift+L',
59
   icon: require('../assets/line.svg'),
69
   icon: require('../assets/line.svg'),
60
-  markerType: LineMarker
70
+  markerType: LineMarker,
71
+  draggable: true
61
 });
72
 });
62
 
73
 
63
 export const closeToolbarItem = new ToolbarItem({
74
 export const closeToolbarItem = new ToolbarItem({
70
 
81
 
71
 export function getToolbars(page?: WhitePage) {
82
 export function getToolbars(page?: WhitePage) {
72
   const toolbars = [
83
   const toolbars = [
73
-    {
74
-      icon: PointerIcon,
75
-      name: 'pointer',
76
-      tooltipText: 'Pointer',
77
-      draggable: true
78
-    },
84
+    // {
85
+    //   icon: PointerIcon,
86
+    //   name: 'pointer',
87
+    //   tooltipText: 'Pointer'
88
+    // },
79
     {
89
     {
80
       icon: DeleteIcon,
90
       icon: DeleteIcon,
81
       name: 'delete',
91
       name: 'delete',

+ 2
- 0
src/types.d.ts View File

13
 }
13
 }
14
 
14
 
15
 declare module 'siema';
15
 declare module 'siema';
16
+
17
+declare module 'lodash.debounce';

+ 9
- 0
src/utils/layout.ts View File

9
   | 'centerRight'
9
   | 'centerRight'
10
   | 'topCenter'
10
   | 'topCenter'
11
   | 'bottomCenter';
11
   | 'bottomCenter';
12
+
13
+/** 判断是否在某个包含的区域呢 */
14
+export function rectContains(rect: ClientRect, { x, y }: { x: number; y: number }) {
15
+  if (x < rect.left || x > rect.left + rect.width || y < rect.top || y > rect.top + rect.height) {
16
+    return false;
17
+  }
18
+
19
+  return true;
20
+}

+ 16
- 0
src/whiteboard/AbstractWhiteboard/index.less View File

12
     height: 100%;
12
     height: 100%;
13
   }
13
   }
14
 
14
 
15
+  &-imgs {
16
+    > div,
17
+    > div > div {
18
+      height: 100%;
19
+    }
20
+  }
21
+
15
   &-img {
22
   &-img {
16
     width: 100%;
23
     width: 100%;
17
     height: 100%;
24
     height: 100%;
18
   }
25
   }
19
 
26
 
27
+  &-img-wrapper {
28
+    background-image: url(https://i.postimg.cc/RZwf0MRw/image.png);
29
+    background-size: contain;
30
+    background-position: center;
31
+    height: 100%;
32
+    width: 100%;
33
+    background-repeat: no-repeat;
34
+  }
35
+
20
   &-flip-arrow {
36
   &-flip-arrow {
21
     height: 20px;
37
     height: 20px;
22
     width: 20px;
38
     width: 20px;

+ 115
- 6
src/whiteboard/AbstractWhiteboard/index.ts View File

19
   /** 元素 */
19
   /** 元素 */
20
   // 如果传入的是图片地址,则需要挂载到该 Target 元素下
20
   // 如果传入的是图片地址,则需要挂载到该 Target 元素下
21
   target: HTMLDivElement;
21
   target: HTMLDivElement;
22
-  imgEles: HTMLImageElement[] = [];
22
+  imgEles: HTMLDivElement[] = [];
23
   imgsContainer: HTMLDivElement;
23
   imgsContainer: HTMLDivElement;
24
   pagesContainer: HTMLDivElement;
24
   pagesContainer: HTMLDivElement;
25
 
25
 
26
   /** Options */
26
   /** Options */
27
   // 是否仅同步快照数据,用于弱网状态下
27
   // 是否仅同步快照数据,用于弱网状态下
28
+  allowRollback: boolean = false;
28
   onlyEmitSnap: boolean = false;
29
   onlyEmitSnap: boolean = false;
29
   snapInterval: number = 15 * 1000;
30
   snapInterval: number = 15 * 1000;
30
 
31
 
48
     return map;
49
     return map;
49
   }
50
   }
50
   siema: any;
51
   siema: any;
52
+  // 历史快照记录
53
+  snapHistory: WhiteboardSnap[] = [];
51
 
54
 
52
   /** State | 内部状态 */
55
   /** State | 内部状态 */
53
   // 是否被初始化过,如果尚未被初始化,则等待来自于 Master 的同步消息
56
   // 是否被初始化过,如果尚未被初始化,则等待来自于 Master 的同步消息
58
 
61
 
59
   constructor(
62
   constructor(
60
     target: HTMLDivElement,
63
     target: HTMLDivElement,
61
-    { sources, eventHub, visiblePageIndex, onlyEmitSnap }: Partial<AbstractWhiteboard> = {}
64
+    {
65
+      sources,
66
+      eventHub,
67
+      visiblePageIndex,
68
+      allowRollback,
69
+      onlyEmitSnap
70
+    }: Partial<AbstractWhiteboard> = {}
62
   ) {
71
   ) {
63
     if (target) {
72
     if (target) {
64
       this.target = target;
73
       this.target = target;
86
 
95
 
87
     this.onlyEmitSnap = !!onlyEmitSnap;
96
     this.onlyEmitSnap = !!onlyEmitSnap;
88
 
97
 
98
+    if (typeof allowRollback !== 'undefined') {
99
+      this.allowRollback = !!allowRollback;
100
+    }
101
+
89
     this.init();
102
     this.init();
90
   }
103
   }
91
 
104
 
134
       }
147
       }
135
     }
148
     }
136
 
149
 
150
+    // 判断是否进行了元素的增加或者删除,如果开启了则添加历史记录
151
+    if (
152
+      this.allowRollback &&
153
+      (borderEvent.event === 'addMarker' || borderEvent.event === 'removeMarker')
154
+    ) {
155
+      if (this.snapHistory.length > 20) {
156
+        this.snapHistory.shift();
157
+      }
158
+
159
+      this.snapHistory.push(this.captureSnap(false));
160
+    }
161
+
137
     borderEvent.timestamp = Math.floor(Date.now() / 1000);
162
     borderEvent.timestamp = Math.floor(Date.now() / 1000);
138
     this.eventHub.emit('sync', borderEvent);
163
     this.eventHub.emit('sync', borderEvent);
139
   }
164
   }
158
     };
183
     };
159
   }
184
   }
160
 
185
 
186
+  /** 回退到上一个 Snap */
187
+  public rollbackSnap() {
188
+    if (this.snapHistory.length === 0) {
189
+      return;
190
+    }
191
+
192
+    this.snapHistory.pop();
193
+    const snap = this.snapHistory[this.snapHistory.length - 1];
194
+
195
+    if (snap) {
196
+      this.applySnap(snap);
197
+    }
198
+  }
199
+
200
+  /** 销毁操作操作 */
201
+  public destroy(): void {
202
+    if (this.emitInterval) {
203
+      clearInterval(this.emitInterval);
204
+    }
205
+
206
+    if (this.eventHub) {
207
+      this.eventHub.removeAllListeners();
208
+    }
209
+
210
+    if (this.siema) {
211
+      this.siema.destroy();
212
+    }
213
+
214
+    this.imgsContainer.remove();
215
+    this.pagesContainer.remove();
216
+
217
+    this.pages.forEach(page => {
218
+      page.destroy();
219
+    });
220
+  }
221
+
161
   /** 初始化操作 */
222
   /** 初始化操作 */
162
   protected abstract init(): void;
223
   protected abstract init(): void;
163
 
224
 
165
   protected initSiema() {
226
   protected initSiema() {
166
     // 初始化所有的占位图片,用于给 Siema 播放使用
227
     // 初始化所有的占位图片,用于给 Siema 播放使用
167
     this.sources.forEach(source => {
228
     this.sources.forEach(source => {
168
-      const imgEle = document.createElement('img');
169
-      addClassName(imgEle, `${prefix}-img`);
170
-      imgEle.src = source;
171
-      imgEle.alt = 'Siema image';
229
+      const imgEle = document.createElement('div');
230
+      addClassName(imgEle, `${prefix}-img-wrapper`);
231
+      imgEle.style.backgroundImage = `url(${source})`;
172
 
232
 
173
       this.imgEles.push(imgEle);
233
       this.imgEles.push(imgEle);
174
       this.imgsContainer.appendChild(imgEle);
234
       this.imgsContainer.appendChild(imgEle);
188
       rtl: false
248
       rtl: false
189
     });
249
     });
190
   }
250
   }
251
+
252
+  protected abstract onPageChange(nextPageIndex: number): void;
253
+
254
+  /** 响应获取到的快照事件 */
255
+  protected applySnap(snap: WhiteboardSnap) {
256
+    const { id, sources, pageIds } = snap;
257
+
258
+    if (!this.isInitialized && !this.isSyncing) {
259
+      this.id = id;
260
+      this.sources = sources;
261
+      this.isSyncing = true;
262
+
263
+      // 初始化所有的 WhitePages
264
+      this.sources.forEach((source, i) => {
265
+        const page = new WhitePage(
266
+          { imgSrc: source },
267
+          {
268
+            mode: this.mode,
269
+            whiteboard: this,
270
+            parentContainer: this.pagesContainer
271
+          }
272
+        );
273
+        page.id = pageIds[i];
274
+
275
+        // 这里隐藏 Dashboard 的图片源,Siema 切换的是占位图片
276
+        page.container.style.visibility = 'hidden';
277
+
278
+        this.pages.push(page);
279
+
280
+        page.open();
281
+      });
282
+
283
+      this.initSiema();
284
+      this.isInitialized = true;
285
+      this.isSyncing = false;
286
+    }
287
+
288
+    // 如果已经初始化完毕,则进行状态同步
289
+    this.onPageChange(snap.visiblePageIndex);
290
+
291
+    // 同步 Pages
292
+    (snap.pages || []).forEach(pageSnap => {
293
+      const page = this.pageMap[pageSnap.id];
294
+
295
+      if (page) {
296
+        page.applySnap(pageSnap);
297
+      }
298
+    });
299
+  }
191
 }
300
 }

+ 9
- 50
src/whiteboard/MirrorWhiteboard/index.ts View File

1
 import { SyncEvent } from '../../event/SyncEvent';
1
 import { SyncEvent } from '../../event/SyncEvent';
2
-import { WhitePage } from '../WhitePage/index';
3
 import { createDivWithClassName } from '../../utils/dom';
2
 import { createDivWithClassName } from '../../utils/dom';
4
-import { WhiteboardSnap } from '../AbstractWhiteboard/snap';
5
 import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
3
 import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
6
 import { Mode } from '../../utils/types';
4
 import { Mode } from '../../utils/types';
7
 
5
 
35
           this.onPageChange(ev.border.visiblePageIndex);
33
           this.onPageChange(ev.border.visiblePageIndex);
36
         }
34
         }
37
       }
35
       }
36
+
37
+      if (ev.event === 'finish' && ev.id === this.id) {
38
+        this.destroy();
39
+      }
38
     });
40
     });
39
   }
41
   }
40
 
42
 
43
+  public destroy() {
44
+    super.destroy();
45
+  }
46
+
41
   /** 响应页面切换的事件 */
47
   /** 响应页面切换的事件 */
42
-  private onPageChange(nextPageIndex: number) {
48
+  onPageChange(nextPageIndex: number) {
43
     if (this.visiblePageIndex === nextPageIndex) {
49
     if (this.visiblePageIndex === nextPageIndex) {
44
       return;
50
       return;
45
     }
51
     }
63
       border: this.captureSnap()
69
       border: this.captureSnap()
64
     });
70
     });
65
   }
71
   }
66
-
67
-  /** 响应获取到的快照事件 */
68
-  private applySnap(snap: WhiteboardSnap) {
69
-    const { id, sources, pageIds } = snap;
70
-
71
-    if (!this.isInitialized && !this.isSyncing) {
72
-      this.id = id;
73
-      this.sources = sources;
74
-      this.isSyncing = true;
75
-
76
-      // 初始化所有的 WhitePages
77
-      this.sources.forEach((source, i) => {
78
-        const page = new WhitePage(
79
-          { imgSrc: source },
80
-          {
81
-            mode: this.mode,
82
-            whiteboard: this,
83
-            parentContainer: this.pagesContainer
84
-          }
85
-        );
86
-        page.id = pageIds[i];
87
-
88
-        // 这里隐藏 Dashboard 的图片源,Siema 切换的是占位图片
89
-        page.container.style.visibility = 'hidden';
90
-
91
-        this.pages.push(page);
92
-
93
-        page.open();
94
-      });
95
-
96
-      this.initSiema();
97
-      this.isInitialized = true;
98
-      this.isSyncing = false;
99
-    }
100
-
101
-    // 如果已经初始化完毕,则进行状态同步
102
-    this.onPageChange(snap.visiblePageIndex);
103
-
104
-    // 同步 Pages
105
-    (snap.pages || []).forEach(pageSnap => {
106
-      const page = this.pageMap[pageSnap.id];
107
-
108
-      if (page) {
109
-        page.applySnap(pageSnap);
110
-      }
111
-    });
112
-  }
113
 }
72
 }

+ 1
- 1
src/whiteboard/ReplayWhiteboard/index.ts View File

1
 import { MirrorWhiteboard } from '../MirrorWhiteboard';
1
 import { MirrorWhiteboard } from '../MirrorWhiteboard';
2
 import { SyncEvent } from '../../event/SyncEvent';
2
 import { SyncEvent } from '../../event/SyncEvent';
3
-import { EventHub } from 'fc-whiteboard/src/event/EventHub';
3
+import { EventHub } from '../../event/EventHub';
4
 
4
 
5
 // 窗口大小为一分钟
5
 // 窗口大小为一分钟
6
 const windowSize = 60 * 1000;
6
 const windowSize = 60 * 1000;

+ 32
- 8
src/whiteboard/WhitePage/index.ts View File

9
 import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
9
 import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
10
 
10
 
11
 import './index.less';
11
 import './index.less';
12
-import { ToolbarItem } from 'fc-whiteboard/src/toolbar/ToolbarItem';
12
+import { ToolbarItem } from '../../toolbar/ToolbarItem';
13
 
13
 
14
 const prefix = 'fcw-page';
14
 const prefix = 'fcw-page';
15
 
15
 
58
     }
58
     }
59
   }
59
   }
60
 
60
 
61
-  /** LifeCycle open - close */
61
+  /** LifeCycle open - destroy */
62
   public open() {
62
   public open() {
63
     this.drawboard.open();
63
     this.drawboard.open();
64
   }
64
   }
71
     this.drawboard.show();
71
     this.drawboard.show();
72
   }
72
   }
73
 
73
 
74
-  public close() {
75
-    this.drawboard.close();
74
+  public destroy() {
75
+    this.drawboard.destroy();
76
   }
76
   }
77
 
77
 
78
   /** 生成快照 */
78
   /** 生成快照 */
87
 
87
 
88
   /** 应用快照 */
88
   /** 应用快照 */
89
   public applySnap(snap: WhitepageSnap) {
89
   public applySnap(snap: WhitepageSnap) {
90
+    const markerIdsSet = new Set();
91
+
90
     snap.markers.forEach(markerSnap => {
92
     snap.markers.forEach(markerSnap => {
91
       // 判断是否存在,存在则同步,否则创建
93
       // 判断是否存在,存在则同步,否则创建
92
       const marker = this.drawboard.markerMap[markerSnap.id];
94
       const marker = this.drawboard.markerMap[markerSnap.id];
93
 
95
 
96
+      markerIdsSet.add(markerSnap.id);
97
+
98
+      // 如果存在则直接应用,否则创建新的 Marker
94
       if (marker) {
99
       if (marker) {
95
         marker.applySnap(markerSnap);
100
         marker.applySnap(markerSnap);
96
       } else {
101
       } else {
100
         newMarker.applySnap(markerSnap);
105
         newMarker.applySnap(markerSnap);
101
       }
106
       }
102
     });
107
     });
108
+
109
+    // 移除当前不存在的 Marker
110
+    this.drawboard.markers.forEach(marker => {
111
+      if (!markerIdsSet.has(marker.id)) {
112
+        // 如果不存在该 Marker,则删除
113
+        this.drawboard.deleteMarkerWithEvent(marker);
114
+      }
115
+    });
103
   }
116
   }
104
 
117
 
105
   /** 初始化源 */
118
   /** 初始化源 */
136
       this.drawboard = new Drawboard(
149
       this.drawboard = new Drawboard(
137
         { imgEle: this.target },
150
         { imgEle: this.target },
138
         {
151
         {
139
-          page: this,
140
           extraToolbarItems,
152
           extraToolbarItems,
153
+          mountContainer: this.whiteboard!.target,
154
+          page: this,
141
           onChange: ev => this.whiteboard!.emit(ev)
155
           onChange: ev => this.whiteboard!.emit(ev)
142
         }
156
         }
143
       );
157
       );
144
     } else {
158
     } else {
145
-      this.drawboard = new Drawboard({ imgEle: this.target }, { page: this });
159
+      this.drawboard = new Drawboard(
160
+        { imgEle: this.target },
161
+        { page: this, mountContainer: this.whiteboard!.target }
162
+      );
146
     }
163
     }
147
   }
164
   }
148
 
165
 
152
       throw new Error('Invalid whiteboard');
169
       throw new Error('Invalid whiteboard');
153
     }
170
     }
154
 
171
 
155
-    this.drawboard = new Drawboard({ imgEle: this.target }, { page: this });
172
+    this.drawboard = new Drawboard(
173
+      { imgEle: this.target },
174
+      { page: this, mountContainer: this.whiteboard!.target }
175
+    );
156
 
176
 
157
     this.whiteboard!.eventHub!.on('sync', (ev: SyncEvent) => {
177
     this.whiteboard!.eventHub!.on('sync', (ev: SyncEvent) => {
158
       try {
178
       try {
185
     if (ev.event === 'addMarker' && ev.parentId === this.id) {
205
     if (ev.event === 'addMarker' && ev.parentId === this.id) {
186
       const marker = this.drawboard.markerMap[id!];
206
       const marker = this.drawboard.markerMap[id!];
187
       if (!marker) {
207
       if (!marker) {
188
-        this.drawboard.addMarker(getMarkerByType(ev.marker.type!), { id: ev.marker.id });
208
+        this.drawboard.addMarker(getMarkerByType(ev.marker.type!), {
209
+          id: ev.marker.id,
210
+          originX: ev.marker.dx,
211
+          originY: ev.marker.dy
212
+        });
189
       }
213
       }
190
     }
214
     }
191
 
215
 

+ 71
- 4
src/whiteboard/Whiteboard/index.ts View File

1
+import { ToolbarItem } from './../../toolbar/ToolbarItem';
1
 import { WhitePage } from '../WhitePage/index';
2
 import { WhitePage } from '../WhitePage/index';
2
 import { createDivWithClassName } from '../../utils/dom';
3
 import { createDivWithClassName } from '../../utils/dom';
3
 import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
4
 import { AbstractWhiteboard } from '../AbstractWhiteboard/index';
6
 
7
 
7
 const LeftArrowIcon = require('../../assets/bx-left-arrow.svg');
8
 const LeftArrowIcon = require('../../assets/bx-left-arrow.svg');
8
 const RightArrowIcon = require('../../assets/bx-right-arrow.svg');
9
 const RightArrowIcon = require('../../assets/bx-right-arrow.svg');
10
+const FinishIcon = require('../../assets/finish.svg');
11
+const RollbackIcon = require('../../assets/rollback.svg');
9
 
12
 
10
 const prefix = 'fcw-board';
13
 const prefix = 'fcw-board';
11
 
14
 
12
 export class Whiteboard extends AbstractWhiteboard {
15
 export class Whiteboard extends AbstractWhiteboard {
13
   mode: Mode = 'master';
16
   mode: Mode = 'master';
14
 
17
 
18
+  /** 销毁操作 */
19
+  public destroy() {
20
+    super.destroy();
21
+  }
22
+
15
   /** 初始化操作 */
23
   /** 初始化操作 */
16
   protected init() {
24
   protected init() {
17
     // 为 target 添加子 imgs 容器
25
     // 为 target 添加子 imgs 容器
21
 
29
 
22
     this.initMaster();
30
     this.initMaster();
23
 
31
 
32
+    // 添加初始化的 Snapshot
33
+    this.snapHistory.push(this.captureSnap(false));
34
+
24
     this.emitSnapshot();
35
     this.emitSnapshot();
25
   }
36
   }
26
 
37
 
27
   /** 以主模式启动 */
38
   /** 以主模式启动 */
28
   private initMaster() {
39
   private initMaster() {
40
+    this.isInitialized = true;
41
+
29
     // 初始化控制节点
42
     // 初始化控制节点
30
     const prevToolbarItem = {
43
     const prevToolbarItem = {
31
       icon: LeftArrowIcon,
44
       icon: LeftArrowIcon,
33
       tooltipText: 'Prev',
46
       tooltipText: 'Prev',
34
       onClick: () => {
47
       onClick: () => {
35
         const nextPageIndex =
48
         const nextPageIndex =
36
-          this.visiblePageIndex + 1 > this.pages.length - 1 ? 0 : this.visiblePageIndex + 1;
49
+          this.visiblePageIndex - 1 < 0 ? this.pages.length - 1 : this.visiblePageIndex - 1;
50
+
51
+        document.querySelectorAll('.fc-whiteboard-indicator-current').forEach(e => {
52
+          e.innerHTML = `${nextPageIndex + 1}`;
53
+        });
54
+
37
         this.onPageChange(nextPageIndex);
55
         this.onPageChange(nextPageIndex);
38
       }
56
       }
39
     };
57
     };
40
 
58
 
59
+    const indicatorContainer = document.createElement('div');
60
+    indicatorContainer.className = 'fc-whiteboard-indicator-container';
61
+    const indicatorCurrent = document.createElement('span');
62
+    indicatorCurrent.className = 'fc-whiteboard-indicator-current';
63
+    indicatorCurrent.innerHTML = `${this.visiblePageIndex + 1}`;
64
+
65
+    indicatorContainer.appendChild(indicatorCurrent);
66
+    indicatorContainer.appendChild(document.createTextNode(`/${this.sources.length}`));
67
+
68
+    const indicatorItem: ToolbarItem = {
69
+      name: 'indicator',
70
+      onRender: () => indicatorContainer
71
+    };
72
+
41
     const nextToolbarItem = {
73
     const nextToolbarItem = {
42
       icon: RightArrowIcon,
74
       icon: RightArrowIcon,
43
       name: 'next-flip-arrow',
75
       name: 'next-flip-arrow',
44
       tooltipText: 'Next',
76
       tooltipText: 'Next',
45
       onClick: () => {
77
       onClick: () => {
46
         const nextPageIndex =
78
         const nextPageIndex =
47
-          this.visiblePageIndex - 1 < 0 ? this.pages.length - 1 : this.visiblePageIndex - 1;
79
+          this.visiblePageIndex + 1 > this.pages.length - 1 ? 0 : this.visiblePageIndex + 1;
80
+
81
+        document.querySelectorAll('.fc-whiteboard-indicator-current').forEach(e => {
82
+          e.innerHTML = `${nextPageIndex + 1}`;
83
+        });
48
 
84
 
49
         this.onPageChange(nextPageIndex);
85
         this.onPageChange(nextPageIndex);
50
       }
86
       }
51
     };
87
     };
52
 
88
 
89
+    const finishItem: ToolbarItem = {
90
+      icon: FinishIcon,
91
+      name: 'finish',
92
+      tooltipText: 'Finish',
93
+      onClick: () => {
94
+        this.emit({
95
+          event: 'finish',
96
+          id: this.id,
97
+          target: 'whiteboard'
98
+        });
99
+      }
100
+    };
101
+
102
+    const rollbackItem: ToolbarItem = {
103
+      icon: RollbackIcon,
104
+      name: 'rollback',
105
+      tooltipText: 'Rollback',
106
+      shortcut: 'ESC',
107
+      onClick: () => {
108
+        this.rollbackSnap();
109
+      }
110
+    };
111
+
53
     // 初始化所有的 WhitePages
112
     // 初始化所有的 WhitePages
54
     this.sources.forEach(source => {
113
     this.sources.forEach(source => {
55
       const page = new WhitePage(
114
       const page = new WhitePage(
58
           mode: this.mode,
117
           mode: this.mode,
59
           whiteboard: this,
118
           whiteboard: this,
60
           parentContainer: this.pagesContainer,
119
           parentContainer: this.pagesContainer,
61
-          extraToolbarItems: [separatorToolbarItem, prevToolbarItem, nextToolbarItem]
120
+          extraToolbarItems: [
121
+            separatorToolbarItem,
122
+            prevToolbarItem,
123
+            indicatorItem,
124
+            nextToolbarItem,
125
+            separatorToolbarItem,
126
+            finishItem,
127
+            rollbackItem
128
+          ]
62
         }
129
         }
63
       );
130
       );
64
 
131
 
72
   }
139
   }
73
 
140
 
74
   /** 响应页面切换的事件 */
141
   /** 响应页面切换的事件 */
75
-  private onPageChange(nextPageIndex: number) {
142
+  onPageChange(nextPageIndex: number) {
76
     if (this.visiblePageIndex === nextPageIndex) {
143
     if (this.visiblePageIndex === nextPageIndex) {
77
       return;
144
       return;
78
     }
145
     }

+ 151
- 1
yarn.lock View File

119
     lodash "^4.17.11"
119
     lodash "^4.17.11"
120
     to-fast-properties "^2.0.0"
120
     to-fast-properties "^2.0.0"
121
 
121
 
122
+"@interactjs/actions@1.4.9":
123
+  version "1.4.9"
124
+  resolved "https://registry.npm.taobao.org/@interactjs/actions/download/@interactjs/actions-1.4.9.tgz#be7c71b17e0aa5510a6110a45e33c42382597130"
125
+  integrity sha1-vnxxsX4KpVEKYRCkXjPEI4JZcTA=
126
+
127
+"@interactjs/auto-scroll@1.4.9":
128
+  version "1.4.9"
129
+  resolved "https://registry.npm.taobao.org/@interactjs/auto-scroll/download/@interactjs/auto-scroll-1.4.9.tgz#4bafff16d0dfefe699c7547f7a751a8716412e2a"
130
+  integrity sha1-S6//FtDf7+aZx1R/enUahxZBLio=
131
+
132
+"@interactjs/auto-start@1.4.9":
133
+  version "1.4.9"
134
+  resolved "https://registry.npm.taobao.org/@interactjs/auto-start/download/@interactjs/auto-start-1.4.9.tgz#acf6178419275ff46f026e2daf01b499d2fde546"
135
+  integrity sha1-rPYXhBknX/RvAm4trwG0mdL95UY=
136
+
137
+"@interactjs/core@1.4.9":
138
+  version "1.4.9"
139
+  resolved "https://registry.npm.taobao.org/@interactjs/core/download/@interactjs/core-1.4.9.tgz#85993b67a9839676719f3e80719f0254b417439a"
140
+  integrity sha1-hZk7Z6mDlnZxnz6AcZ8CVLQXQ5o=
141
+
142
+"@interactjs/dev-tools@1.4.9":
143
+  version "1.4.9"
144
+  resolved "https://registry.npm.taobao.org/@interactjs/dev-tools/download/@interactjs/dev-tools-1.4.9.tgz#ffd555f956814a93aa12535a38186216aaa55878"
145
+  integrity sha1-/9VV+VaBSpOqElNaOBhiFqqlWHg=
146
+  dependencies:
147
+    "@interactjs/utils" "1.4.9"
148
+
149
+"@interactjs/inertia@1.4.9":
150
+  version "1.4.9"
151
+  resolved "https://registry.npm.taobao.org/@interactjs/inertia/download/@interactjs/inertia-1.4.9.tgz#9268750f1e04ae0f0e9d111bf3e12c2a05992c26"
152
+  integrity sha1-kmh1Dx4Erg8OnREb8+EsKgWZLCY=
153
+
154
+"@interactjs/interact@1.4.9":
155
+  version "1.4.9"
156
+  resolved "https://registry.npm.taobao.org/@interactjs/interact/download/@interactjs/interact-1.4.9.tgz#f0d7fb9555bb552bff421436e651cc2127f88572"
157
+  integrity sha1-8Nf7lVW7VSv/QhQ25lHMISf4hXI=
158
+
159
+"@interactjs/modifiers@1.4.9":
160
+  version "1.4.9"
161
+  resolved "https://registry.npm.taobao.org/@interactjs/modifiers/download/@interactjs/modifiers-1.4.9.tgz#9d96f7c72c4b3dab7f99fcfc9b0c50c97a7d80c9"
162
+  integrity sha1-nZb3xyxLPat/mfz8mwxQyXp9gMk=
163
+
164
+"@interactjs/pointer-events@1.4.9":
165
+  version "1.4.9"
166
+  resolved "https://registry.npm.taobao.org/@interactjs/pointer-events/download/@interactjs/pointer-events-1.4.9.tgz#1939f0076dcf10f9ca2f6dc1895a0d0bad515887"
167
+  integrity sha1-GTnwB23PEPnKL23BiVoNC61RWIc=
168
+
169
+"@interactjs/reflow@1.4.9":
170
+  version "1.4.9"
171
+  resolved "https://registry.npm.taobao.org/@interactjs/reflow/download/@interactjs/reflow-1.4.9.tgz#c4191ccf104049c46e9405593a4d23e0ac3b3db1"
172
+  integrity sha1-xBkczxBAScRulAVZOk0j4Kw7PbE=
173
+
174
+"@interactjs/types@1.4.9":
175
+  version "1.4.9"
176
+  resolved "https://registry.npm.taobao.org/@interactjs/types/download/@interactjs/types-1.4.9.tgz#13e25b1ad942071b42af95985f71407d932f8591"
177
+  integrity sha1-E+JbGtlCBxtCr5WYX3FAfZMvhZE=
178
+  dependencies:
179
+    "@interactjs/actions" "1.4.9"
180
+    "@interactjs/auto-scroll" "1.4.9"
181
+    "@interactjs/auto-start" "1.4.9"
182
+    "@interactjs/core" "1.4.9"
183
+    "@interactjs/dev-tools" "1.4.9"
184
+    "@interactjs/inertia" "1.4.9"
185
+    "@interactjs/interact" "1.4.9"
186
+    "@interactjs/modifiers" "1.4.9"
187
+    "@interactjs/pointer-events" "1.4.9"
188
+    "@interactjs/reflow" "1.4.9"
189
+    "@interactjs/utils" "1.4.9"
190
+
191
+"@interactjs/utils@1.4.9":
192
+  version "1.4.9"
193
+  resolved "https://registry.npm.taobao.org/@interactjs/utils/download/@interactjs/utils-1.4.9.tgz#be06d81eae37ceded95205500fbd3f7dd2fdadc5"
194
+  integrity sha1-vgbYHq43zt7ZUgVQD70/fdL9rcU=
195
+
122
 "@lerna/add@3.13.1":
196
 "@lerna/add@3.13.1":
123
   version "3.13.1"
197
   version "3.13.1"
124
   resolved "http://registry.npm.taobao.org/@lerna/add/download/@lerna/add-3.13.1.tgz#2cd7838857edb3b43ed73e3c21f69a20beb9b702"
198
   resolved "http://registry.npm.taobao.org/@lerna/add/download/@lerna/add-3.13.1.tgz#2cd7838857edb3b43ed73e3c21f69a20beb9b702"
3667
   resolved "http://registry.npm.taobao.org/eventemitter3/download/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
3741
   resolved "http://registry.npm.taobao.org/eventemitter3/download/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163"
3668
   integrity sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=
3742
   integrity sha1-CQtNbNvWRe0Qv3UNS1QHlC17oWM=
3669
 
3743
 
3744
+eventemitter3@^3.1.2:
3745
+  version "3.1.2"
3746
+  resolved "https://registry.npm.taobao.org/eventemitter3/download/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7"
3747
+  integrity sha1-LT1I+cNGaY/Og6hdfWZOmFNd9uc=
3748
+
3670
 events@^3.0.0:
3749
 events@^3.0.0:
3671
   version "3.0.0"
3750
   version "3.0.0"
3672
   resolved "http://registry.npm.taobao.org/events/download/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
3751
   resolved "http://registry.npm.taobao.org/events/download/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88"
3936
   dependencies:
4015
   dependencies:
3937
     bser "^2.0.0"
4016
     bser "^2.0.0"
3938
 
4017
 
4018
+fc-hotkeys@^0.0.1-alpha.1:
4019
+  version "0.0.1-alpha.1"
4020
+  resolved "https://registry.npm.taobao.org/fc-hotkeys/download/fc-hotkeys-0.0.1-alpha.1.tgz#531cf2ffd73cf52ace324e76be2bd5ad4e2e9759"
4021
+  integrity sha1-Uxzy/9c89SrOMk52vivVrU4ul1k=
4022
+  dependencies:
4023
+    eventemitter3 "^3.1.2"
4024
+    interactjs "^1.4.0"
4025
+    mousetrap "^1.6.3"
4026
+    prop-types "^15.7.2"
4027
+    react "^16.8.6"
4028
+    react-dom "^16.8.6"
4029
+    siema "^1.5.1"
4030
+    uuid "^3.3.2"
4031
+
3939
 figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
4032
 figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
3940
   version "3.5.1"
4033
   version "3.5.1"
3941
   resolved "http://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
4034
   resolved "http://registry.npm.taobao.org/figgy-pudding/download/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
5017
     pify "^3.0.0"
5110
     pify "^3.0.0"
5018
     yargs "^11.0.0"
5111
     yargs "^11.0.0"
5019
 
5112
 
5113
+interactjs@^1.4.0, interactjs@^1.4.9:
5114
+  version "1.4.9"
5115
+  resolved "https://registry.npm.taobao.org/interactjs/download/interactjs-1.4.9.tgz#7fb30c7c1c5befb767e700ebef12acaf22f8e563"
5116
+  integrity sha1-f7MMfBxb77dn5wDr7xKsryL45WM=
5117
+  dependencies:
5118
+    "@interactjs/types" "1.4.9"
5119
+
5020
 internal-ip@^4.2.0:
5120
 internal-ip@^4.2.0:
5021
   version "4.2.0"
5121
   version "4.2.0"
5022
   resolved "http://registry.npm.taobao.org/internal-ip/download/internal-ip-4.2.0.tgz#46e81b638d84c338e5c67e42b1a17db67d0814fa"
5122
   resolved "http://registry.npm.taobao.org/internal-ip/download/internal-ip-4.2.0.tgz#46e81b638d84c338e5c67e42b1a17db67d0814fa"
6327
   resolved "http://registry.npm.taobao.org/lodash.clonedeep/download/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
6427
   resolved "http://registry.npm.taobao.org/lodash.clonedeep/download/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
6328
   integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
6428
   integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
6329
 
6429
 
6430
+lodash.debounce@^4.0.8:
6431
+  version "4.0.8"
6432
+  resolved "https://registry.npm.taobao.org/lodash.debounce/download/lodash.debounce-4.0.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.debounce%2Fdownload%2Flodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
6433
+  integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
6434
+
6330
 lodash.defaults@^3.1.2:
6435
 lodash.defaults@^3.1.2:
6331
   version "3.1.2"
6436
   version "3.1.2"
6332
   resolved "http://registry.npm.taobao.org/lodash.defaults/download/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c"
6437
   resolved "http://registry.npm.taobao.org/lodash.defaults/download/lodash.defaults-3.1.2.tgz#c7308b18dbf8bc9372d701a73493c61192bd2e2c"
6925
     "@most/prelude" "^1.4.0"
7030
     "@most/prelude" "^1.4.0"
6926
     symbol-observable "^1.0.2"
7031
     symbol-observable "^1.0.2"
6927
 
7032
 
7033
+mousetrap@^1.6.3:
7034
+  version "1.6.3"
7035
+  resolved "https://registry.npm.taobao.org/mousetrap/download/mousetrap-1.6.3.tgz#80fee49665fd478bccf072c9d46bdf1bfed3558a"
7036
+  integrity sha1-gP7klmX9R4vM8HLJ1GvfG/7TVYo=
7037
+
6928
 move-concurrently@^1.0.1:
7038
 move-concurrently@^1.0.1:
6929
   version "1.0.1"
7039
   version "1.0.1"
6930
   resolved "http://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
7040
   resolved "http://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
7943
   resolved "http://registry.npm.taobao.org/pn/download/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
8053
   resolved "http://registry.npm.taobao.org/pn/download/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
7944
   integrity sha1-4vTO8OIZ9GPBeas3Rj5OHs3Muvs=
8054
   integrity sha1-4vTO8OIZ9GPBeas3Rj5OHs3Muvs=
7945
 
8055
 
8056
+popper.js@^1.14.7:
8057
+  version "1.15.0"
8058
+  resolved "https://registry.npm.taobao.org/popper.js/download/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2"
8059
+  integrity sha1-VWC5m7rXZH6fqkdca4BWYh9aT/I=
8060
+
7946
 portfinder@^1.0.9:
8061
 portfinder@^1.0.9:
7947
   version "1.0.20"
8062
   version "1.0.20"
7948
   resolved "http://registry.npm.taobao.org/portfinder/download/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a"
8063
   resolved "http://registry.npm.taobao.org/portfinder/download/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a"
8382
   dependencies:
8497
   dependencies:
8383
     read "1"
8498
     read "1"
8384
 
8499
 
8385
-prop-types@^15.6.1, prop-types@^15.6.2:
8500
+prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
8386
   version "15.7.2"
8501
   version "15.7.2"
8387
   resolved "http://registry.npm.taobao.org/prop-types/download/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
8502
   resolved "http://registry.npm.taobao.org/prop-types/download/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
8388
   integrity sha1-UsQedbjIfnK52TYOAga5ncv/psU=
8503
   integrity sha1-UsQedbjIfnK52TYOAga5ncv/psU=
8592
     prop-types "^15.6.2"
8707
     prop-types "^15.6.2"
8593
     scheduler "^0.13.4"
8708
     scheduler "^0.13.4"
8594
 
8709
 
8710
+react-dom@^16.8.6:
8711
+  version "16.8.6"
8712
+  resolved "https://registry.npm.taobao.org/react-dom/download/react-dom-16.8.6.tgz#71d6303f631e8b0097f56165ef608f051ff6e10f"
8713
+  integrity sha1-cdYwP2MeiwCX9WFl72CPBR/24Q8=
8714
+  dependencies:
8715
+    loose-envify "^1.1.0"
8716
+    object-assign "^4.1.1"
8717
+    prop-types "^15.6.2"
8718
+    scheduler "^0.13.6"
8719
+
8595
 react-hot-loader@^4.6.3:
8720
 react-hot-loader@^4.6.3:
8596
   version "4.8.0"
8721
   version "4.8.0"
8597
   resolved "http://registry.npm.taobao.org/react-hot-loader/download/react-hot-loader-4.8.0.tgz#0b7c7dd9407415e23eb8246fdd28b0b839f54cb6"
8722
   resolved "http://registry.npm.taobao.org/react-hot-loader/download/react-hot-loader-4.8.0.tgz#0b7c7dd9407415e23eb8246fdd28b0b839f54cb6"
8652
     prop-types "^15.6.2"
8777
     prop-types "^15.6.2"
8653
     scheduler "^0.13.4"
8778
     scheduler "^0.13.4"
8654
 
8779
 
8780
+react@^16.8.6:
8781
+  version "16.8.6"
8782
+  resolved "https://registry.npm.taobao.org/react/download/react-16.8.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact%2Fdownload%2Freact-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"
8783
+  integrity sha1-rWw6lhT9Ok6e9REX9U2IjaAfK74=
8784
+  dependencies:
8785
+    loose-envify "^1.1.0"
8786
+    object-assign "^4.1.1"
8787
+    prop-types "^15.6.2"
8788
+    scheduler "^0.13.6"
8789
+
8655
 read-cmd-shim@^1.0.1:
8790
 read-cmd-shim@^1.0.1:
8656
   version "1.0.1"
8791
   version "1.0.1"
8657
   resolved "http://registry.npm.taobao.org/read-cmd-shim/download/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b"
8792
   resolved "http://registry.npm.taobao.org/read-cmd-shim/download/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b"
9137
     loose-envify "^1.1.0"
9272
     loose-envify "^1.1.0"
9138
     object-assign "^4.1.1"
9273
     object-assign "^4.1.1"
9139
 
9274
 
9275
+scheduler@^0.13.6:
9276
+  version "0.13.6"
9277
+  resolved "https://registry.npm.taobao.org/scheduler/download/scheduler-0.13.6.tgz?cache=0&sync_timestamp=1559596534856&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fscheduler%2Fdownload%2Fscheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889"
9278
+  integrity sha1-RmpOwzJGezGpG5v3TlNHBy5M2Ik=
9279
+  dependencies:
9280
+    loose-envify "^1.1.0"
9281
+    object-assign "^4.1.1"
9282
+
9140
 schema-utils@^1.0.0:
9283
 schema-utils@^1.0.0:
9141
   version "1.0.0"
9284
   version "1.0.0"
9142
   resolved "http://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
9285
   resolved "http://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
10014
   resolved "http://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
10157
   resolved "http://registry.npm.taobao.org/timsort/download/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
10015
   integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
10158
   integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
10016
 
10159
 
10160
+tippy.js@^4.3.4:
10161
+  version "4.3.4"
10162
+  resolved "https://registry.npm.taobao.org/tippy.js/download/tippy.js-4.3.4.tgz#9a91fd5ce8c401f181b7adaa6b2c27f3d105f3ba"
10163
+  integrity sha1-mpH9XOjEAfGBt62qaywn89EF87o=
10164
+  dependencies:
10165
+    popper.js "^1.14.7"
10166
+
10017
 tmp@^0.0.33:
10167
 tmp@^0.0.33:
10018
   version "0.0.33"
10168
   version "0.0.33"
10019
   resolved "http://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
10169
   resolved "http://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"