med-viewer-sdk 0.1.24 → 0.1.26
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/dist/med-viewer-sdk.mjs +244 -382
- package/dist/med-viewer-sdk.umd.js +1 -1
- package/package.json +1 -1
package/dist/med-viewer-sdk.mjs
CHANGED
|
@@ -12794,6 +12794,15 @@ const CSS_VAR_MAP = {
|
|
|
12794
12794
|
function cssVar(key) {
|
|
12795
12795
|
return `var(${CSS_VAR_MAP[key]})`;
|
|
12796
12796
|
}
|
|
12797
|
+
const GLOBAL_ANNO_EDITOR_KEYS = [
|
|
12798
|
+
"annoEditorBg",
|
|
12799
|
+
"annoEditorText",
|
|
12800
|
+
"annoEditorBorder",
|
|
12801
|
+
"annoEditorInputBg",
|
|
12802
|
+
"annoEditorBtnBg",
|
|
12803
|
+
"annoEditorBtnHoverBg",
|
|
12804
|
+
"annoEditorBtnColor"
|
|
12805
|
+
];
|
|
12797
12806
|
class ThemeManager {
|
|
12798
12807
|
constructor(container, themeConfig) {
|
|
12799
12808
|
__publicField(this, "container");
|
|
@@ -12830,6 +12839,7 @@ class ThemeManager {
|
|
|
12830
12839
|
}
|
|
12831
12840
|
/**
|
|
12832
12841
|
* 将主题颜色应用为 CSS 变量到容器元素
|
|
12842
|
+
* 同时将 annoEditor* 相关变量提升到 :root,供 .r6o-editor(挂载在 body 下)使用
|
|
12833
12843
|
*/
|
|
12834
12844
|
applyTheme(colors) {
|
|
12835
12845
|
const keys = Object.keys(CSS_VAR_MAP);
|
|
@@ -12837,6 +12847,9 @@ class ThemeManager {
|
|
|
12837
12847
|
const value = colors[key];
|
|
12838
12848
|
if (value !== void 0) {
|
|
12839
12849
|
this.container.style.setProperty(CSS_VAR_MAP[key], value);
|
|
12850
|
+
if (GLOBAL_ANNO_EDITOR_KEYS.includes(key)) {
|
|
12851
|
+
document.documentElement.style.setProperty(CSS_VAR_MAP[key], value);
|
|
12852
|
+
}
|
|
12840
12853
|
}
|
|
12841
12854
|
});
|
|
12842
12855
|
}
|
|
@@ -12874,6 +12887,9 @@ class ThemeManager {
|
|
|
12874
12887
|
const keys = Object.keys(CSS_VAR_MAP);
|
|
12875
12888
|
keys.forEach((key) => {
|
|
12876
12889
|
this.container.style.removeProperty(CSS_VAR_MAP[key]);
|
|
12890
|
+
if (GLOBAL_ANNO_EDITOR_KEYS.includes(key)) {
|
|
12891
|
+
document.documentElement.style.removeProperty(CSS_VAR_MAP[key]);
|
|
12892
|
+
}
|
|
12877
12893
|
});
|
|
12878
12894
|
}
|
|
12879
12895
|
}
|
|
@@ -12882,6 +12898,7 @@ class AnnoAnnotator extends BaseAnnotator {
|
|
|
12882
12898
|
super(engine);
|
|
12883
12899
|
__publicField(this, "anno");
|
|
12884
12900
|
__publicField(this, "listeners", /* @__PURE__ */ new Map());
|
|
12901
|
+
__publicField(this, "injectedStyleEl", null);
|
|
12885
12902
|
this.anno = Annotorious(this.engine.viewer, {
|
|
12886
12903
|
...config
|
|
12887
12904
|
// 可以在此配置样式、偏好等
|
|
@@ -12936,7 +12953,10 @@ class AnnoAnnotator extends BaseAnnotator {
|
|
|
12936
12953
|
this.anno.clearAnnotations();
|
|
12937
12954
|
}
|
|
12938
12955
|
destroy() {
|
|
12956
|
+
var _a2;
|
|
12939
12957
|
this.anno.destroy();
|
|
12958
|
+
(_a2 = this.injectedStyleEl) == null ? void 0 : _a2.remove();
|
|
12959
|
+
this.injectedStyleEl = null;
|
|
12940
12960
|
}
|
|
12941
12961
|
initEvents(config) {
|
|
12942
12962
|
if (config.onCreateAnnotation) {
|
|
@@ -12973,11 +12993,9 @@ class AnnoAnnotator extends BaseAnnotator {
|
|
|
12973
12993
|
}
|
|
12974
12994
|
}
|
|
12975
12995
|
injectStyles() {
|
|
12976
|
-
const styleId = "med-anno-v2-7-17-overrides";
|
|
12977
|
-
if (document.getElementById(styleId))
|
|
12978
|
-
return;
|
|
12979
12996
|
const style = document.createElement("style");
|
|
12980
|
-
style.
|
|
12997
|
+
style.setAttribute("data-med-anno-instance", "true");
|
|
12998
|
+
this.injectedStyleEl = style;
|
|
12981
12999
|
style.innerHTML = `
|
|
12982
13000
|
/* ── 标注手柄 ── */
|
|
12983
13001
|
.a9s-handle .a9s-handle-inner {
|
|
@@ -14150,442 +14168,234 @@ function t(path) {
|
|
|
14150
14168
|
}
|
|
14151
14169
|
return typeof value === "string" ? value : path;
|
|
14152
14170
|
}
|
|
14171
|
+
function getCurrentLocale() {
|
|
14172
|
+
return currentLocale;
|
|
14173
|
+
}
|
|
14153
14174
|
function getWithUnit(value, unitSuffix) {
|
|
14154
|
-
|
|
14175
|
+
const isArea = unitSuffix.includes("²");
|
|
14176
|
+
const baseSuffix = unitSuffix.replace("²", "");
|
|
14177
|
+
if (isArea) {
|
|
14178
|
+
if (value >= 1e12) {
|
|
14179
|
+
return (value / 1e12).toFixed(2) + " " + baseSuffix + "²";
|
|
14180
|
+
}
|
|
14181
|
+
if (value >= 1e6) {
|
|
14182
|
+
return (value / 1e6).toFixed(2) + " m" + baseSuffix + "²";
|
|
14183
|
+
}
|
|
14184
|
+
return value.toFixed(2) + " μ" + baseSuffix + "²";
|
|
14185
|
+
} else {
|
|
14186
|
+
if (value >= 1e6) {
|
|
14187
|
+
return (value / 1e6).toFixed(2) + " " + baseSuffix;
|
|
14188
|
+
}
|
|
14189
|
+
if (value >= 1e3) {
|
|
14190
|
+
return (value / 1e3).toFixed(2) + " m" + baseSuffix;
|
|
14191
|
+
}
|
|
14192
|
+
return value.toFixed(2) + " μ" + baseSuffix;
|
|
14193
|
+
}
|
|
14155
14194
|
}
|
|
14156
|
-
function
|
|
14157
|
-
|
|
14158
|
-
|
|
14195
|
+
function pixelsToMicrons(value, pixelsPerMeter) {
|
|
14196
|
+
return value / pixelsPerMeter * 1e6;
|
|
14197
|
+
}
|
|
14198
|
+
function computePolygonArea(pts) {
|
|
14199
|
+
let sum = 0;
|
|
14200
|
+
for (let i2 = 0; i2 < pts.length - 1; i2++) {
|
|
14201
|
+
const [x1, y1] = pts[i2];
|
|
14202
|
+
const [x2, y2] = pts[i2 + 1];
|
|
14203
|
+
sum += x1 * y2 - x2 * y1;
|
|
14204
|
+
}
|
|
14205
|
+
return Math.abs(sum / 2);
|
|
14159
14206
|
}
|
|
14160
14207
|
const ShapeLabelsFormatter = (pixelsPerMeter, showMeasure) => (annotation) => {
|
|
14161
14208
|
var _a2;
|
|
14162
14209
|
const bodies = Array.isArray(annotation.body) ? annotation.body : [annotation.body];
|
|
14163
|
-
let toolName = (_a2 = annotation.target.renderedVia) == null ? void 0 : _a2.name;
|
|
14164
|
-
if (!showMeasure)
|
|
14210
|
+
let toolName = ((_a2 = annotation.target.renderedVia) == null ? void 0 : _a2.name) ?? null;
|
|
14211
|
+
if (!showMeasure)
|
|
14165
14212
|
toolName = null;
|
|
14166
|
-
}
|
|
14167
14213
|
const foreignObject = document.createElementNS(
|
|
14168
14214
|
"http://www.w3.org/2000/svg",
|
|
14169
14215
|
"foreignObject"
|
|
14170
14216
|
);
|
|
14171
14217
|
foreignObject.setAttribute("width", "1px");
|
|
14172
14218
|
foreignObject.setAttribute("height", "1px");
|
|
14173
|
-
const firstTag = bodies.find((b2) => b2.purpose
|
|
14219
|
+
const firstTag = bodies.find((b2) => (b2 == null ? void 0 : b2.purpose) === "commenting");
|
|
14220
|
+
const wrapLabel = (rows, remark) => {
|
|
14221
|
+
const remarkRow = remark ? `<p>${t("annotation.remark")}: ${remark}</p>` : "";
|
|
14222
|
+
return `<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14223
|
+
<div class="a9s-shape-label">
|
|
14224
|
+
${rows.map((r2) => `<p>${r2}</p>`).join("")}
|
|
14225
|
+
${remarkRow}
|
|
14226
|
+
</div>
|
|
14227
|
+
</div>`;
|
|
14228
|
+
};
|
|
14174
14229
|
switch (toolName) {
|
|
14175
|
-
case "line":
|
|
14176
|
-
|
|
14177
|
-
|
|
14178
|
-
|
|
14179
|
-
|
|
14180
|
-
|
|
14181
|
-
|
|
14182
|
-
|
|
14183
|
-
);
|
|
14184
|
-
|
|
14185
|
-
|
|
14186
|
-
|
|
14187
|
-
);
|
|
14188
|
-
let x2 = pixelsToPerMeter(
|
|
14189
|
-
Number(line.getAttribute("x2")),
|
|
14190
|
-
pixelsPerMeter
|
|
14230
|
+
case "line": {
|
|
14231
|
+
const div = document.createElement("div");
|
|
14232
|
+
div.innerHTML = annotation.target.selector.value;
|
|
14233
|
+
const el = div.getElementsByTagName("line")[0];
|
|
14234
|
+
const x1 = pixelsToMicrons(Number(el.getAttribute("x1")), pixelsPerMeter);
|
|
14235
|
+
const y1 = pixelsToMicrons(Number(el.getAttribute("y1")), pixelsPerMeter);
|
|
14236
|
+
const x2 = pixelsToMicrons(Number(el.getAttribute("x2")), pixelsPerMeter);
|
|
14237
|
+
const y2 = pixelsToMicrons(Number(el.getAttribute("y2")), pixelsPerMeter);
|
|
14238
|
+
const len = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
14239
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14240
|
+
[`${t("annotation.length")}: ${getWithUnit(len, "m")}`],
|
|
14241
|
+
firstTag == null ? void 0 : firstTag.value
|
|
14191
14242
|
);
|
|
14192
|
-
let y2 = pixelsToPerMeter(
|
|
14193
|
-
Number(line.getAttribute("y2")),
|
|
14194
|
-
pixelsPerMeter
|
|
14195
|
-
);
|
|
14196
|
-
let len = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
|
|
14197
|
-
if (firstTag) {
|
|
14198
|
-
foreignObject.innerHTML = `
|
|
14199
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14200
|
-
<div class="a9s-shape-label" >
|
|
14201
|
-
<p >
|
|
14202
|
-
${t(`annotation.length`)}: ${getWithUnit(
|
|
14203
|
-
len,
|
|
14204
|
-
"m"
|
|
14205
|
-
)} </p> <p >
|
|
14206
|
-
${t(`annotation.remark`)}: ${firstTag.value}
|
|
14207
|
-
</p>
|
|
14208
|
-
</div>
|
|
14209
|
-
</div>`;
|
|
14210
|
-
} else {
|
|
14211
|
-
foreignObject.innerHTML = `
|
|
14212
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14213
|
-
|
|
14214
|
-
<div class="a9s-shape-label" >
|
|
14215
|
-
<p>
|
|
14216
|
-
${t(`annotation.length`)}: ${getWithUnit(len, "m")}
|
|
14217
|
-
</p>
|
|
14218
|
-
</div>
|
|
14219
|
-
</div>`;
|
|
14220
|
-
}
|
|
14221
14243
|
break;
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
const
|
|
14227
|
-
const
|
|
14228
|
-
const
|
|
14229
|
-
const
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
"m"
|
|
14239
|
-
)} </p> <p>
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
${t(`annotation.height`)}: ${getWithUnit(
|
|
14243
|
-
rectHeight,
|
|
14244
|
-
"m"
|
|
14245
|
-
)} </p> <p>
|
|
14246
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14247
|
-
rectPerimeter,
|
|
14248
|
-
"m"
|
|
14249
|
-
)} </p> <p>
|
|
14250
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14251
|
-
rectArea,
|
|
14252
|
-
"m²"
|
|
14253
|
-
)} </p> <p>
|
|
14254
|
-
${t(`annotation.remark`)}: ${firstTag.value}
|
|
14255
|
-
</p>
|
|
14256
|
-
</div>
|
|
14257
|
-
</div>`;
|
|
14258
|
-
} else {
|
|
14259
|
-
foreignObject.innerHTML = `
|
|
14260
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14261
|
-
<div class="a9s-shape-label">
|
|
14262
|
-
<p >
|
|
14263
|
-
${t(`annotation.width`)}: ${getWithUnit(
|
|
14264
|
-
rectWidth,
|
|
14265
|
-
"m"
|
|
14266
|
-
)} </p> <p>
|
|
14267
|
-
${t(`annotation.height`)}: ${getWithUnit(
|
|
14268
|
-
rectHeight,
|
|
14269
|
-
"m"
|
|
14270
|
-
)} </p> <p>
|
|
14271
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14272
|
-
rectPerimeter,
|
|
14273
|
-
"m"
|
|
14274
|
-
)} </p> <p>
|
|
14275
|
-
${t(`annotation.area`)}: ${getWithUnit(rectArea, "m²")}
|
|
14276
|
-
</p>
|
|
14277
|
-
</div>
|
|
14278
|
-
</div>`;
|
|
14279
|
-
}
|
|
14280
|
-
break;
|
|
14281
|
-
case "circle":
|
|
14282
|
-
let circleDiv = document.createElement("div");
|
|
14283
|
-
console.log(annotation);
|
|
14284
|
-
circleDiv.innerHTML = annotation.target.selector.value;
|
|
14285
|
-
let circle = circleDiv.getElementsByTagName("circle")[0];
|
|
14286
|
-
const circleRadius = pixelsToPerMeter(
|
|
14287
|
-
Number(circle.getAttribute("r")),
|
|
14288
|
-
pixelsPerMeter
|
|
14244
|
+
}
|
|
14245
|
+
case "rect": {
|
|
14246
|
+
const str = annotation.target.selector.value.replace(/xywh=pixel:/g, "");
|
|
14247
|
+
const parts = str.split(",");
|
|
14248
|
+
const rw = pixelsToMicrons(Number(parts[2]), pixelsPerMeter);
|
|
14249
|
+
const rh = pixelsToMicrons(Number(parts[3]), pixelsPerMeter);
|
|
14250
|
+
const rp = 2 * (rw + rh);
|
|
14251
|
+
const ra = rw * rh;
|
|
14252
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14253
|
+
[
|
|
14254
|
+
`${t("annotation.width")}: ${getWithUnit(rw, "m")}`,
|
|
14255
|
+
`${t("annotation.height")}: ${getWithUnit(rh, "m")}`,
|
|
14256
|
+
`${t("annotation.perimeter")}: ${getWithUnit(rp, "m")}`,
|
|
14257
|
+
`${t("annotation.area")}: ${getWithUnit(ra, "m²")}`
|
|
14258
|
+
],
|
|
14259
|
+
firstTag == null ? void 0 : firstTag.value
|
|
14289
14260
|
);
|
|
14290
|
-
const circleCircumference = 2 * Math.PI * circleRadius;
|
|
14291
|
-
const circleArea = Math.PI * Math.pow(circleRadius, 2);
|
|
14292
|
-
if (firstTag) {
|
|
14293
|
-
foreignObject.innerHTML = `
|
|
14294
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14295
|
-
|
|
14296
|
-
<div class="a9s-shape-label">
|
|
14297
|
-
<p>
|
|
14298
|
-
${t(`annotation.radius`)}: ${getWithUnit(
|
|
14299
|
-
circleRadius,
|
|
14300
|
-
"m"
|
|
14301
|
-
)} </p><p>
|
|
14302
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14303
|
-
circleCircumference,
|
|
14304
|
-
"m"
|
|
14305
|
-
)} </p><p>
|
|
14306
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14307
|
-
circleArea,
|
|
14308
|
-
"m²"
|
|
14309
|
-
)} </p><p>
|
|
14310
|
-
${t(`annotation.remark`)}: ${firstTag.value}
|
|
14311
|
-
</p>
|
|
14312
|
-
</div>
|
|
14313
|
-
</div>`;
|
|
14314
|
-
} else {
|
|
14315
|
-
foreignObject.innerHTML = `
|
|
14316
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14317
|
-
<div class="a9s-shape-label">
|
|
14318
|
-
<p>
|
|
14319
|
-
${t(`annotation.radius`)}: ${getWithUnit(
|
|
14320
|
-
circleRadius,
|
|
14321
|
-
"m"
|
|
14322
|
-
)} </p><p>
|
|
14323
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14324
|
-
circleCircumference,
|
|
14325
|
-
"m"
|
|
14326
|
-
)} </p><p>
|
|
14327
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14328
|
-
circleArea,
|
|
14329
|
-
"m²"
|
|
14330
|
-
)}
|
|
14331
|
-
|
|
14332
|
-
</p>
|
|
14333
|
-
</div>
|
|
14334
|
-
</div>`;
|
|
14335
|
-
}
|
|
14336
14261
|
break;
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14340
|
-
|
|
14341
|
-
|
|
14342
|
-
|
|
14343
|
-
|
|
14262
|
+
}
|
|
14263
|
+
case "circle": {
|
|
14264
|
+
const div = document.createElement("div");
|
|
14265
|
+
div.innerHTML = annotation.target.selector.value;
|
|
14266
|
+
const el = div.getElementsByTagName("circle")[0];
|
|
14267
|
+
const r2 = pixelsToMicrons(Number(el.getAttribute("r")), pixelsPerMeter);
|
|
14268
|
+
const circum = 2 * Math.PI * r2;
|
|
14269
|
+
const area = Math.PI * r2 * r2;
|
|
14270
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14271
|
+
[
|
|
14272
|
+
`${t("annotation.radius")}: ${getWithUnit(r2, "m")}`,
|
|
14273
|
+
`${t("annotation.perimeter")}: ${getWithUnit(circum, "m")}`,
|
|
14274
|
+
`${t("annotation.area")}: ${getWithUnit(area, "m²")}`
|
|
14275
|
+
],
|
|
14276
|
+
firstTag == null ? void 0 : firstTag.value
|
|
14344
14277
|
);
|
|
14345
|
-
|
|
14346
|
-
|
|
14347
|
-
|
|
14278
|
+
break;
|
|
14279
|
+
}
|
|
14280
|
+
case "ellipse": {
|
|
14281
|
+
const div = document.createElement("div");
|
|
14282
|
+
div.innerHTML = annotation.target.selector.value;
|
|
14283
|
+
const el = div.getElementsByTagName("ellipse")[0];
|
|
14284
|
+
const rx = pixelsToMicrons(Number(el.getAttribute("rx")), pixelsPerMeter);
|
|
14285
|
+
const ry = pixelsToMicrons(Number(el.getAttribute("ry")), pixelsPerMeter);
|
|
14286
|
+
const majorAxis = Math.max(rx, ry);
|
|
14287
|
+
const minorAxis = Math.min(rx, ry);
|
|
14288
|
+
const perim = Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
|
|
14289
|
+
const area = Math.PI * rx * ry;
|
|
14290
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14291
|
+
[
|
|
14292
|
+
`${t("annotation.majorAxis")}: ${getWithUnit(majorAxis, "m")}`,
|
|
14293
|
+
`${t("annotation.minorAxis")}: ${getWithUnit(minorAxis, "m")}`,
|
|
14294
|
+
`${t("annotation.perimeter")}: ${getWithUnit(perim, "m")}`,
|
|
14295
|
+
`${t("annotation.area")}: ${getWithUnit(area, "m²")}`
|
|
14296
|
+
],
|
|
14297
|
+
firstTag == null ? void 0 : firstTag.value
|
|
14348
14298
|
);
|
|
14349
|
-
let majorAxis = null;
|
|
14350
|
-
let minorAxis = null;
|
|
14351
|
-
if (rx >= ry) {
|
|
14352
|
-
majorAxis = rx;
|
|
14353
|
-
minorAxis = ry;
|
|
14354
|
-
} else {
|
|
14355
|
-
majorAxis = ry;
|
|
14356
|
-
minorAxis = rx;
|
|
14357
|
-
}
|
|
14358
|
-
const ellipsePerimeter = Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
|
|
14359
|
-
const ellipseArea = Math.PI * rx * ry;
|
|
14360
|
-
if (firstTag) {
|
|
14361
|
-
foreignObject.innerHTML = `
|
|
14362
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14363
|
-
<div class="a9s-shape-label">
|
|
14364
|
-
<p>
|
|
14365
|
-
${t(`annotation.majorAxis`)}: ${getWithUnit(
|
|
14366
|
-
majorAxis,
|
|
14367
|
-
"m"
|
|
14368
|
-
)} </p> <p>
|
|
14369
|
-
|
|
14370
|
-
${t(`annotation.minorAxis`)}: ${getWithUnit(
|
|
14371
|
-
minorAxis,
|
|
14372
|
-
"m"
|
|
14373
|
-
)} </p> <p>
|
|
14374
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14375
|
-
ellipsePerimeter,
|
|
14376
|
-
"m"
|
|
14377
|
-
)} </p> <p>
|
|
14378
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14379
|
-
ellipseArea,
|
|
14380
|
-
"m²"
|
|
14381
|
-
)} </p> <p>
|
|
14382
|
-
${t(`annotation.remark`)}: ${firstTag.value}
|
|
14383
|
-
</p>
|
|
14384
|
-
</div>
|
|
14385
|
-
</div>`;
|
|
14386
|
-
} else {
|
|
14387
|
-
foreignObject.innerHTML = `
|
|
14388
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14389
|
-
<div class="a9s-shape-label">
|
|
14390
|
-
<p>
|
|
14391
|
-
${t(`annotation.majorAxis`)}: ${getWithUnit(
|
|
14392
|
-
majorAxis,
|
|
14393
|
-
"m"
|
|
14394
|
-
)} </p><p>
|
|
14395
|
-
|
|
14396
|
-
${t(`annotation.minorAxis`)}: ${getWithUnit(
|
|
14397
|
-
minorAxis,
|
|
14398
|
-
"m"
|
|
14399
|
-
)} </p><p>
|
|
14400
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14401
|
-
ellipsePerimeter,
|
|
14402
|
-
"m"
|
|
14403
|
-
)} </p><p>
|
|
14404
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14405
|
-
ellipseArea,
|
|
14406
|
-
"m²"
|
|
14407
|
-
)}
|
|
14408
|
-
</p>
|
|
14409
|
-
</div>
|
|
14410
|
-
</div>`;
|
|
14411
|
-
}
|
|
14412
14299
|
break;
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
const
|
|
14419
|
-
const [
|
|
14420
|
-
return
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14300
|
+
}
|
|
14301
|
+
case "polygon": {
|
|
14302
|
+
const div = document.createElement("div");
|
|
14303
|
+
div.innerHTML = annotation.target.selector.value;
|
|
14304
|
+
const el = div.getElementsByTagName("polygon")[0];
|
|
14305
|
+
const pts = (el.getAttribute("points") ?? "").trim().split(/\s+/).map((p2) => {
|
|
14306
|
+
const [x2, y2] = p2.split(",").map(parseFloat);
|
|
14307
|
+
return [
|
|
14308
|
+
pixelsToMicrons(x2, pixelsPerMeter),
|
|
14309
|
+
pixelsToMicrons(y2, pixelsPerMeter)
|
|
14310
|
+
];
|
|
14424
14311
|
});
|
|
14425
|
-
let
|
|
14426
|
-
for (let i2 = 0; i2 <
|
|
14427
|
-
const
|
|
14428
|
-
const
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14435
|
-
|
|
14436
|
-
|
|
14437
|
-
|
|
14438
|
-
|
|
14439
|
-
polygonArea = Math.abs(polygonArea) / 2;
|
|
14440
|
-
if (firstTag) {
|
|
14441
|
-
foreignObject.innerHTML = `
|
|
14442
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14443
|
-
<div class="a9s-shape-label">
|
|
14444
|
-
<p>
|
|
14445
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14446
|
-
polygonPerimeter,
|
|
14447
|
-
"m"
|
|
14448
|
-
)} </p> <p>
|
|
14449
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14450
|
-
polygonArea,
|
|
14451
|
-
"m²"
|
|
14452
|
-
)} </p> <p>
|
|
14453
|
-
${t(`annotation.remark`)}: ${firstTag.value}
|
|
14454
|
-
</p>
|
|
14455
|
-
</div>
|
|
14456
|
-
</div>`;
|
|
14457
|
-
} else {
|
|
14458
|
-
foreignObject.innerHTML = `
|
|
14459
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14460
|
-
|
|
14461
|
-
<div class="a9s-shape-label">
|
|
14462
|
-
<p>
|
|
14463
|
-
${t(`annotation.perimeter`)}: ${getWithUnit(
|
|
14464
|
-
polygonPerimeter,
|
|
14465
|
-
"m"
|
|
14466
|
-
)} </p><p>
|
|
14467
|
-
${t(`annotation.area`)}: ${getWithUnit(
|
|
14468
|
-
polygonArea,
|
|
14469
|
-
"m²"
|
|
14470
|
-
)}
|
|
14471
|
-
</p>
|
|
14472
|
-
</div>
|
|
14473
|
-
</div>`;
|
|
14474
|
-
}
|
|
14312
|
+
let polyPerim = 0;
|
|
14313
|
+
for (let i2 = 0; i2 < pts.length; i2++) {
|
|
14314
|
+
const [ax, ay] = pts[i2];
|
|
14315
|
+
const [bx, by] = pts[(i2 + 1) % pts.length];
|
|
14316
|
+
polyPerim += Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2));
|
|
14317
|
+
}
|
|
14318
|
+
const polyArea = computePolygonArea(pts);
|
|
14319
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14320
|
+
[
|
|
14321
|
+
`${t("annotation.perimeter")}: ${getWithUnit(polyPerim, "m")}`,
|
|
14322
|
+
`${t("annotation.area")}: ${getWithUnit(polyArea, "m²")}`
|
|
14323
|
+
],
|
|
14324
|
+
firstTag == null ? void 0 : firstTag.value
|
|
14325
|
+
);
|
|
14475
14326
|
break;
|
|
14476
|
-
|
|
14477
|
-
|
|
14478
|
-
|
|
14479
|
-
|
|
14480
|
-
|
|
14481
|
-
|
|
14482
|
-
|
|
14483
|
-
|
|
14484
|
-
|
|
14485
|
-
|
|
14486
|
-
let pathDiv = document.createElement("div");
|
|
14487
|
-
pathDiv.innerHTML = annotation.target.selector.value;
|
|
14488
|
-
let path = pathDiv.getElementsByTagName("path")[0];
|
|
14489
|
-
let d2 = path.getAttribute("d");
|
|
14490
|
-
const properties = new N(d2);
|
|
14491
|
-
let pixelPerimeter = properties.getTotalLength();
|
|
14492
|
-
let steps = 300;
|
|
14493
|
-
let freehandPoints = [];
|
|
14327
|
+
}
|
|
14328
|
+
case "freehand": {
|
|
14329
|
+
const div = document.createElement("div");
|
|
14330
|
+
div.innerHTML = annotation.target.selector.value;
|
|
14331
|
+
const el = div.getElementsByTagName("path")[0];
|
|
14332
|
+
const d2 = el.getAttribute("d") ?? "";
|
|
14333
|
+
const props = new N(d2);
|
|
14334
|
+
const pixelPerim = props.getTotalLength();
|
|
14335
|
+
const steps = 300;
|
|
14336
|
+
const fhPts = [];
|
|
14494
14337
|
for (let i2 = 0; i2 <= steps; i2++) {
|
|
14495
|
-
|
|
14496
|
-
|
|
14497
|
-
}
|
|
14498
|
-
|
|
14499
|
-
|
|
14500
|
-
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
</div>
|
|
14510
|
-
</div>`;
|
|
14511
|
-
} else {
|
|
14512
|
-
foreignObject.innerHTML = `
|
|
14513
|
-
<div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
|
|
14514
|
-
<div class="a9s-shape-label">
|
|
14515
|
-
<p>${t(`annotation.length`)}: ${getWithUnit(realPerimeter, "m")}</p>
|
|
14516
|
-
<p>${t(`annotation.area`)}: ${getWithUnit(realArea, "m²")}</p>
|
|
14517
|
-
</div>
|
|
14518
|
-
</div>`;
|
|
14519
|
-
}
|
|
14338
|
+
const pos = props.getPointAtLength(i2 / steps * pixelPerim);
|
|
14339
|
+
fhPts.push([pos.x, pos.y]);
|
|
14340
|
+
}
|
|
14341
|
+
const areaPixel = computePolygonArea(fhPts);
|
|
14342
|
+
const realPerim = pixelsToMicrons(pixelPerim, pixelsPerMeter);
|
|
14343
|
+
const pixelToMicro = pixelsToMicrons(1, pixelsPerMeter);
|
|
14344
|
+
const realArea = areaPixel * pixelToMicro * pixelToMicro;
|
|
14345
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14346
|
+
[
|
|
14347
|
+
`${t("annotation.length")}: ${getWithUnit(realPerim, "m")}`,
|
|
14348
|
+
`${t("annotation.area")}: ${getWithUnit(realArea, "m²")}`
|
|
14349
|
+
],
|
|
14350
|
+
firstTag == null ? void 0 : firstTag.value
|
|
14351
|
+
);
|
|
14520
14352
|
break;
|
|
14353
|
+
}
|
|
14521
14354
|
default:
|
|
14522
14355
|
if (firstTag) {
|
|
14523
|
-
foreignObject.innerHTML =
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
${t(`annotation.remark`)}: ${firstTag.value}
|
|
14528
|
-
</p>
|
|
14529
|
-
</div>
|
|
14530
|
-
</div>`;
|
|
14356
|
+
foreignObject.innerHTML = wrapLabel(
|
|
14357
|
+
[],
|
|
14358
|
+
firstTag.value
|
|
14359
|
+
);
|
|
14531
14360
|
}
|
|
14532
14361
|
}
|
|
14533
|
-
return {
|
|
14534
|
-
element: foreignObject
|
|
14535
|
-
};
|
|
14362
|
+
return { element: foreignObject };
|
|
14536
14363
|
};
|
|
14537
|
-
|
|
14364
|
+
function injectShapeLabelStyles() {
|
|
14538
14365
|
const styleId = "med-anno-default-shapeLabelsFormatter-overrides";
|
|
14539
14366
|
if (document.getElementById(styleId))
|
|
14540
14367
|
return;
|
|
14541
14368
|
const style = document.createElement("style");
|
|
14542
14369
|
style.id = styleId;
|
|
14543
14370
|
style.innerHTML = `
|
|
14544
|
-
|
|
14545
14371
|
.a9s-annotationlayer .a9s-formatter-el,
|
|
14546
14372
|
.a9s-annotationlayer .a9s-formatter-el foreignObject {
|
|
14547
14373
|
overflow: visible;
|
|
14548
14374
|
pointer-events: none;
|
|
14549
14375
|
}
|
|
14550
|
-
|
|
14551
14376
|
.a9s-annotationlayer .a9s-formatter-el foreignObject .a9s-shape-label-wrapper {
|
|
14552
14377
|
position: relative;
|
|
14553
14378
|
transform: translateY(-100%);
|
|
14554
14379
|
padding-bottom: 4px;
|
|
14555
14380
|
}
|
|
14556
|
-
|
|
14557
|
-
.a9s-annotationlayer
|
|
14558
|
-
.a9s-formatter-el
|
|
14559
|
-
foreignObject
|
|
14560
|
-
.a9s-shape-label-wrapper
|
|
14561
|
-
.a9s-shape-label {
|
|
14381
|
+
.a9s-annotationlayer .a9s-formatter-el foreignObject .a9s-shape-label-wrapper .a9s-shape-label {
|
|
14562
14382
|
display: inline-block;
|
|
14563
14383
|
max-width: 24vw !important;
|
|
14564
14384
|
color: #000;
|
|
14565
|
-
/* min-width: 10vw !important; */
|
|
14566
|
-
|
|
14567
14385
|
word-wrap: break-word;
|
|
14568
14386
|
word-break: keep-all;
|
|
14569
|
-
/* white-space: nowrap; */
|
|
14570
|
-
|
|
14571
14387
|
padding: 3px 5px;
|
|
14572
14388
|
margin-bottom: 2px;
|
|
14573
14389
|
background-color: rgba(255, 255, 255, 0.85);
|
|
14574
14390
|
border-radius: 3px;
|
|
14575
14391
|
font-size: 14px;
|
|
14576
14392
|
}
|
|
14577
|
-
|
|
14578
|
-
.a9s-annotationlayer
|
|
14579
|
-
.a9s-formatter-el
|
|
14580
|
-
foreignObject
|
|
14581
|
-
.a9s-shape-label-wrapper
|
|
14582
|
-
.a9s-shape-label
|
|
14583
|
-
p {
|
|
14393
|
+
.a9s-annotationlayer .a9s-formatter-el foreignObject .a9s-shape-label-wrapper .a9s-shape-label p {
|
|
14584
14394
|
margin: 5px !important;
|
|
14585
14395
|
}
|
|
14586
|
-
|
|
14396
|
+
`;
|
|
14587
14397
|
document.head.appendChild(style);
|
|
14588
|
-
}
|
|
14398
|
+
}
|
|
14589
14399
|
var MagnificationPosition = /* @__PURE__ */ ((MagnificationPosition2) => {
|
|
14590
14400
|
MagnificationPosition2["TOP_LEFT"] = "TOP_LEFT";
|
|
14591
14401
|
MagnificationPosition2["TOP_CENTER"] = "TOP_CENTER";
|
|
@@ -16060,6 +15870,12 @@ var ToolbarPosition = /* @__PURE__ */ ((ToolbarPosition2) => {
|
|
|
16060
15870
|
return ToolbarPosition2;
|
|
16061
15871
|
})(ToolbarPosition || {});
|
|
16062
15872
|
const createAnnoDropdownContent = (engine, hide) => {
|
|
15873
|
+
if (!engine.anno) {
|
|
15874
|
+
const tip = document.createElement("div");
|
|
15875
|
+
tip.className = "med-toolbar-dropdown-inner med-plugin-unavailable";
|
|
15876
|
+
tip.innerHTML = `<p>标注插件未启用,请在 plugins.annotorious 中开启</p>`;
|
|
15877
|
+
return tip;
|
|
15878
|
+
}
|
|
16063
15879
|
const container = document.createElement("div");
|
|
16064
15880
|
container.className = "med-toolbar-dropdown-inner";
|
|
16065
15881
|
let selectedColor = "#ff0000";
|
|
@@ -16124,6 +15940,12 @@ const debounce = (fn, delay) => {
|
|
|
16124
15940
|
};
|
|
16125
15941
|
const createColorAdjustDropdownContent = (engine, hide) => {
|
|
16126
15942
|
var _a2;
|
|
15943
|
+
if (!engine.colorAdjust) {
|
|
15944
|
+
const tip = document.createElement("div");
|
|
15945
|
+
tip.className = "med-toolbar-dropdown-inner med-plugin-unavailable";
|
|
15946
|
+
tip.innerHTML = `<p>颜色调整插件未启用,请在 plugins.colorAdjust 中开启</p>`;
|
|
15947
|
+
return tip;
|
|
15948
|
+
}
|
|
16127
15949
|
const container = document.createElement("div");
|
|
16128
15950
|
container.className = "med-toolbar-dropdown-inner med-color-adjust-dropdown";
|
|
16129
15951
|
if (engine.anno)
|
|
@@ -16465,9 +16287,13 @@ const DEFAULT_BUTTONS = [
|
|
|
16465
16287
|
icon: buttonSelection,
|
|
16466
16288
|
label: t("toolbar.screenshot"),
|
|
16467
16289
|
onClick: (engine, hide) => {
|
|
16468
|
-
|
|
16290
|
+
if (!engine.selection) {
|
|
16291
|
+
console.warn("[MedToolbar] 截图插件未启用,请在 plugins.selection 中开启");
|
|
16292
|
+
hide();
|
|
16293
|
+
return;
|
|
16294
|
+
}
|
|
16469
16295
|
console.log("selection toggleState");
|
|
16470
|
-
|
|
16296
|
+
engine.selection.toggleState();
|
|
16471
16297
|
if (engine.anno) {
|
|
16472
16298
|
engine.anno.setEnabled(false);
|
|
16473
16299
|
}
|
|
@@ -17010,6 +16836,17 @@ class MedToolbar {
|
|
|
17010
16836
|
.med-reset-btn:hover {
|
|
17011
16837
|
background: ${cssVar("dangerBgHigh")};
|
|
17012
16838
|
}
|
|
16839
|
+
.med-plugin-unavailable {
|
|
16840
|
+
min-width: 200px;
|
|
16841
|
+
padding: 16px 12px;
|
|
16842
|
+
text-align: center;
|
|
16843
|
+
}
|
|
16844
|
+
.med-plugin-unavailable p {
|
|
16845
|
+
margin: 0;
|
|
16846
|
+
font-size: 13px;
|
|
16847
|
+
color: ${cssVar("textMuted")};
|
|
16848
|
+
line-height: 1.5;
|
|
16849
|
+
}
|
|
17013
16850
|
`;
|
|
17014
16851
|
document.head.appendChild(style);
|
|
17015
16852
|
}
|
|
@@ -17099,6 +16936,7 @@ class MedViewerEngine {
|
|
|
17099
16936
|
this.options = options;
|
|
17100
16937
|
this.viewer = OpenSeadragon(osdOptions);
|
|
17101
16938
|
this.themeManager = new ThemeManager(this.viewer.element, options.theme);
|
|
16939
|
+
this.injectNavigatorStyles();
|
|
17102
16940
|
this.viewer.addOnceHandler("open", () => {
|
|
17103
16941
|
this.viewer.viewport.goHome();
|
|
17104
16942
|
this.emit("ready");
|
|
@@ -17325,6 +17163,27 @@ class MedViewerEngine {
|
|
|
17325
17163
|
var _a2;
|
|
17326
17164
|
return ((_a2 = this.themeManager) == null ? void 0 : _a2.getColors()) ?? null;
|
|
17327
17165
|
}
|
|
17166
|
+
getThemeName() {
|
|
17167
|
+
var _a2;
|
|
17168
|
+
return ((_a2 = this.themeManager) == null ? void 0 : _a2.getThemeName()) ?? null;
|
|
17169
|
+
}
|
|
17170
|
+
/**
|
|
17171
|
+
* 为 Navigator 小图添加圆角样式
|
|
17172
|
+
*/
|
|
17173
|
+
injectNavigatorStyles() {
|
|
17174
|
+
const STYLE_ID2 = "med-navigator-styles";
|
|
17175
|
+
if (document.getElementById(STYLE_ID2))
|
|
17176
|
+
return;
|
|
17177
|
+
const style = document.createElement("style");
|
|
17178
|
+
style.id = STYLE_ID2;
|
|
17179
|
+
style.textContent = `
|
|
17180
|
+
.navigator {
|
|
17181
|
+
border-radius: 8px;
|
|
17182
|
+
overflow: hidden;
|
|
17183
|
+
}
|
|
17184
|
+
`;
|
|
17185
|
+
document.head.appendChild(style);
|
|
17186
|
+
}
|
|
17328
17187
|
/**
|
|
17329
17188
|
* 销毁引擎与所有插件
|
|
17330
17189
|
*/
|
|
@@ -17355,6 +17214,9 @@ class MedViewerEngine {
|
|
|
17355
17214
|
;
|
|
17356
17215
|
console.log(`[MedEngine] Locale changed to ${locale}`);
|
|
17357
17216
|
}
|
|
17217
|
+
getLocale() {
|
|
17218
|
+
return getCurrentLocale();
|
|
17219
|
+
}
|
|
17358
17220
|
}
|
|
17359
17221
|
const MedViewer = defineComponent({
|
|
17360
17222
|
name: "MedViewer",
|