med-viewer-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +253 -0
  2. package/dist/adapters/vue/MedViewer.d.ts +17 -0
  3. package/dist/adapters/vue/index.d.ts +2 -0
  4. package/dist/core/AnnoAnnotator.d.ts +15 -0
  5. package/dist/core/BaseAnnotator.d.ts +33 -0
  6. package/dist/core/ColorAdjustPlugin.d.ts +29 -0
  7. package/dist/core/Coords.d.ts +6 -0
  8. package/dist/core/Engine.d.ts +57 -0
  9. package/dist/core/KonvaAnnotator.d.ts +36 -0
  10. package/dist/core/Scalebar.d.ts +42 -0
  11. package/dist/core/SelectionPlugin.d.ts +102 -0
  12. package/dist/core/Toolbar.d.ts +32 -0
  13. package/dist/med-viewer-sdk.d.ts +6 -0
  14. package/dist/med-viewer-sdk.mjs +14248 -0
  15. package/dist/med-viewer-sdk.umd.js +2 -0
  16. package/dist/style.css +1 -0
  17. package/package.json +34 -0
  18. package/src/adapters/vue/MedViewer.ts +37 -0
  19. package/src/adapters/vue/index.ts +4 -0
  20. package/src/assets/icons/button_grouphover.png +0 -0
  21. package/src/assets/icons/button_hover.png +0 -0
  22. package/src/assets/icons/button_pressed.png +0 -0
  23. package/src/assets/icons/button_rest.png +0 -0
  24. package/src/assets/icons/flip_grouphover.png +0 -0
  25. package/src/assets/icons/flip_hover.png +0 -0
  26. package/src/assets/icons/flip_pressed.png +0 -0
  27. package/src/assets/icons/flip_rest.png +0 -0
  28. package/src/assets/icons/fullpage_grouphover.png +0 -0
  29. package/src/assets/icons/fullpage_hover.png +0 -0
  30. package/src/assets/icons/fullpage_pressed.png +0 -0
  31. package/src/assets/icons/fullpage_rest.png +0 -0
  32. package/src/assets/icons/home_grouphover.png +0 -0
  33. package/src/assets/icons/home_hover.png +0 -0
  34. package/src/assets/icons/home_pressed.png +0 -0
  35. package/src/assets/icons/home_rest.png +0 -0
  36. package/src/assets/icons/next_grouphover.png +0 -0
  37. package/src/assets/icons/next_hover.png +0 -0
  38. package/src/assets/icons/next_pressed.png +0 -0
  39. package/src/assets/icons/next_rest.png +0 -0
  40. package/src/assets/icons/previous_grouphover.png +0 -0
  41. package/src/assets/icons/previous_hover.png +0 -0
  42. package/src/assets/icons/previous_pressed.png +0 -0
  43. package/src/assets/icons/previous_rest.png +0 -0
  44. package/src/assets/icons/rotateleft_grouphover.png +0 -0
  45. package/src/assets/icons/rotateleft_hover.png +0 -0
  46. package/src/assets/icons/rotateleft_pressed.png +0 -0
  47. package/src/assets/icons/rotateleft_rest.png +0 -0
  48. package/src/assets/icons/rotateright_grouphover.png +0 -0
  49. package/src/assets/icons/rotateright_hover.png +0 -0
  50. package/src/assets/icons/rotateright_pressed.png +0 -0
  51. package/src/assets/icons/rotateright_rest.png +0 -0
  52. package/src/assets/icons/selection_cancel_grouphover.png +0 -0
  53. package/src/assets/icons/selection_cancel_hover.png +0 -0
  54. package/src/assets/icons/selection_cancel_pressed.png +0 -0
  55. package/src/assets/icons/selection_cancel_rest.png +0 -0
  56. package/src/assets/icons/selection_confirm_grouphover.png +0 -0
  57. package/src/assets/icons/selection_confirm_hover.png +0 -0
  58. package/src/assets/icons/selection_confirm_pressed.png +0 -0
  59. package/src/assets/icons/selection_confirm_rest.png +0 -0
  60. package/src/assets/icons/selection_grouphover.png +0 -0
  61. package/src/assets/icons/selection_hover.png +0 -0
  62. package/src/assets/icons/selection_pressed.png +0 -0
  63. package/src/assets/icons/selection_rest.png +0 -0
  64. package/src/assets/icons/tool_anno.png +0 -0
  65. package/src/assets/icons/tool_selection.png +0 -0
  66. package/src/assets/icons/zoomin_grouphover.png +0 -0
  67. package/src/assets/icons/zoomin_hover.png +0 -0
  68. package/src/assets/icons/zoomin_pressed.png +0 -0
  69. package/src/assets/icons/zoomin_rest.png +0 -0
  70. package/src/assets/icons/zoomout_grouphover.png +0 -0
  71. package/src/assets/icons/zoomout_hover.png +0 -0
  72. package/src/assets/icons/zoomout_pressed.png +0 -0
  73. package/src/assets/icons/zoomout_rest.png +0 -0
  74. package/src/core/AnnoAnnotator.ts +102 -0
  75. package/src/core/BaseAnnotator.ts +43 -0
  76. package/src/core/ColorAdjustPlugin.ts +256 -0
  77. package/src/core/Coords.ts +9 -0
  78. package/src/core/Engine.ts +246 -0
  79. package/src/core/KonvaAnnotator.ts +185 -0
  80. package/src/core/Scalebar.ts +87 -0
  81. package/src/core/SelectionPlugin.ts +252 -0
  82. package/src/core/Toolbar.ts +370 -0
  83. package/src/index.ts +21 -0
  84. package/src/plugins/ShapeLabelsFormatter.js +435 -0
  85. package/src/plugins/openseadragon-scalebar.js +592 -0
  86. package/src/plugins/openseadragon-selection.js +657 -0
  87. package/src/types/type.d.ts +9 -0
@@ -0,0 +1,435 @@
1
+ const pathDataParser = require("path-data-parser");
2
+ import { svgPathProperties } from "svg-path-properties";
3
+
4
+ import i18n from "@/lang";
5
+ function getWithUnit(value, unitSuffix) {
6
+ // if (value < 0.000001) {
7
+ // return (value * 1000000000).toFixed(2) + "n" + unitSuffix;
8
+ // }
9
+ // if (value < 0.001) {
10
+ return value.toFixed(2) + "μ" + unitSuffix;
11
+ // }
12
+ // if (value < 1) {
13
+ // return (value * 1000).toFixed(2) + "m" + unitSuffix;
14
+ // }
15
+ // if (value >= 1000) {
16
+ // return (value / 1000).toFixed(2) + "k" + unitSuffix;
17
+ // }
18
+ // return value + " " + unitSuffix;
19
+ }
20
+ function pixelsToPerMeter(value, config) {
21
+ let nweValue = value / config.scalebarInstance.pixelsPerMeter;
22
+
23
+ return nweValue * 1000000;
24
+ }
25
+
26
+ const ShapeLabelsFormatter = (config, ShowMeasure) => (annotation) => {
27
+ const bodies = Array.isArray(annotation.body)
28
+ ? annotation.body
29
+ : [annotation.body];
30
+
31
+ let toolName = annotation.target.renderedVia?.name;
32
+ if (!ShowMeasure) {
33
+ toolName = null;
34
+ }
35
+
36
+ const foreignObject = document.createElementNS(
37
+ "http://www.w3.org/2000/svg",
38
+ "foreignObject",
39
+ );
40
+ foreignObject.setAttribute("width", "1px");
41
+ foreignObject.setAttribute("height", "1px");
42
+ const firstTag = bodies.find((b) => b.purpose == "commenting");
43
+
44
+ switch (toolName) {
45
+ case "line":
46
+ let lineDiv = document.createElement("div");
47
+ lineDiv.innerHTML = annotation.target.selector.value;
48
+ let line = lineDiv.getElementsByTagName("line")[0];
49
+ let x1 = pixelsToPerMeter(Number(line.getAttribute("x1")), config);
50
+ let y1 = pixelsToPerMeter(Number(line.getAttribute("y1")), config);
51
+ let x2 = pixelsToPerMeter(Number(line.getAttribute("x2")), config);
52
+ let y2 = pixelsToPerMeter(Number(line.getAttribute("y2")), config);
53
+ let len = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
54
+ // realLen = getWithUnit((len / config.scalebarInstance.pixelsPerMeter), 'm');
55
+ if (firstTag) {
56
+ foreignObject.innerHTML = `
57
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
58
+ <div class="a9s-shape-label" >
59
+ <p >
60
+ ${i18n.t(`length`)}:&nbsp;&nbsp;${getWithUnit(
61
+ len,
62
+ "m",
63
+ )}&nbsp;&nbsp; </p> <p >
64
+ ${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
65
+ </p>
66
+ </div>
67
+ </div>`;
68
+ } else {
69
+ foreignObject.innerHTML = `
70
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
71
+
72
+ <div class="a9s-shape-label" >
73
+ <p>
74
+ ${i18n.t(`length`)}:&nbsp;&nbsp;${getWithUnit(len, "m")}&nbsp;&nbsp;
75
+ </p>
76
+ </div>
77
+ </div>`;
78
+ }
79
+
80
+ break;
81
+ case "rect":
82
+ let reg = new RegExp("xywh=pixel:", "g");
83
+ let str = annotation.target.selector.value.replace(reg, "");
84
+ let point = str.split(",");
85
+
86
+ const rectWidth = pixelsToPerMeter(Number(point[2]), config); // 请根据你的实际情况替换为正确的半径值
87
+ const rectHeight = pixelsToPerMeter(Number(point[3]), config); // 替换为正确的高度值
88
+
89
+ // 计算${i18n.t(`perimeter`)}
90
+ const rectPerimeter = 2 * (rectWidth + rectHeight);
91
+
92
+ // 计算${i18n.t(`area`)}
93
+ const rectArea = rectWidth * rectHeight;
94
+
95
+ if (firstTag) {
96
+ foreignObject.innerHTML = `
97
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
98
+
99
+ <div class="a9s-shape-label">
100
+ <p>
101
+ ${i18n.t(`width`)}:&nbsp;&nbsp;${getWithUnit(
102
+ rectWidth,
103
+ "m",
104
+ )}&nbsp;&nbsp;</p> <p>
105
+
106
+
107
+ ${i18n.t(`height`)}:&nbsp;&nbsp;${getWithUnit(
108
+ rectHeight,
109
+ "m",
110
+ )}&nbsp;&nbsp;</p> <p>
111
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
112
+ rectPerimeter,
113
+ "m",
114
+ )}&nbsp;&nbsp;</p> <p>
115
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
116
+ rectArea,
117
+ "m²",
118
+ )}&nbsp;&nbsp;</p> <p>
119
+ ${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
120
+ </p>
121
+ </div>
122
+ </div>`;
123
+ } else {
124
+ foreignObject.innerHTML = `
125
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
126
+ <div class="a9s-shape-label">
127
+ <p >
128
+ ${i18n.t(`width`)}:&nbsp;&nbsp;${getWithUnit(
129
+ rectWidth,
130
+ "m",
131
+ )}&nbsp;&nbsp;</p> <p>
132
+ ${i18n.t(`height`)}:&nbsp;&nbsp;${getWithUnit(
133
+ rectHeight,
134
+ "m",
135
+ )}&nbsp;&nbsp;</p> <p>
136
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
137
+ rectPerimeter,
138
+ "m",
139
+ )}&nbsp;&nbsp;</p> <p>
140
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(rectArea, "m²")}&nbsp;&nbsp;
141
+ </p>
142
+ </div>
143
+ </div>`;
144
+ }
145
+ break;
146
+ case "circle":
147
+ let circleDiv = document.createElement("div");
148
+ circleDiv.innerHTML = annotation.target.selector.value;
149
+ let circle = circleDiv.getElementsByTagName("circle")[0];
150
+ const circleRadius = pixelsToPerMeter(
151
+ Number(circle.getAttribute("r")),
152
+ config,
153
+ ); // 请根据你的实际情况替换为正确的半径值
154
+
155
+ // 计算${i18n.t(`perimeter`)}
156
+ const circleCircumference = 2 * Math.PI * circleRadius;
157
+ // 计算${i18n.t(`area`)}
158
+ const circleArea = Math.PI * Math.pow(circleRadius, 2);
159
+
160
+ if (firstTag) {
161
+ foreignObject.innerHTML = `
162
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
163
+
164
+ <div class="a9s-shape-label">
165
+ <p>
166
+ ${i18n.t(`radius`)}:&nbsp;&nbsp;${getWithUnit(
167
+ circleRadius,
168
+ "m",
169
+ )}&nbsp;&nbsp;</p><p>
170
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
171
+ circleCircumference,
172
+ "m",
173
+ )}&nbsp;&nbsp;</p><p>
174
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
175
+ circleArea,
176
+ "m²",
177
+ )}&nbsp;&nbsp;</p><p>
178
+ ${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
179
+ </p>
180
+ </div>
181
+ </div>`;
182
+ } else {
183
+ foreignObject.innerHTML = `
184
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
185
+ <div class="a9s-shape-label">
186
+ <p>
187
+ ${i18n.t(`radius`)}:&nbsp;&nbsp;${getWithUnit(
188
+ circleRadius,
189
+ "m",
190
+ )}&nbsp;&nbsp;</p><p>
191
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
192
+ circleCircumference,
193
+ "m",
194
+ )}&nbsp;&nbsp;</p><p>
195
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
196
+ circleArea,
197
+ "m²",
198
+ )}&nbsp;&nbsp;
199
+
200
+ </p>
201
+ </div>
202
+ </div>`;
203
+ }
204
+
205
+ break;
206
+ case "ellipse":
207
+ let ellipseDiv = document.createElement("div");
208
+ ellipseDiv.innerHTML = annotation.target.selector.value;
209
+ let ellipse = ellipseDiv.getElementsByTagName("ellipse")[0];
210
+
211
+ let rx = pixelsToPerMeter(Number(ellipse.getAttribute("rx")), config);
212
+ let ry = pixelsToPerMeter(Number(ellipse.getAttribute("ry")), config);
213
+ let majorAxis = null;
214
+ let minorAxis = null;
215
+ if (rx >= ry) {
216
+ majorAxis = rx;
217
+ minorAxis = ry;
218
+ } else {
219
+ majorAxis = ry;
220
+ minorAxis = rx;
221
+ }
222
+ const ellipsePerimeter =
223
+ Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
224
+
225
+ // 计算${i18n.t(`area`)}
226
+ const ellipseArea = Math.PI * rx * ry;
227
+ if (firstTag) {
228
+ foreignObject.innerHTML = `
229
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
230
+ <div class="a9s-shape-label">
231
+ <p>
232
+ ${i18n.t(`majorAxis`)}:&nbsp;&nbsp;${getWithUnit(
233
+ majorAxis,
234
+ "m",
235
+ )}&nbsp;&nbsp;</p> <p>
236
+
237
+ ${i18n.t(`minorAxis`)}:&nbsp;&nbsp;${getWithUnit(
238
+ minorAxis,
239
+ "m",
240
+ )}&nbsp;&nbsp;</p> <p>
241
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
242
+ ellipsePerimeter,
243
+ "m",
244
+ )}&nbsp;&nbsp;</p> <p>
245
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
246
+ ellipseArea,
247
+ "m²",
248
+ )}&nbsp;&nbsp;</p> <p>
249
+ ${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
250
+ </p>
251
+ </div>
252
+ </div>`;
253
+ } else {
254
+ foreignObject.innerHTML = `
255
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
256
+ <div class="a9s-shape-label">
257
+ <p>
258
+ ${i18n.t(`majorAxis`)}:&nbsp;&nbsp;${getWithUnit(
259
+ majorAxis,
260
+ "m",
261
+ )}&nbsp;&nbsp;</p><p>
262
+
263
+ ${i18n.t(`minorAxis`)}:&nbsp;&nbsp;${getWithUnit(
264
+ minorAxis,
265
+ "m",
266
+ )}&nbsp;&nbsp;</p><p>
267
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
268
+ ellipsePerimeter,
269
+ "m",
270
+ )}&nbsp;&nbsp;</p><p>
271
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
272
+ ellipseArea,
273
+ "m²",
274
+ )}&nbsp;&nbsp;
275
+ </p>
276
+ </div>
277
+ </div>`;
278
+ }
279
+
280
+ break;
281
+ case "polygon":
282
+ let polygonDiv = document.createElement("div");
283
+ polygonDiv.innerHTML = annotation.target.selector.value;
284
+
285
+ let polygon = polygonDiv.getElementsByTagName("polygon")[0];
286
+ let pointsAttribute = polygon.getAttribute("points");
287
+ const points = pointsAttribute.split(" ").map((point) => {
288
+ const [x, y] = point.split(",").map(parseFloat);
289
+ return {
290
+ x: pixelsToPerMeter(x, config),
291
+ y: pixelsToPerMeter(y, config),
292
+ };
293
+ });
294
+
295
+ // 计算${i18n.t(`perimeter`)}
296
+ let polygonPerimeter = 0;
297
+ for (let i = 0; i < points.length; i++) {
298
+ const currentPoint = points[i];
299
+ const nextPoint = points[(i + 1) % points.length];
300
+ const dx = nextPoint.x - currentPoint.x;
301
+ const dy = nextPoint.y - currentPoint.y;
302
+ polygonPerimeter += Math.sqrt(dx * dx + dy * dy);
303
+ }
304
+
305
+ // 计算${i18n.t(`area`)}
306
+ let polygonArea = 0;
307
+ for (let i = 0; i < points.length; i++) {
308
+ const currentPoint = points[i];
309
+ const nextPoint = points[(i + 1) % points.length];
310
+ polygonArea +=
311
+ currentPoint.x * nextPoint.y - nextPoint.x * currentPoint.y;
312
+ }
313
+ polygonArea = Math.abs(polygonArea) / 2;
314
+ if (firstTag) {
315
+ foreignObject.innerHTML = `
316
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
317
+ <div class="a9s-shape-label">
318
+ <p>
319
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
320
+ polygonPerimeter,
321
+ "m",
322
+ )}&nbsp;&nbsp;</p> <p>
323
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
324
+ polygonArea,
325
+ "m²",
326
+ )}&nbsp;&nbsp;</p> <p>
327
+ ${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
328
+ </p>
329
+ </div>
330
+ </div>`;
331
+ } else {
332
+ foreignObject.innerHTML = `
333
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
334
+
335
+ <div class="a9s-shape-label">
336
+ <p>
337
+ ${i18n.t(`perimeter`)}:&nbsp;&nbsp;${getWithUnit(
338
+ polygonPerimeter,
339
+ "m",
340
+ )}&nbsp;&nbsp;</p><p>
341
+ ${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(
342
+ polygonArea,
343
+ "m²",
344
+ )}&nbsp;&nbsp;
345
+ </p>
346
+ </div>
347
+ </div>`;
348
+ }
349
+
350
+ break;
351
+ case "freehand":
352
+ // 解析 path
353
+ let pathDiv = document.createElement("div");
354
+ pathDiv.innerHTML = annotation.target.selector.value;
355
+
356
+ let path = pathDiv.getElementsByTagName("path")[0];
357
+ let d = path.getAttribute("d");
358
+
359
+ // 使用 svg-path-properties 解析曲线
360
+ const properties = new svgPathProperties(d);
361
+
362
+ // 周长(像素)
363
+ let pixelPerimeter = properties.getTotalLength();
364
+
365
+ // 离散化路径为点(越多越精确)
366
+ let steps = 300; // 建议 200~500
367
+ let freehandPoints = [];
368
+ for (let i = 0; i <= steps; i++) {
369
+ let pos = properties.getPointAtLength((i / steps) * pixelPerimeter);
370
+ freehandPoints.push([pos.x, pos.y]);
371
+ }
372
+
373
+ // 计算面积(鞋带公式)
374
+ let areaPixel = computeFreehandArea(freehandPoints);
375
+
376
+ // 转换单位(你的 config)
377
+ let realPerimeter = pixelsToPerMeter(pixelPerimeter, config);
378
+
379
+ // 面积单位转换(像素² → μm²)
380
+ // pixelsToPerMeter(1) = 1 像素对应多少 μm
381
+ let pixelToMicro = pixelsToPerMeter(1, config);
382
+ let realArea = areaPixel * pixelToMicro * pixelToMicro;
383
+
384
+ // 鞋带公式
385
+ function computeFreehandArea(freehandPoints) {
386
+ let sum = 0;
387
+ for (let i = 0; i < freehandPoints.length - 1; i++) {
388
+ const [x1, y1] = freehandPoints[i];
389
+ const [x2, y2] = freehandPoints[i + 1];
390
+ sum += x1 * y2 - x2 * y1;
391
+ }
392
+ return Math.abs(sum / 2);
393
+ }
394
+
395
+ if (firstTag) {
396
+ foreignObject.innerHTML = `
397
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
398
+ <div class="a9s-shape-label">
399
+ <p>${i18n.t(`length`)}:&nbsp;&nbsp;${getWithUnit(realPerimeter, "m")}</p>
400
+ <p>${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(realArea, "m²")}</p>
401
+ <p>${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}</p>
402
+ </div>
403
+ </div>`;
404
+ } else {
405
+ foreignObject.innerHTML = `
406
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
407
+ <div class="a9s-shape-label">
408
+ <p>${i18n.t(`length`)}:&nbsp;&nbsp;${getWithUnit(realPerimeter, "m")}</p>
409
+ <p>${i18n.t(`area`)}:&nbsp;&nbsp;${getWithUnit(realArea, "m²")}</p>
410
+ </div>
411
+ </div>`;
412
+ }
413
+
414
+ break;
415
+
416
+ default:
417
+ if (firstTag) {
418
+ foreignObject.innerHTML = `
419
+ <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
420
+ <div class="a9s-shape-label">
421
+ <p>
422
+ ${i18n.t(`remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
423
+ </p>
424
+ </div>
425
+ </div>`;
426
+ }
427
+ // 如果没有与表达式相同的值,则执行该代码
428
+ }
429
+
430
+ return {
431
+ element: foreignObject,
432
+ };
433
+ };
434
+
435
+ export default ShapeLabelsFormatter;