kfb-view 2.1.15 → 2.1.18

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kfb-view",
3
3
  "description": "一个在线kfb的阅片软件",
4
- "version": "2.1.15",
4
+ "version": "2.1.18",
5
5
  "author": "qifeng.fan <qifeng.fan@hzztai.com>",
6
6
  "license": "MIT",
7
7
  "main": "lib/kfb-view.js",
@@ -71,29 +71,40 @@ export class ViewerCommon extends EventEmitter {
71
71
  * @return {boolean}
72
72
  */
73
73
  isContainerLabel(point, list) {
74
- const contain = list.find(({region, tool, points, isClose}) => {
75
- const p1 = {x: region.x, y: region.y};
76
- const p2 = {x: region.x + region.width, y: region.y};
77
- const p3 = {x: region.x, y: region.y + region.height};
78
- const p4 = {x: region.x + region.width, y: region.y + region.height};
79
- const center = {
80
- x: region.x + region.width / 2, y: region.y + region.height / 2,
81
- };
82
- if (tool === ELLIPSE) {
83
- return isPointInEllipse(point, center, Math.abs(region.width / 2),
84
- Math.abs(region.height / 2 >> 0));
85
- }
86
- if (tool === RECTANGLE) {
87
- return isPointInMatrix(p1, p2, p3, p4, point);
88
- }
89
- if (tool === POLYGON && isClose) {
90
- return isPointInPolygon(point, points);
91
- }
92
- return false;
93
- });
74
+ const contain = list.find((item) => this.isContainerInRegion(point, item));
94
75
  return !!contain;
95
76
  }
96
77
 
78
+ /**
79
+ * 判断点是否在某个区域内
80
+ * @param {Object} point
81
+ * @param {Object} region
82
+ * @param {String} tool
83
+ * @param {Array} points
84
+ * @param {boolean} isClose
85
+ * @return {boolean}
86
+ */
87
+ isContainerInRegion(point, {region, tool, points, isClose}) {
88
+ const p1 = {x: region.x, y: region.y};
89
+ const p2 = {x: region.x + region.width, y: region.y};
90
+ const p3 = {x: region.x, y: region.y + region.height};
91
+ const p4 = {x: region.x + region.width, y: region.y + region.height};
92
+ const center = {
93
+ x: region.x + region.width / 2, y: region.y + region.height / 2,
94
+ };
95
+ if (tool === ELLIPSE) {
96
+ return isPointInEllipse(point, center, Math.abs(region.width / 2),
97
+ Math.abs(region.height / 2 >> 0));
98
+ }
99
+ if (tool === RECTANGLE) {
100
+ return isPointInMatrix(p1, p2, p3, p4, point);
101
+ }
102
+ if (tool === POLYGON && isClose) {
103
+ return isPointInPolygon(point, points);
104
+ }
105
+ return false;
106
+ }
107
+
97
108
  /**
98
109
  * 转化图像区域到元素坐标区域
99
110
  * @param {number} x
@@ -149,10 +160,14 @@ export class ViewerCommon extends EventEmitter {
149
160
  * @return {{}[]}
150
161
  */
151
162
  imageToViewerElementPoints(points) {
152
- return (points || []).map((point) => ({
153
- ...point,
154
- ...this.imageToViewerElementCoordinates(point.x, point.y),
155
- }));
163
+ return (points || []).map((point) => {
164
+ const p = this.imageToViewerElementCoordinates(point.x, point.y);
165
+ return {
166
+ canMove: point.canMove,
167
+ x: p.x,
168
+ y: p.y,
169
+ };
170
+ });
156
171
  }
157
172
 
158
173
  /**
@@ -372,12 +387,17 @@ export class ViewerCommon extends EventEmitter {
372
387
  /**
373
388
  * 判断region是否在canvas中
374
389
  * @param {Object} region
390
+ * @param {boolean} status
375
391
  * @return {boolean}
376
392
  */
377
- isInCanvas(region) {
378
- const startPoint = this.imageToViewerElementCoordinates(region.x, region.y);
379
- const endPoint = this.imageToViewerElementCoordinates(
380
- region.x + region.width, region.y + region.height);
393
+ isInCanvas(region, status = false) {
394
+ const startPoint = status ?
395
+ {x: region.x, y: region.y} :
396
+ this.imageToViewerElementCoordinates(region.x, region.y);
397
+ const endPoint = status ?
398
+ {x: region.x + region.width, y: region.y + region.height} :
399
+ this.imageToViewerElementCoordinates(
400
+ region.x + region.width, region.y + region.height);
381
401
  if (endPoint.x < startPoint.x) {
382
402
  const x = startPoint.x;
383
403
  startPoint.x = endPoint.x;
@@ -1,6 +1,6 @@
1
1
  import {
2
- HAS_REGION_TYPES, MARKS,
3
- NO_NORMAL_REGION_TYPES, POINT_TYPES, POLYGON, REGION_TYPES,
2
+ HAS_REGION_TYPES,
3
+ MARKS, NO_NORMAL_REGION_TYPES, POINT_TYPES, POLYGON, REGION_TYPES,
4
4
  } from '../../const/mark';
5
5
  import {ViewerCommon} from '../common/common';
6
6
  import * as Tools from '../../tool';
@@ -58,21 +58,30 @@ export class Shape extends ViewerCommon {
58
58
  change() {
59
59
  this.clearCanvas();
60
60
  // 区域标注列表
61
- const regionLabelList = this.labelList.filter(
62
- ({tool, isClose}) => REGION_TYPES.includes(tool) || isClose && tool ===
63
- POLYGON).
64
- map((item) => ({
65
- ...item,
66
- child: [],
67
- self: item,
68
- }));
61
+ const regionLabelList = [];
62
+ this.labelList.forEach(
63
+ (item) => {
64
+ if (REGION_TYPES.includes(item.tool) || item.isClose && item.tool ===
65
+ POLYGON) {
66
+ regionLabelList.push({
67
+ ...item,
68
+ child: [],
69
+ self: item,
70
+ });
71
+ }
72
+ });
69
73
  // strokeStyle, lineWidth, fillStyle 相同认为是一个路径下的图形,一起绘制,优化性能
70
74
  const sameFixWidthLabel = {}; // star, flag, star, font lineWidth固定为2
71
75
  const sameNormalLabel = {};
72
76
  this.labelList.forEach((item) => {
73
- if (!this.isInCanvas(item.region)) return;
74
77
  if (item.show === false) return;
75
78
  if (!this[item.tool]) return;
79
+ if (!this.isInCanvas(item.region)) return;
80
+ /* const point = this.imageToViewerElementCoordinates(item.points[0].x,
81
+ item.points[0].y);
82
+ if ((point.x > this.canvas.width ||
83
+ point.y > this.canvas.height ||
84
+ point.x < 0 || point.y < 0)) return;*/
76
85
  const key = `${item.strokeStyle ?? ''}_${item.lineWidth ??
77
86
  ''}_${item.fillStyle ?? ''}`;
78
87
  const regionKey = `${item.strokeStyle ?? ''}_${item.lineWidth ?? ''}`;
@@ -90,37 +99,48 @@ export class Shape extends ViewerCommon {
90
99
  }
91
100
  }
92
101
  const parent = regionLabelList.find(
93
- (parent) => parent.self !== item && item.points.every(
94
- (point) => this.isContainerLabel(point, [parent])));
102
+ (parent) => HAS_REGION_TYPES.includes(parent.tool) && parent.self !==
103
+ item && item.points.every(
104
+ (point) => this.isContainerInRegion(point, parent)));
95
105
  if (parent) {
96
106
  parent.child.push(item);
97
107
  }
98
108
  });
109
+ const ctx = this.canvas.getContext('2d');
99
110
  Object.values(sameFixWidthLabel).forEach((labels) => {
100
- const ctx = this.canvas.getContext('2d');
101
111
  ctx.beginPath();
102
112
  labels.forEach((item) => {
103
113
  this.drawLabel(item);
104
114
  });
105
- ctx.stroke();
106
- if (labels?.[0]?.fillStyle) {
115
+ const firstLabel = labels?.[0];
116
+ if (firstLabel?.fillStyle) {
117
+ ctx.fillStyle = firstLabel.fillStyle;
107
118
  ctx.fill();
108
119
  }
120
+ ctx.strokeStyle = firstLabel.strokeStyle;
121
+ ctx.stroke();
109
122
  });
110
123
  Object.values(sameNormalLabel).forEach((labels) => {
111
- const ctx = this.canvas.getContext('2d');
112
124
  ctx.beginPath();
113
125
  labels.forEach((item) => {
114
126
  this.drawLabel(item);
115
127
  });
128
+ const firstLabel = labels?.[0];
129
+ ctx.lineWidth = firstLabel.lineWidth;
130
+ ctx.strokeStyle = firstLabel.strokeStyle;
116
131
  ctx.stroke();
117
132
  });
118
133
 
119
134
  regionLabelList.forEach((item) => {
120
- if (!this.isInCanvas(item.region)) return;
121
135
  if (item.show === false) return;
122
136
  if (!this[item.tool]) return;
123
- this.combination.setContent(this.canvas, {...item});
137
+ if (!this.isInCanvas(item.region)) return;
138
+ /* const point = this.imageToViewerElementCoordinates(item.points[0].x,
139
+ item.points[0].y);
140
+ if ((point.x > this.canvas.width ||
141
+ point.y > this.canvas.height ||
142
+ point.x < 0 || point.y < 0)) return;*/
143
+ this.combination.setContent(this.canvas, item);
124
144
  this.combination.draw({
125
145
  points: this.imageToViewerElementPoints(item.points),
126
146
  tool: item.tool,
@@ -132,13 +152,13 @@ export class Shape extends ViewerCommon {
132
152
  }
133
153
 
134
154
  drawLabel(item) {
135
- const scale = this.getImageZoom(true) / item.scale;
136
155
  const points = this.imageToViewerElementPoints(item.points);
137
- this[item.tool].setContent(this.canvas, {...item});
156
+ this[item.tool].setContent(this.canvas, item);
138
157
  if (!NO_NORMAL_REGION_TYPES.includes(item.tool)) {
139
158
  this[item.tool].draw(points, this.viewport.getRotation(),
140
159
  this.imageToViewerElementRectangle(item.region));
141
160
  } else {
161
+ const scale = this.getImageZoom(true) / item.scale;
142
162
  this[item.tool].draw(points, scale);
143
163
  }
144
164
  }
@@ -11,7 +11,7 @@ export class LabelModel {
11
11
  this.strokeStyle = data.strokeStyle || '#027AFF'; // 标注颜色
12
12
  this.fillStyle = data.fillStyle; // 填充颜色
13
13
  this.description = data.description; // 描述
14
- this.fontSize = data.fontSize; // 字号
14
+ this.fontSize = data.fontSize || 14; // 字号
15
15
  this.text = data.text; // 文字
16
16
  this.angle = data.angle ?? 0; // 旋转角度
17
17
  this.measure = data.measure; // 是否显示测量信息
package/src/tool/Brush.js CHANGED
@@ -21,9 +21,7 @@ class Brush {
21
21
  setContent(canvas, options) {
22
22
  this.canvas = canvas;
23
23
  this.thumb.setCanvas(canvas);
24
- this.options = {
25
- ...options,
26
- };
24
+ this.options = options;
27
25
  }
28
26
 
29
27
  startDraw() {
package/src/tool/Font.js CHANGED
@@ -24,13 +24,12 @@ class Font extends Brush {
24
24
  const angle = this.options.angle || 0;
25
25
  const text = this.options.text || '编辑文字';
26
26
  const ctx = this.canvas.getContext('2d');
27
- ctx.fillStyle = this.options.fillStyle || this.options.strokeStyle ||
28
- '#FDFDFD';
27
+ ctx.fillStyle = this.options.strokeStyle;
29
28
  ctx.save();
30
29
  ctx.translate(point.x, point.y);
31
30
  ctx.rotate(angle / 180 * Math.PI);
32
31
  ctx.scale(scale, scale);
33
- ctx.font = `${this.options.fontSize || 14}px Arial`;
32
+ ctx.font = `${this.options.fontSize}px Arial`;
34
33
  ctx.fillText(text, 0, 0);
35
34
  ctx.restore();
36
35
  }
package/src/tool/Star.js CHANGED
@@ -24,7 +24,6 @@ class Star extends Brush {
24
24
  let dist = this.options.lineWidth;
25
25
  const point = points[0];
26
26
  dist *= scale;
27
- this.endPoint = {x: point.x, y: point.y};
28
27
  const angle = 36 / 180 * Math.PI;
29
28
  const angle1 = 54 / 180 * Math.PI;
30
29
  const long_side = Math.sin(angle) * dist * 2;
@@ -60,7 +60,6 @@ CanvasRenderingContext2D.prototype.drawOval = function drawOval(
60
60
  this.save();
61
61
  // 选择a、b中的较大者作为arc方法的半径参数
62
62
  const r = (a > b) ? a : b;
63
- console.log(r);
64
63
  const ratioX = a / r; // 横轴缩放比率
65
64
  const ratioY = b / r; // 纵轴缩放比率
66
65
  this.scale(ratioX, ratioY); // 进行缩放(均匀压缩)
package/src/view.js CHANGED
@@ -96,7 +96,6 @@ export default class KfbView extends EventEmitter {
96
96
  this.labelList = list.map((item) => new LabelModel({
97
97
  ...item,
98
98
  region: item.region || pointsToRegion(item.points),
99
- strokeStyle: item.strokeStyle || '#0000FF',
100
99
  __data__: deepClone(item),
101
100
  }));
102
101
  this.board?.setLabelList?.(this.labelList);
@@ -106,10 +105,9 @@ export default class KfbView extends EventEmitter {
106
105
 
107
106
  appendLabelList(list) {
108
107
  this.labelList = [
109
- ...this.labelList, list.map((item) => new LabelModel({
108
+ ...this.labelList, ...list.map((item) => new LabelModel({
110
109
  ...item,
111
110
  region: item.region || pointsToRegion(item.points),
112
- strokeStyle: item.strokeStyle || '#0000FF',
113
111
  __data__: deepClone(item),
114
112
  }))];
115
113
  this.board?.setLabelList?.(this.labelList);
package/test.html CHANGED
@@ -7,7 +7,7 @@
7
7
  <body>
8
8
 
9
9
  <canvas id="canvas" width="800" height="600"></canvas>
10
-
10
+ <button id="reDraw">重绘</button>
11
11
  <script>
12
12
  /**
13
13
  * 清除圆形区域
@@ -206,109 +206,40 @@
206
206
  </script>
207
207
  <script>
208
208
  const canvas = document.getElementById('canvas');
209
+ const reDrawBtn = document.getElementById('reDraw');
209
210
  const ctx = canvas.getContext('2d');
210
- ctx.beginPath();
211
-
212
- drawA([{x: 10, y: 10}, {x: 50, y: 40}]);
213
- drawA([{x: 70, y: 70}, {x: 120, y: 120}]);
214
-
215
- drawB([{x: 130, y: 130}, {x: 90, y: 60}]);
216
- drawB([{x: 20, y: 20}, {x: 20, y: 90}]);
217
- drawF([{x: 300, y: 200}]);
218
- drawF([{x: 100, y: 500}]);
219
-
220
- function drawA(points) {
221
- const startPoint = points[0];
222
- const endPoint = points[points.length - 1];
223
- ctx.lineWidth = 2;
224
- ctx.strokeStyle = '#0000FF';
225
- ctx.moveTo(startPoint.x, startPoint.y);
226
- ctx.lineTo(endPoint.x, endPoint.y);
227
- ctx.drawArrow(startPoint, endPoint);
228
- ctx.stroke();
229
- }
230
211
 
231
- function drawB(points) {
232
- const startPoint = points[0];
233
- const endPoint = points[points.length - 1];
234
- ctx.lineWidth = 2;
235
- ctx.strokeStyle = '#00FF00';
236
- ctx.moveTo(startPoint.x, startPoint.y);
237
- ctx.lineTo(endPoint.x, endPoint.y);
238
- ctx.drawArrow(startPoint, endPoint);
239
- ctx.drawArrow(endPoint, startPoint);
240
- ctx.stroke();
241
- }
242
-
243
- function drawF(points, scale = 1) {
244
- let dist = 30;
245
- dist *= scale;
212
+ function drwaP(points) {
213
+ let dist = 4 * 1;
246
214
  const point = points[0];
215
+ const ctx = canvas.getContext('2d');
216
+ const {x, y} = point;
247
217
  ctx.lineWidth = 2;
248
- ctx.strokeStyle = '#0000FF';
249
- ctx.moveTo(point.x, point.y);
250
- ctx.lineTo(point.x, point.y - dist);
251
- const _dist = dist / 5;
252
- const p1 = {
253
- x: point.x + _dist,
254
- y: point.y - dist,
255
- };
256
- const p2 = {
257
- x: point.x + _dist * 2,
258
- y: point.y - dist - _dist,
259
- };
260
- const p3 = {
261
- x: point.x + _dist * 4,
262
- y: point.y - dist + _dist,
263
- };
264
- const p4 = {
265
- x: point.x + dist,
266
- y: point.y - dist,
267
- };
268
- ctx.bezierCurve([p1, p2, p3, p4]);
269
- ctx.moveTo(p4.x, p4.y);
270
- ctx.lineTo(p4.x, p4.y + dist / 2);
271
- const p11 = {
272
- x: point.x + _dist,
273
- y: point.y - dist / 2,
274
- };
275
- const p22 = {
276
- x: point.x + _dist * 2,
277
- y: point.y - dist / 2 - _dist,
278
- };
279
- const p33 = {
280
- x: point.x + _dist * 4,
281
- y: point.y - dist / 2 + _dist,
282
- };
283
- const p44 = {
284
- x: point.x + dist,
285
- y: point.y - dist / 2,
286
- };
287
- ctx.bezierCurve([p11, p22, p33, p44]);
288
- ctx.moveTo(p1.x, p1.y);
289
- ctx.lineTo(p11.x, p11.y);
290
- ctx.stroke();
218
+ ctx.moveTo(x + dist, y);
219
+ ctx.arc(x, y, dist, 0, Math.PI * 2, !1);
291
220
  }
292
221
 
293
- console.log(new Date().getTime());
294
- console.time('draw');
222
+ ctx.beginPath();
295
223
  ctx.fillStyle = '#ff0000';
296
224
  ctx.strokeStyle = '#00ff00';
297
225
  ctx.lineWidth = 2;
298
- ctx.beginPath();
299
- for (let i = 0; i < 800; i++) {
300
- for (let j = 0; j < 600; j++) {
301
- if (i % 50 === 0 && j % 50 === 0) {
302
- ctx.moveTo(i + 4, j);
303
- ctx.arc(i, j, 4, 0, Math.PI * 2, !1);
304
- }
305
- }
226
+ for (let i = 0; i < 4000; i++) {
227
+ drwaP([{x: Math.random() * 800, y: Math.random() * 600}]);
306
228
  }
307
- ctx.fill();
308
229
  ctx.stroke();
309
- console.timeEnd('draw');
310
- console.log(new Date().getTime());
311
-
230
+ reDrawBtn.addEventListener('click', (e) => {
231
+ ctx.clearRect(0, 0, 800, 600);
232
+ console.time('draw');
233
+ ctx.beginPath();
234
+ ctx.fillStyle = '#ff0000';
235
+ ctx.strokeStyle = '#00ff00';
236
+ ctx.lineWidth = 2;
237
+ for (let i = 0; i < 10000; i++) {
238
+ drwaP([{x: Math.random() * 800, y: Math.random() * 600}]);
239
+ }
240
+ ctx.stroke();
241
+ console.timeEnd('draw');
242
+ });
312
243
 
313
244
  </script>
314
245
  </body>