@netless/forge-whiteboard 0.1.6 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -3
- package/changelog.md +28 -0
- package/dist/Camera.d.ts +14 -2
- package/dist/Camera.d.ts.map +1 -1
- package/dist/Whiteboard.d.ts +31 -0
- package/dist/Whiteboard.d.ts.map +1 -1
- package/dist/WhiteboardApplication.d.ts +6 -0
- package/dist/WhiteboardApplication.d.ts.map +1 -1
- package/dist/whiteboard.esm.js +216 -22
- package/dist/whiteboard.esm.js.map +3 -3
- package/dist/whiteboard.js +215 -21
- package/dist/whiteboard.js.map +2 -2
- package/package.json +4 -3
package/dist/whiteboard.js
CHANGED
|
@@ -27761,7 +27761,7 @@ var ToolbarModel = class extends import_eventemitter33.default {
|
|
|
27761
27761
|
this.root = root;
|
|
27762
27762
|
this.root.observe(this.handleRootUpdate);
|
|
27763
27763
|
Object.keys(defaultStyle).forEach((key) => {
|
|
27764
|
-
if (!this.root.has(key)) {
|
|
27764
|
+
if (!this.root.has(key) || this.root.get(key) === void 0) {
|
|
27765
27765
|
this.root.set(key, defaultStyle[key]);
|
|
27766
27766
|
}
|
|
27767
27767
|
});
|
|
@@ -28838,6 +28838,14 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
28838
28838
|
hasPermission;
|
|
28839
28839
|
gesture;
|
|
28840
28840
|
inherentScale = 1;
|
|
28841
|
+
maxScale;
|
|
28842
|
+
initSize;
|
|
28843
|
+
bound;
|
|
28844
|
+
boundTiemoutId;
|
|
28845
|
+
enableByMouse = true;
|
|
28846
|
+
enableByTouch = true;
|
|
28847
|
+
boundaryColor = "#F44336";
|
|
28848
|
+
enableBoundaryHighlight = true;
|
|
28841
28849
|
get inherentMatrix() {
|
|
28842
28850
|
const inherentMatrix = new this.scope.Matrix();
|
|
28843
28851
|
inherentMatrix.scale(this.inherentScale, [0, 0]);
|
|
@@ -28847,8 +28855,12 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
28847
28855
|
const view = this.scope.project.view;
|
|
28848
28856
|
return 1 / view.matrix.scaling.x;
|
|
28849
28857
|
}
|
|
28850
|
-
constructor(dom, userManager, scope, whiteboardAttrsMap, hasPermission, requestUserMap, paperSize, domSize) {
|
|
28858
|
+
constructor(initSize, maxScale, dom, userManager, scope, whiteboardAttrsMap, hasPermission, requestUserMap, paperSize, domSize) {
|
|
28851
28859
|
super();
|
|
28860
|
+
this.maxScale = maxScale;
|
|
28861
|
+
this.bound = window.document.createElement("div");
|
|
28862
|
+
this.bound.style.cssText = `transition: box-shadow 100ms;pointer-events:none;z-index:99;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);`;
|
|
28863
|
+
this.initSize = initSize;
|
|
28852
28864
|
this.hasPermission = hasPermission;
|
|
28853
28865
|
this.paperSize = paperSize;
|
|
28854
28866
|
this.domSize = domSize;
|
|
@@ -28857,6 +28869,7 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
28857
28869
|
this.requestUserMap = requestUserMap;
|
|
28858
28870
|
this.userManager = userManager;
|
|
28859
28871
|
this.dom = dom;
|
|
28872
|
+
this.dom.appendChild(this.bound);
|
|
28860
28873
|
this.dom.addEventListener("wheel", this.handleWheel, { passive: false, capture: true });
|
|
28861
28874
|
this.dom.addEventListener("touchstart", (e) => {
|
|
28862
28875
|
e.preventDefault();
|
|
@@ -28877,17 +28890,32 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
28877
28890
|
this.whiteboardAttrsMap.observe(this.handleMainCameraChange);
|
|
28878
28891
|
this.gesture = new Gesture(this.dom, this.scope);
|
|
28879
28892
|
this.gesture.on("offset", (x, y) => {
|
|
28893
|
+
if (!this.enableByTouch) {
|
|
28894
|
+
return;
|
|
28895
|
+
}
|
|
28880
28896
|
const matrix = new this.scope.Matrix();
|
|
28881
28897
|
matrix.translate({ x: x * this.translateScale, y: y * this.translateScale });
|
|
28882
|
-
this.
|
|
28898
|
+
this.updateViewMatrix(matrix);
|
|
28883
28899
|
});
|
|
28884
28900
|
this.gesture.on("scale", (scale, center) => {
|
|
28901
|
+
if (!this.enableByTouch) {
|
|
28902
|
+
return;
|
|
28903
|
+
}
|
|
28885
28904
|
const matrix = new this.scope.Matrix();
|
|
28886
28905
|
const paperPoint = this.scope.project.view.viewToProject(center);
|
|
28887
28906
|
matrix.scale(scale, paperPoint);
|
|
28888
|
-
this.
|
|
28907
|
+
this.updateViewMatrix(matrix);
|
|
28889
28908
|
});
|
|
28890
28909
|
}
|
|
28910
|
+
highlightBound() {
|
|
28911
|
+
if (this.enableBoundaryHighlight) {
|
|
28912
|
+
this.bound.style.boxShadow = `inset 0px 0px 6px 2px ${this.boundaryColor}`;
|
|
28913
|
+
window.clearTimeout(this.boundTiemoutId);
|
|
28914
|
+
this.boundTiemoutId = window.setTimeout(() => {
|
|
28915
|
+
this.bound.style.boxShadow = `none`;
|
|
28916
|
+
}, 100);
|
|
28917
|
+
}
|
|
28918
|
+
}
|
|
28891
28919
|
updateInherentScale(scale) {
|
|
28892
28920
|
this.inherentScale = scale;
|
|
28893
28921
|
}
|
|
@@ -28904,6 +28932,9 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
28904
28932
|
return new this.scope.Matrix(matrixValue);
|
|
28905
28933
|
}
|
|
28906
28934
|
triggerZoom() {
|
|
28935
|
+
const [width, height] = this.domSize();
|
|
28936
|
+
this.bound.style.width = `${width}px`;
|
|
28937
|
+
this.bound.style.height = `${height}px`;
|
|
28907
28938
|
this.emit("zoom", this.inherentMatrix.appended(this.getActiveMatrix()));
|
|
28908
28939
|
}
|
|
28909
28940
|
resetViewMatrixToFlow(userId) {
|
|
@@ -28982,29 +29013,89 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
28982
29013
|
}
|
|
28983
29014
|
}
|
|
28984
29015
|
};
|
|
28985
|
-
|
|
29016
|
+
validNextMatrix(next) {
|
|
29017
|
+
let shouldHighlightBound = false;
|
|
29018
|
+
const maxTranslate = (this.maxScale - 1) / 2;
|
|
29019
|
+
const maxScale = maxTranslate * 2 + 1;
|
|
29020
|
+
const minScale = 1 / maxScale;
|
|
29021
|
+
if (next.a > maxScale) {
|
|
29022
|
+
const tx = next.tx / next.a;
|
|
29023
|
+
next.a = maxScale;
|
|
29024
|
+
next.tx = tx * maxScale;
|
|
29025
|
+
shouldHighlightBound = true;
|
|
29026
|
+
}
|
|
29027
|
+
if (next.a < minScale) {
|
|
29028
|
+
const tx = next.tx / next.a;
|
|
29029
|
+
next.a = minScale;
|
|
29030
|
+
next.tx = tx * minScale;
|
|
29031
|
+
shouldHighlightBound = true;
|
|
29032
|
+
}
|
|
29033
|
+
if (next.d > maxScale) {
|
|
29034
|
+
const ty = next.ty / next.d;
|
|
29035
|
+
next.d = maxScale;
|
|
29036
|
+
next.ty = ty * maxScale;
|
|
29037
|
+
shouldHighlightBound = true;
|
|
29038
|
+
}
|
|
29039
|
+
if (next.d < minScale) {
|
|
29040
|
+
const ty = next.ty / next.d;
|
|
29041
|
+
next.d = minScale;
|
|
29042
|
+
next.ty = ty * minScale;
|
|
29043
|
+
shouldHighlightBound = true;
|
|
29044
|
+
}
|
|
29045
|
+
const maxTranslateX = this.initSize.width * maxTranslate;
|
|
29046
|
+
if (next.tx / next.a > maxTranslateX) {
|
|
29047
|
+
next.tx = maxTranslateX * next.a;
|
|
29048
|
+
shouldHighlightBound = true;
|
|
29049
|
+
}
|
|
29050
|
+
const minTx = (this.initSize.width * (maxTranslate + 1) - this.scope.project.view.bounds.width) * -next.a;
|
|
29051
|
+
if (next.tx < minTx) {
|
|
29052
|
+
next.tx = minTx;
|
|
29053
|
+
shouldHighlightBound = true;
|
|
29054
|
+
}
|
|
29055
|
+
const maxTranslateY = this.initSize.height * maxTranslate;
|
|
29056
|
+
if (next.ty / next.d > maxTranslateY) {
|
|
29057
|
+
next.ty = maxTranslateY * next.d;
|
|
29058
|
+
shouldHighlightBound = true;
|
|
29059
|
+
}
|
|
29060
|
+
const minTy = (this.initSize.height * (maxTranslate + 1) - this.scope.project.view.bounds.height) * -next.d;
|
|
29061
|
+
if (next.ty < minTy) {
|
|
29062
|
+
next.ty = minTy;
|
|
29063
|
+
shouldHighlightBound = true;
|
|
29064
|
+
}
|
|
29065
|
+
if (shouldHighlightBound) {
|
|
29066
|
+
this.highlightBound();
|
|
29067
|
+
}
|
|
29068
|
+
return next;
|
|
29069
|
+
}
|
|
29070
|
+
updateViewMatrix(matrix, append = true) {
|
|
28986
29071
|
const userMap = this.requestUserMap(this.userManager.selfId);
|
|
28987
29072
|
const cameraMode = userMap.get(WhiteboardKeys.cameraMode);
|
|
28988
|
-
|
|
29073
|
+
let next = matrix;
|
|
29074
|
+
if (append) {
|
|
28989
29075
|
const currentMatrixValue = userMap.get(WhiteboardKeys.viewMatrix);
|
|
28990
29076
|
const current = new this.scope.Matrix(currentMatrixValue);
|
|
28991
|
-
|
|
28992
|
-
|
|
28993
|
-
|
|
29077
|
+
next = current.appended(matrix);
|
|
29078
|
+
}
|
|
29079
|
+
if (this.maxScale >= 1) {
|
|
29080
|
+
next = this.validNextMatrix(next);
|
|
29081
|
+
} else {
|
|
29082
|
+
if (!(next.scaling.x <= 3 && next.scaling.x >= 0.2) && append) {
|
|
29083
|
+
return;
|
|
28994
29084
|
}
|
|
28995
29085
|
}
|
|
29086
|
+
if (cameraMode === "free" || cameraMode === "main") {
|
|
29087
|
+
userMap.set(WhiteboardKeys.viewMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
|
|
29088
|
+
}
|
|
28996
29089
|
if (cameraMode === "main") {
|
|
28997
29090
|
if (this.hasPermission(32 /* mainView */)) {
|
|
28998
|
-
|
|
28999
|
-
const current = new this.scope.Matrix(currentMatrixValue);
|
|
29000
|
-
const next = current.appended(matrix);
|
|
29001
|
-
if (next.scaling.x <= 3 && next.scaling.x >= 0.3) {
|
|
29002
|
-
this.whiteboardAttrsMap.set(WhiteboardKeys.viewMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
|
|
29003
|
-
}
|
|
29091
|
+
this.whiteboardAttrsMap.set(WhiteboardKeys.viewMatrix, [next.a, next.b, next.c, next.d, next.tx, next.ty]);
|
|
29004
29092
|
}
|
|
29005
29093
|
}
|
|
29006
29094
|
}
|
|
29007
29095
|
handleWheel = (evt) => {
|
|
29096
|
+
if (!this.enableByMouse) {
|
|
29097
|
+
return;
|
|
29098
|
+
}
|
|
29008
29099
|
evt.preventDefault();
|
|
29009
29100
|
evt.stopImmediatePropagation();
|
|
29010
29101
|
evt.stopPropagation();
|
|
@@ -29028,22 +29119,33 @@ var Camera = class extends import_eventemitter38.default {
|
|
|
29028
29119
|
} else {
|
|
29029
29120
|
scale = 1 + Math.abs(deltaY / wheelDelta);
|
|
29030
29121
|
}
|
|
29122
|
+
scale = Math.max(0.9, scale);
|
|
29123
|
+
scale = Math.min(1.1, scale);
|
|
29031
29124
|
matrix.scale(scale, paperPoint);
|
|
29032
|
-
this.
|
|
29125
|
+
this.updateViewMatrix(matrix);
|
|
29033
29126
|
} else {
|
|
29034
29127
|
const deltaX = this.lastDelta.x + evt.deltaX;
|
|
29035
29128
|
const deltaY = this.lastDelta.y + evt.deltaY;
|
|
29036
29129
|
const matrix = new this.scope.Matrix();
|
|
29037
29130
|
matrix.translate({ x: -deltaX * window.devicePixelRatio, y: -deltaY * window.devicePixelRatio });
|
|
29038
|
-
this.
|
|
29131
|
+
this.updateViewMatrix(matrix);
|
|
29039
29132
|
}
|
|
29040
29133
|
this.lastTriggerTime = Date.now();
|
|
29041
29134
|
this.lastDelta = { x: 0, y: 0 };
|
|
29042
29135
|
};
|
|
29136
|
+
scale(value) {
|
|
29137
|
+
const matrix = new this.scope.Matrix();
|
|
29138
|
+
matrix.scale(value, this.scope.project.view.bounds.center);
|
|
29139
|
+
this.updateViewMatrix(matrix);
|
|
29140
|
+
}
|
|
29043
29141
|
translate(offsetX, offsetY) {
|
|
29044
29142
|
const matrix = new this.scope.Matrix();
|
|
29045
29143
|
matrix.translate({ x: offsetX, y: offsetY });
|
|
29046
|
-
this.
|
|
29144
|
+
this.updateViewMatrix(matrix);
|
|
29145
|
+
}
|
|
29146
|
+
reset() {
|
|
29147
|
+
this.updateViewMatrix(new this.scope.Matrix(), false);
|
|
29148
|
+
this.lastDelta = { x: 0, y: 0 };
|
|
29047
29149
|
}
|
|
29048
29150
|
};
|
|
29049
29151
|
|
|
@@ -29152,6 +29254,22 @@ var Whiteboard = class extends import_eventemitter39.default {
|
|
|
29152
29254
|
* 描边宽度
|
|
29153
29255
|
*/
|
|
29154
29256
|
strokeWidth;
|
|
29257
|
+
/**
|
|
29258
|
+
* 是否允许用鼠标/触控板进行缩放和拖动画布
|
|
29259
|
+
*/
|
|
29260
|
+
enableCameraByMouse;
|
|
29261
|
+
/**
|
|
29262
|
+
* 是否允许触摸屏上触摸事件进行缩放和拖动画布
|
|
29263
|
+
*/
|
|
29264
|
+
enableCameraByTouch;
|
|
29265
|
+
/**
|
|
29266
|
+
* 相机超出边界时, 警示阴影的颜色, 默认 "#F44336"
|
|
29267
|
+
*/
|
|
29268
|
+
cameraBoundaryColor;
|
|
29269
|
+
/**
|
|
29270
|
+
* 是否允许相机超出边界时, 警示高亮阴影, 默认 true
|
|
29271
|
+
*/
|
|
29272
|
+
enableCameraBoundaryHighlight;
|
|
29155
29273
|
getElementAttribute;
|
|
29156
29274
|
setElementAttribute;
|
|
29157
29275
|
getCurrentTool;
|
|
@@ -29193,6 +29311,21 @@ var Whiteboard = class extends import_eventemitter39.default {
|
|
|
29193
29311
|
* 清空当前页面
|
|
29194
29312
|
*/
|
|
29195
29313
|
clearPage;
|
|
29314
|
+
/**
|
|
29315
|
+
* 平移画布
|
|
29316
|
+
* @param {number} offsetX - x 轴偏移量
|
|
29317
|
+
* @param {number} offsetY - y 轴偏移量
|
|
29318
|
+
*/
|
|
29319
|
+
translateCamera;
|
|
29320
|
+
/**
|
|
29321
|
+
* 以画布中心为固定点缩放画布
|
|
29322
|
+
* @param {number} scale - 缩放比例
|
|
29323
|
+
*/
|
|
29324
|
+
scaleCamera;
|
|
29325
|
+
/**
|
|
29326
|
+
* 重置画布, 将画布缩放比例重置为 1, 平移量重置为 [0, 0]
|
|
29327
|
+
*/
|
|
29328
|
+
resetCamera;
|
|
29196
29329
|
/**
|
|
29197
29330
|
* 为 userId 指定的用户设置页面, 调用需要有 `WhiteboardPermissionFlag.setOthersView` 权限,
|
|
29198
29331
|
* userId 指定的用户的视角模式应为 `free`, 否则调用无效
|
|
@@ -30149,6 +30282,21 @@ var WhiteboardApplication = class extends import_forge_room3.AbstractApplication
|
|
|
30149
30282
|
this.inputType = type;
|
|
30150
30283
|
this.emitter.emit("inputTypeChange", this.inputType);
|
|
30151
30284
|
};
|
|
30285
|
+
this.emitter.translateCamera = (offsetX, offsetY) => {
|
|
30286
|
+
this.camera.translate(offsetX, offsetY);
|
|
30287
|
+
};
|
|
30288
|
+
this.emitter.scaleCamera = (scale) => {
|
|
30289
|
+
this.camera.scale(scale);
|
|
30290
|
+
};
|
|
30291
|
+
this.emitter.resetCamera = () => {
|
|
30292
|
+
this.camera.reset();
|
|
30293
|
+
};
|
|
30294
|
+
this.emitter.on("error", (errorCode, errorMessage) => {
|
|
30295
|
+
(0, import_forge_room3.log)("WhiteboardApplicationError", {
|
|
30296
|
+
errorCode,
|
|
30297
|
+
errorMessage
|
|
30298
|
+
});
|
|
30299
|
+
});
|
|
30152
30300
|
const that = this;
|
|
30153
30301
|
Object.defineProperty(this.emitter, "tool", {
|
|
30154
30302
|
get() {
|
|
@@ -30206,6 +30354,38 @@ var WhiteboardApplication = class extends import_forge_room3.AbstractApplication
|
|
|
30206
30354
|
that.toolbarModel.dashArray = v;
|
|
30207
30355
|
}
|
|
30208
30356
|
});
|
|
30357
|
+
Object.defineProperty(this.emitter, "enableCameraByMouse", {
|
|
30358
|
+
get() {
|
|
30359
|
+
return that.camera.enableByMouse;
|
|
30360
|
+
},
|
|
30361
|
+
set(value) {
|
|
30362
|
+
that.camera.enableByMouse = value;
|
|
30363
|
+
}
|
|
30364
|
+
});
|
|
30365
|
+
Object.defineProperty(this.emitter, "enableCameraByTouch", {
|
|
30366
|
+
get() {
|
|
30367
|
+
return that.camera.enableByTouch;
|
|
30368
|
+
},
|
|
30369
|
+
set(value) {
|
|
30370
|
+
that.camera.enableByTouch = value;
|
|
30371
|
+
}
|
|
30372
|
+
});
|
|
30373
|
+
Object.defineProperty(this.emitter, "cameraBoundaryColor", {
|
|
30374
|
+
get() {
|
|
30375
|
+
return that.camera.boundaryColor;
|
|
30376
|
+
},
|
|
30377
|
+
set(value) {
|
|
30378
|
+
that.camera.boundaryColor = value;
|
|
30379
|
+
}
|
|
30380
|
+
});
|
|
30381
|
+
Object.defineProperty(this.emitter, "enableCameraBoundaryHighlight", {
|
|
30382
|
+
get() {
|
|
30383
|
+
return that.camera.enableBoundaryHighlight;
|
|
30384
|
+
},
|
|
30385
|
+
set(value) {
|
|
30386
|
+
that.camera.enableBoundaryHighlight = value;
|
|
30387
|
+
}
|
|
30388
|
+
});
|
|
30209
30389
|
}
|
|
30210
30390
|
userMap(userId) {
|
|
30211
30391
|
return this.getMap(`user/${userId}`);
|
|
@@ -30233,7 +30413,12 @@ var WhiteboardApplication = class extends import_forge_room3.AbstractApplication
|
|
|
30233
30413
|
);
|
|
30234
30414
|
this.pageModel.on("pagesChange", this.handleLayersChange);
|
|
30235
30415
|
this.pageModel.on("switchPage", this.handlePageSwitch);
|
|
30416
|
+
if (option.maxScaleRatio && option.maxScaleRatio < 1 && option.maxScaleRatio !== -1) {
|
|
30417
|
+
throw new Error(`[@netless/forge-whiteboard] invalid maxScaleRatio ${option.maxScaleRatio}`);
|
|
30418
|
+
}
|
|
30236
30419
|
this.camera = new Camera(
|
|
30420
|
+
new this.paperScope.Size(option.width, option.height),
|
|
30421
|
+
option.maxScaleRatio ?? -1,
|
|
30237
30422
|
this.rootElement,
|
|
30238
30423
|
this.userManager,
|
|
30239
30424
|
this.paperScope,
|
|
@@ -30294,10 +30479,19 @@ var WhiteboardApplication = class extends import_forge_room3.AbstractApplication
|
|
|
30294
30479
|
grab: new GrabTool(this.enableToolEvent, this.getCurrentRenderableModel, this.shadowEmitter, this.paperScope, this.camera)
|
|
30295
30480
|
};
|
|
30296
30481
|
this.toolbarModel.on("update", (style) => {
|
|
30297
|
-
|
|
30482
|
+
if (this.tools[style.tool]) {
|
|
30483
|
+
this.paperScope.tool = this.tools[style.tool].tool;
|
|
30484
|
+
} else {
|
|
30485
|
+
this.emitter.emit("error", 300001, `${style.tool} not supported`);
|
|
30486
|
+
}
|
|
30298
30487
|
this.emitter.emit("toolbarStyleChange", style);
|
|
30299
30488
|
});
|
|
30300
|
-
|
|
30489
|
+
if (this.tools[this.toolbarModel.currentTool]) {
|
|
30490
|
+
this.paperScope.tool = this.tools[this.toolbarModel.currentTool].tool;
|
|
30491
|
+
} else {
|
|
30492
|
+
this.paperScope.tool = this.tools["curve"].tool;
|
|
30493
|
+
(0, import_forge_room3.log)(`${this.toolbarModel.currentTool} not supported, backup to curve`);
|
|
30494
|
+
}
|
|
30301
30495
|
this.selectElementsModel.on("elementsChange", this.handleElementsSelect);
|
|
30302
30496
|
this.trashedElementsModel.on("elementsChange", this.handleElementsTrash);
|
|
30303
30497
|
this.trashedElementsModel.on("removeElementForSelf", this.handleRemoveTrashedElementForSelf);
|
|
@@ -30516,7 +30710,7 @@ var WhiteboardApplication = class extends import_forge_room3.AbstractApplication
|
|
|
30516
30710
|
getCurrentRenderableModel = () => {
|
|
30517
30711
|
let layerId = this.userMap(this.userId).get(WhiteboardKeys.currentPage);
|
|
30518
30712
|
if (!this.layers.has(layerId)) {
|
|
30519
|
-
this.emitter.emit("error",
|
|
30713
|
+
this.emitter.emit("error", 300002, `target page: ${layerId} not found`);
|
|
30520
30714
|
}
|
|
30521
30715
|
return this.layers.get(layerId);
|
|
30522
30716
|
};
|