kfb-view 2.1.7 → 2.1.11
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/.idea/git_toolbox_prj.xml +15 -0
- package/.idea/workspace.xml +109 -166
- package/config/webpack.dev.conf.js +2 -2
- package/config/webpack.lib.conf.js +3 -3
- package/config/webpack.prod.conf.js +3 -3
- package/example/index.js +120 -83
- package/lib/kfb-view.js +2 -1
- package/lib/kfb-view.js.LICENSE.txt +9 -0
- package/package.json +3 -3
- package/src/components/area/index.js +32 -14
- package/src/components/board/index.js +7 -2
- package/src/components/tailoring/index.js +11 -11
- package/src/util/imageData.js +10 -6
- package/src/view.js +19 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kfb-view",
|
|
3
3
|
"description": "一个在线kfb的阅片软件",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.11",
|
|
5
5
|
"author": "qifeng.fan <qifeng.fan@hzztai.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "lib/kfb-view.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@babel/plugin-proposal-function-bind": "^7.0.0",
|
|
35
35
|
"@babel/plugin-proposal-function-sent": "^7.0.0",
|
|
36
36
|
"@babel/plugin-proposal-json-strings": "^7.0.0",
|
|
37
|
-
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.
|
|
37
|
+
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
|
|
38
38
|
"@babel/plugin-proposal-numeric-separator": "^7.0.0",
|
|
39
39
|
"@babel/plugin-proposal-object-rest-spread": "^7.3.1",
|
|
40
40
|
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"sass-loader": "^7.0.3",
|
|
68
68
|
"script-ext-html-webpack-plugin": "^2.0.1",
|
|
69
69
|
"style-loader": "^0.21.0",
|
|
70
|
-
"
|
|
70
|
+
"terser-webpack-plugin": "^4.2.2",
|
|
71
71
|
"url-loader": "^1.0.1",
|
|
72
72
|
"webpack": "^4.14.0",
|
|
73
73
|
"webpack-cli": "^3.0.8",
|
|
@@ -51,7 +51,10 @@ export class Area extends ViewerCommon {
|
|
|
51
51
|
* @param {Object=} config 参数,参见thumb
|
|
52
52
|
*/
|
|
53
53
|
drawPoint(point, config) {
|
|
54
|
-
this.thumb.draw(point,
|
|
54
|
+
this.thumb.draw(point, {
|
|
55
|
+
...config,
|
|
56
|
+
strokeStyle: this.options.thumbColor,
|
|
57
|
+
});
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
/**
|
|
@@ -167,8 +170,8 @@ export class Area extends ViewerCommon {
|
|
|
167
170
|
if (~moveIndex) {
|
|
168
171
|
this.movePoint = {position: moveIndex, label: item};
|
|
169
172
|
} else if ((item.tool !== POLYGON &&
|
|
170
|
-
|
|
171
|
-
|
|
173
|
+
isPointInMatrix(pointList[0], pointList[2], pointList[6], pointList[8],
|
|
174
|
+
{x, y})) ||
|
|
172
175
|
(item.tool === POLYGON && isPointInPolygon({x, y}, pointList))) {
|
|
173
176
|
selectList.push(item);
|
|
174
177
|
}
|
|
@@ -344,7 +347,7 @@ export class Area extends ViewerCommon {
|
|
|
344
347
|
(position === movePoints[movePoints.length - 1].index && index >=
|
|
345
348
|
position && index >= nextIndex) ||
|
|
346
349
|
((position !== 0 && position !==
|
|
347
|
-
|
|
350
|
+
movePoints[movePoints.length - 1].index) && index >= position &&
|
|
348
351
|
index <= nextIndex)) {
|
|
349
352
|
if (nextRatio === Infinity) {
|
|
350
353
|
return {
|
|
@@ -363,7 +366,7 @@ export class Area extends ViewerCommon {
|
|
|
363
366
|
(position === movePoints[movePoints.length - 1].index && index <=
|
|
364
367
|
position && index >= lastIndex) ||
|
|
365
368
|
((position !== 0 && position !==
|
|
366
|
-
|
|
369
|
+
movePoints[movePoints.length - 1].index) && index >= lastIndex &&
|
|
367
370
|
index <= position)) {
|
|
368
371
|
if (lastRatio === Infinity) {
|
|
369
372
|
return {
|
|
@@ -388,7 +391,16 @@ export class Area extends ViewerCommon {
|
|
|
388
391
|
_startPoint = {x: endPoint.x + distX, y: endPoint.y + distY};
|
|
389
392
|
_endPoint = {x: endPoint.x + distX, y: endPoint.y + distY};
|
|
390
393
|
}
|
|
391
|
-
} else if (tool === STAR
|
|
394
|
+
} else if (tool === STAR) {
|
|
395
|
+
if (position === 4) {
|
|
396
|
+
_startPoint = {x: endPoint.x + distX, y: endPoint.y + distY};
|
|
397
|
+
_endPoint = {x: endPoint.x + distX, y: endPoint.y + distY};
|
|
398
|
+
} else if (position === 0 || position === 2) {
|
|
399
|
+
label.lineWidth -= distY / scale;
|
|
400
|
+
} else if (position === 6 || position === 8) {
|
|
401
|
+
label.lineWidth += distY / scale;
|
|
402
|
+
}
|
|
403
|
+
} else if (tool === FLAG) {
|
|
392
404
|
if (position === 4) {
|
|
393
405
|
_startPoint = {x: endPoint.x + distX, y: endPoint.y + distY};
|
|
394
406
|
_endPoint = {x: endPoint.x + distX, y: endPoint.y + distY};
|
|
@@ -396,6 +408,8 @@ export class Area extends ViewerCommon {
|
|
|
396
408
|
label.lineWidth -= distY / scale;
|
|
397
409
|
} else if (position === 6 || position === 8) {
|
|
398
410
|
label.lineWidth += distY / scale;
|
|
411
|
+
_endPoint = {x: endPoint.x, y: endPoint.y + distY};
|
|
412
|
+
_startPoint = {x: endPoint.x, y: endPoint.y + distY};
|
|
399
413
|
}
|
|
400
414
|
}
|
|
401
415
|
if (tool !== POLYGON) {
|
|
@@ -426,31 +440,35 @@ export class Area extends ViewerCommon {
|
|
|
426
440
|
* @param {string} type
|
|
427
441
|
*/
|
|
428
442
|
drawThumbPoint(points, type) {
|
|
443
|
+
if (this.options.thumb === false) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const thumbRadius = this.options.thumbRadius ?? 5;
|
|
429
447
|
if (LINE_TYPES.includes(type)) {
|
|
430
|
-
this.drawPoint(points[0], {thumbRadius
|
|
448
|
+
this.drawPoint(points[0], {thumbRadius});
|
|
431
449
|
this.drawPoint({
|
|
432
450
|
x: (points[0].x + points[1].x) / 2,
|
|
433
451
|
y: (points[0].y + points[1].y) / 2,
|
|
434
|
-
}, {thumbRadius:
|
|
435
|
-
this.drawPoint(points[1], {thumbRadius
|
|
452
|
+
}, {thumbRadius: thumbRadius + 2});
|
|
453
|
+
this.drawPoint(points[1], {thumbRadius});
|
|
436
454
|
} else if (REGION_TYPES.includes(type)) {
|
|
437
455
|
getRectPoint(points[0], points[1]).forEach((point) => {
|
|
438
|
-
this.drawPoint(point, {thumbRadius
|
|
456
|
+
this.drawPoint(point, {thumbRadius});
|
|
439
457
|
});
|
|
440
458
|
} else if (type === POLYGON) {
|
|
441
459
|
points.forEach((point) => {
|
|
442
460
|
if (point.canMove) {
|
|
443
|
-
this.drawPoint(point, {thumbRadius
|
|
461
|
+
this.drawPoint(point, {thumbRadius});
|
|
444
462
|
}
|
|
445
463
|
});
|
|
446
464
|
} else if (type === FONT || type === DOT) {
|
|
447
|
-
this.drawPoint(points[0], {thumbRadius
|
|
465
|
+
this.drawPoint(points[0], {thumbRadius});
|
|
448
466
|
} else if (type === STAR || type === FLAG) {
|
|
449
467
|
getRectPoint(points[0], points[1]).
|
|
450
468
|
filter((item, index) => index === 0 || index === 2 || index === 4 ||
|
|
451
469
|
index === 6 || index === 8).
|
|
452
470
|
forEach((point) => {
|
|
453
|
-
this.drawPoint(point, {thumbRadius
|
|
471
|
+
this.drawPoint(point, {thumbRadius});
|
|
454
472
|
});
|
|
455
473
|
}
|
|
456
474
|
}
|
|
@@ -533,7 +551,7 @@ export class Area extends ViewerCommon {
|
|
|
533
551
|
point.canMove = false;
|
|
534
552
|
label.points[index].canMove = false;
|
|
535
553
|
if (index === 0 || (!pointInOtherPoint(lastPoint, point, 30) &&
|
|
536
|
-
|
|
554
|
+
!pointInOtherPoint(movePoints[0], point, 30)) ||
|
|
537
555
|
(!label.isClose && index === movePoints.length - 1)) {
|
|
538
556
|
lastPoint = point;
|
|
539
557
|
point.canMove = true;
|
|
@@ -46,6 +46,12 @@ export class Board extends ViewerCommon {
|
|
|
46
46
|
* @param {string} options.tool
|
|
47
47
|
* @param {number} options.lineWidth
|
|
48
48
|
* @param {boolean} [options.measure=true] 绘画时显示信息
|
|
49
|
+
* @param {boolean} [options.clear=true] 是否结束绘画时清空画布
|
|
50
|
+
* @param {boolean} [options.isClose=true] 是否自动闭合曲线
|
|
51
|
+
* @param {boolean} [options.once=false] 是否绘画一次后自动结束
|
|
52
|
+
* @param {boolean} [options.isROI=false] 是否是感性区域
|
|
53
|
+
* @param {boolean} [options.move=true] 是否可移动
|
|
54
|
+
* @param {boolean} [options.resize=true] 是否可调整大小
|
|
49
55
|
*/
|
|
50
56
|
startDraw(options) {
|
|
51
57
|
if (!options.tool) {
|
|
@@ -276,8 +282,7 @@ export class Board extends ViewerCommon {
|
|
|
276
282
|
* @return {boolean}
|
|
277
283
|
*/
|
|
278
284
|
isInROI(point) {
|
|
279
|
-
return this.
|
|
280
|
-
this.isContainerLabel(point, this.ROIList) ||
|
|
285
|
+
return !this.options.ROI || this.isContainerLabel(point, this.ROIList) ||
|
|
281
286
|
this[this.tool].options.isROI;
|
|
282
287
|
}
|
|
283
288
|
|
|
@@ -29,7 +29,7 @@ export class Tailoring extends ViewerCommon {
|
|
|
29
29
|
this.color = '#FFF';
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
init({width, height, left, top, color}) {
|
|
32
|
+
init({width, height, left, top, color, now = false}) {
|
|
33
33
|
this.isInTailoring = true;
|
|
34
34
|
this.movePointIndex = -1;
|
|
35
35
|
const pointList = getRectPoint({x: left, y: top},
|
|
@@ -39,8 +39,13 @@ export class Tailoring extends ViewerCommon {
|
|
|
39
39
|
pointList[2],
|
|
40
40
|
pointList[6],
|
|
41
41
|
pointList[8]];
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
if (now) {
|
|
43
|
+
this.$emit(EVENT_TAILORING_SCREENSHOT, this.getScreenCanvasImage());
|
|
44
|
+
this.stopTailoring();
|
|
45
|
+
} else {
|
|
46
|
+
this.color = color || '#FFF';
|
|
47
|
+
this.change();
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
emitTailoringRegion() {
|
|
@@ -222,15 +227,10 @@ export class Tailoring extends ViewerCommon {
|
|
|
222
227
|
}
|
|
223
228
|
|
|
224
229
|
onCanvasDblClick(position) {
|
|
225
|
-
if (this.tailoringPoints.length
|
|
226
|
-
this.
|
|
227
|
-
} else {
|
|
228
|
-
if (this.isPointInMatrix(position)) {
|
|
229
|
-
this.$emit(EVENT_TAILORING_SCREENSHOT, this.getScreenCanvasImage());
|
|
230
|
-
} else {
|
|
231
|
-
this.stopTailoring();
|
|
232
|
-
}
|
|
230
|
+
if (this.tailoringPoints.length > 0 && this.isPointInMatrix(position)) {
|
|
231
|
+
this.$emit(EVENT_TAILORING_SCREENSHOT, this.getScreenCanvasImage());
|
|
233
232
|
}
|
|
233
|
+
this.stopTailoring();
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
/**
|
package/src/util/imageData.js
CHANGED
|
@@ -36,9 +36,9 @@ export const rgbToHsl = (r, g, b) => {
|
|
|
36
36
|
export const hslToRgb = (h, s, l) => {
|
|
37
37
|
if (s === 0) {
|
|
38
38
|
return {
|
|
39
|
-
r: l * 255,
|
|
40
|
-
g: l * 255,
|
|
41
|
-
b: l * 255,
|
|
39
|
+
r: (l > 1 ? 1 : l) * 255,
|
|
40
|
+
g: (l > 1 ? 1 : l) * 255,
|
|
41
|
+
b: (l > 1 ? 1 : l) * 255,
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
if (s > 1) s = 1;
|
|
@@ -52,7 +52,11 @@ export const hslToRgb = (h, s, l) => {
|
|
|
52
52
|
const r = 255 * hueToRGB(v1, v2, h + (1 / 3));
|
|
53
53
|
const g = 255 * hueToRGB(v1, v2, h);
|
|
54
54
|
const b = 255 * hueToRGB(v1, v2, h - (1 / 3));
|
|
55
|
-
return {
|
|
55
|
+
return {
|
|
56
|
+
r: r > 255 ? 255 : r,
|
|
57
|
+
g: g > 255 ? 255 : g,
|
|
58
|
+
b: b > 255 ? 255 : b,
|
|
59
|
+
};
|
|
56
60
|
};
|
|
57
61
|
|
|
58
62
|
function hueToRGB(v1, v2, h) {
|
|
@@ -72,14 +76,14 @@ export const toGamma = (num, gamma) => {
|
|
|
72
76
|
num = 0;
|
|
73
77
|
}
|
|
74
78
|
num = num / 255;
|
|
75
|
-
const compensate = Math.pow(num, gamma);
|
|
79
|
+
const compensate = Math.pow(num, 1 / gamma);
|
|
76
80
|
return compensate * 255;
|
|
77
81
|
};
|
|
78
82
|
|
|
79
83
|
const cacheGammaTable = {};
|
|
80
84
|
|
|
81
85
|
for (let i = 0; i < 256; i++) {
|
|
82
|
-
for (let j = 0.01; j <=
|
|
86
|
+
for (let j = 0.01; j <= 2; j = ((j + 0.01).toFixed(3) / 1)) {
|
|
83
87
|
if (cacheGammaTable[`${j}`]) {
|
|
84
88
|
cacheGammaTable[`${j}`].push(toGamma(i, j));
|
|
85
89
|
} else {
|
package/src/view.js
CHANGED
|
@@ -24,6 +24,8 @@ export default class KfbView extends EventEmitter {
|
|
|
24
24
|
* @param {Object} [config.navigator = {}] navigator参数
|
|
25
25
|
* @param {string=} config.navigator.style navigator样式
|
|
26
26
|
* @param {boolean=} config.navigator.disabled 是否禁用navigator
|
|
27
|
+
* @param {string} config.navigator.width navigator宽度
|
|
28
|
+
* @param {string} config.navigator.height navigator高度
|
|
27
29
|
* @param {string} config.navigator.thumbnail 缩略图地址
|
|
28
30
|
* @param {boolean=} config.navigator.vestige 是否显示缩略图浏览痕迹
|
|
29
31
|
* @param {number=} config.navigator.vestigeDelay 浏览痕迹颜色时间
|
|
@@ -35,6 +37,9 @@ export default class KfbView extends EventEmitter {
|
|
|
35
37
|
* @param {Object} config.area 交互区域,触发点击、拖动等事件
|
|
36
38
|
* @param {boolean=} config.area.disabled 是否禁用area
|
|
37
39
|
* @param {boolean=} config.area.drag 是否允许拖动
|
|
40
|
+
* @param {boolean=} config.area.thumb 选中区域时是否显示标注点
|
|
41
|
+
* @param {boolean=} config.area.thumbRadius 选中区域标注点的半径
|
|
42
|
+
* @param {boolean=} config.area.thumbColor 选中区域标注点的颜色
|
|
38
43
|
* @param {Object} config.rotation 旋转图像参数
|
|
39
44
|
* @param {boolean=} config.rotation.disabled 是否禁用旋转
|
|
40
45
|
* @param {Object} config.tailoring 裁剪图像参数
|
|
@@ -43,7 +48,7 @@ export default class KfbView extends EventEmitter {
|
|
|
43
48
|
* @param {boolean=} config.shape.disabled 是否禁用标注
|
|
44
49
|
* @param {Object} config.board 标注参数
|
|
45
50
|
* @param {boolean=} config.board.disabled 是否禁用绘制
|
|
46
|
-
* @param {boolean=} config.board.
|
|
51
|
+
* @param {boolean=} config.board.ROI 是否开启ROI,开启后只能在标注类型是ROI的区域内绘制图形
|
|
47
52
|
* @param {Object} config.graduation 刻度参数
|
|
48
53
|
* @param {boolean=} config.graduation.disabled 是否禁用刻度
|
|
49
54
|
* @param {boolean=} config.graduation.custom 是否自定义刻度,抛出graduation-change事件
|
|
@@ -99,6 +104,19 @@ export default class KfbView extends EventEmitter {
|
|
|
99
104
|
this.area?.setLabelList?.(this.labelList);
|
|
100
105
|
}
|
|
101
106
|
|
|
107
|
+
appendLabelList(list) {
|
|
108
|
+
this.labelList = [
|
|
109
|
+
...this.labelList, list.map((item) => new LabelModel({
|
|
110
|
+
...item,
|
|
111
|
+
region: item.region || pointsToRegion(item.points),
|
|
112
|
+
strokeStyle: item.strokeStyle || '#0000FF',
|
|
113
|
+
__data__: deepClone(item),
|
|
114
|
+
}))];
|
|
115
|
+
this.board?.setLabelList?.(this.labelList);
|
|
116
|
+
this.shape?.setLabelList?.(this.labelList);
|
|
117
|
+
this.area?.setLabelList?.(this.labelList);
|
|
118
|
+
}
|
|
119
|
+
|
|
102
120
|
/**
|
|
103
121
|
* 重置绘图大小
|
|
104
122
|
* @param {number} width
|