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.
@@ -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.id = styleId;
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
- return value.toFixed(2) + "μ" + unitSuffix;
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 pixelsToPerMeter(value, pixelsPerMeter) {
14157
- let nweValue = value / pixelsPerMeter;
14158
- return nweValue * 1e6;
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 == "commenting");
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")}:&nbsp;&nbsp;${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
- console.log("line", annotation.target.selector.value);
14177
- let lineDiv = document.createElement("div");
14178
- lineDiv.innerHTML = annotation.target.selector.value;
14179
- let line = lineDiv.getElementsByTagName("line")[0];
14180
- let x1 = pixelsToPerMeter(
14181
- Number(line.getAttribute("x1")),
14182
- pixelsPerMeter
14183
- );
14184
- let y1 = pixelsToPerMeter(
14185
- Number(line.getAttribute("y1")),
14186
- pixelsPerMeter
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")}:&nbsp;&nbsp;${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`)}:&nbsp;&nbsp;${getWithUnit(
14203
- len,
14204
- "m"
14205
- )}&nbsp;&nbsp; </p> <p >
14206
- ${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
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`)}:&nbsp;&nbsp;${getWithUnit(len, "m")}&nbsp;&nbsp;
14217
- </p>
14218
- </div>
14219
- </div>`;
14220
- }
14221
14243
  break;
14222
- case "rect":
14223
- let reg = new RegExp("xywh=pixel:", "g");
14224
- let str = annotation.target.selector.value.replace(reg, "");
14225
- let point = str.split(",");
14226
- const rectWidth = pixelsToPerMeter(Number(point[2]), pixelsPerMeter);
14227
- const rectHeight = pixelsToPerMeter(Number(point[3]), pixelsPerMeter);
14228
- const rectPerimeter = 2 * (rectWidth + rectHeight);
14229
- const rectArea = rectWidth * rectHeight;
14230
- if (firstTag) {
14231
- foreignObject.innerHTML = `
14232
- <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
14233
-
14234
- <div class="a9s-shape-label">
14235
- <p>
14236
- ${t(`annotation.width`)}:&nbsp;&nbsp;${getWithUnit(
14237
- rectWidth,
14238
- "m"
14239
- )}&nbsp;&nbsp;</p> <p>
14240
-
14241
-
14242
- ${t(`annotation.height`)}:&nbsp;&nbsp;${getWithUnit(
14243
- rectHeight,
14244
- "m"
14245
- )}&nbsp;&nbsp;</p> <p>
14246
- ${t(`annotation.perimeter`)}:&nbsp;&nbsp;${getWithUnit(
14247
- rectPerimeter,
14248
- "m"
14249
- )}&nbsp;&nbsp;</p> <p>
14250
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14251
- rectArea,
14252
- "m²"
14253
- )}&nbsp;&nbsp;</p> <p>
14254
- ${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
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`)}:&nbsp;&nbsp;${getWithUnit(
14264
- rectWidth,
14265
- "m"
14266
- )}&nbsp;&nbsp;</p> <p>
14267
- ${t(`annotation.height`)}:&nbsp;&nbsp;${getWithUnit(
14268
- rectHeight,
14269
- "m"
14270
- )}&nbsp;&nbsp;</p> <p>
14271
- ${t(`annotation.perimeter`)}:&nbsp;&nbsp;${getWithUnit(
14272
- rectPerimeter,
14273
- "m"
14274
- )}&nbsp;&nbsp;</p> <p>
14275
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(rectArea, "m²")}&nbsp;&nbsp;
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")}:&nbsp;&nbsp;${getWithUnit(rw, "m")}`,
14255
+ `${t("annotation.height")}:&nbsp;&nbsp;${getWithUnit(rh, "m")}`,
14256
+ `${t("annotation.perimeter")}:&nbsp;&nbsp;${getWithUnit(rp, "m")}`,
14257
+ `${t("annotation.area")}:&nbsp;&nbsp;${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`)}:&nbsp;&nbsp;${getWithUnit(
14299
- circleRadius,
14300
- "m"
14301
- )}&nbsp;&nbsp;</p><p>
14302
- ${t(`annotation.perimeter`)}:&nbsp;&nbsp;${getWithUnit(
14303
- circleCircumference,
14304
- "m"
14305
- )}&nbsp;&nbsp;</p><p>
14306
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14307
- circleArea,
14308
- "m²"
14309
- )}&nbsp;&nbsp;</p><p>
14310
- ${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
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`)}:&nbsp;&nbsp;${getWithUnit(
14320
- circleRadius,
14321
- "m"
14322
- )}&nbsp;&nbsp;</p><p>
14323
- ${t(`annotation.perimeter`)}:&nbsp;&nbsp;${getWithUnit(
14324
- circleCircumference,
14325
- "m"
14326
- )}&nbsp;&nbsp;</p><p>
14327
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14328
- circleArea,
14329
- "m²"
14330
- )}&nbsp;&nbsp;
14331
-
14332
- </p>
14333
- </div>
14334
- </div>`;
14335
- }
14336
14261
  break;
14337
- case "ellipse":
14338
- let ellipseDiv = document.createElement("div");
14339
- ellipseDiv.innerHTML = annotation.target.selector.value;
14340
- let ellipse = ellipseDiv.getElementsByTagName("ellipse")[0];
14341
- let rx = pixelsToPerMeter(
14342
- Number(ellipse.getAttribute("rx")),
14343
- pixelsPerMeter
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")}:&nbsp;&nbsp;${getWithUnit(r2, "m")}`,
14273
+ `${t("annotation.perimeter")}:&nbsp;&nbsp;${getWithUnit(circum, "m")}`,
14274
+ `${t("annotation.area")}:&nbsp;&nbsp;${getWithUnit(area, "m²")}`
14275
+ ],
14276
+ firstTag == null ? void 0 : firstTag.value
14344
14277
  );
14345
- let ry = pixelsToPerMeter(
14346
- Number(ellipse.getAttribute("ry")),
14347
- pixelsPerMeter
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")}:&nbsp;&nbsp;${getWithUnit(majorAxis, "m")}`,
14293
+ `${t("annotation.minorAxis")}:&nbsp;&nbsp;${getWithUnit(minorAxis, "m")}`,
14294
+ `${t("annotation.perimeter")}:&nbsp;&nbsp;${getWithUnit(perim, "m")}`,
14295
+ `${t("annotation.area")}:&nbsp;&nbsp;${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`)}:&nbsp;&nbsp;${getWithUnit(
14366
- majorAxis,
14367
- "m"
14368
- )}&nbsp;&nbsp;</p> <p>
14369
-
14370
- ${t(`annotation.minorAxis`)}:&nbsp;&nbsp;${getWithUnit(
14371
- minorAxis,
14372
- "m"
14373
- )}&nbsp;&nbsp;</p> <p>
14374
- ${t(`annotation.perimeter`)}:&nbsp;&nbsp;${getWithUnit(
14375
- ellipsePerimeter,
14376
- "m"
14377
- )}&nbsp;&nbsp;</p> <p>
14378
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14379
- ellipseArea,
14380
- "m²"
14381
- )}&nbsp;&nbsp;</p> <p>
14382
- ${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
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`)}:&nbsp;&nbsp;${getWithUnit(
14392
- majorAxis,
14393
- "m"
14394
- )}&nbsp;&nbsp;</p><p>
14395
-
14396
- ${t(`annotation.minorAxis`)}:&nbsp;&nbsp;${getWithUnit(
14397
- minorAxis,
14398
- "m"
14399
- )}&nbsp;&nbsp;</p><p>
14400
- ${t(`annotation.perimeter`)}:&nbsp;&nbsp;${getWithUnit(
14401
- ellipsePerimeter,
14402
- "m"
14403
- )}&nbsp;&nbsp;</p><p>
14404
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14405
- ellipseArea,
14406
- "m²"
14407
- )}&nbsp;&nbsp;
14408
- </p>
14409
- </div>
14410
- </div>`;
14411
- }
14412
14299
  break;
14413
- case "polygon":
14414
- let polygonDiv = document.createElement("div");
14415
- polygonDiv.innerHTML = annotation.target.selector.value;
14416
- let polygon = polygonDiv.getElementsByTagName("polygon")[0];
14417
- let pointsAttribute = polygon.getAttribute("points");
14418
- const points = pointsAttribute.split(" ").map((point2) => {
14419
- const [x3, y3] = point2.split(",").map(parseFloat);
14420
- return {
14421
- x: pixelsToPerMeter(x3, pixelsPerMeter),
14422
- y: pixelsToPerMeter(y3, pixelsPerMeter)
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 polygonPerimeter = 0;
14426
- for (let i2 = 0; i2 < points.length; i2++) {
14427
- const currentPoint = points[i2];
14428
- const nextPoint = points[(i2 + 1) % points.length];
14429
- const dx = nextPoint.x - currentPoint.x;
14430
- const dy = nextPoint.y - currentPoint.y;
14431
- polygonPerimeter += Math.sqrt(dx * dx + dy * dy);
14432
- }
14433
- let polygonArea = 0;
14434
- for (let i2 = 0; i2 < points.length; i2++) {
14435
- const currentPoint = points[i2];
14436
- const nextPoint = points[(i2 + 1) % points.length];
14437
- polygonArea += currentPoint.x * nextPoint.y - nextPoint.x * currentPoint.y;
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`)}:&nbsp;&nbsp;${getWithUnit(
14446
- polygonPerimeter,
14447
- "m"
14448
- )}&nbsp;&nbsp;</p> <p>
14449
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14450
- polygonArea,
14451
- "m²"
14452
- )}&nbsp;&nbsp;</p> <p>
14453
- ${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
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`)}:&nbsp;&nbsp;${getWithUnit(
14464
- polygonPerimeter,
14465
- "m"
14466
- )}&nbsp;&nbsp;</p><p>
14467
- ${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(
14468
- polygonArea,
14469
- "m²"
14470
- )}&nbsp;&nbsp;
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")}:&nbsp;&nbsp;${getWithUnit(polyPerim, "m")}`,
14322
+ `${t("annotation.area")}:&nbsp;&nbsp;${getWithUnit(polyArea, "m²")}`
14323
+ ],
14324
+ firstTag == null ? void 0 : firstTag.value
14325
+ );
14475
14326
  break;
14476
- case "freehand":
14477
- let computeFreehandArea = function(freehandPoints2) {
14478
- let sum = 0;
14479
- for (let i2 = 0; i2 < freehandPoints2.length - 1; i2++) {
14480
- const [x12, y12] = freehandPoints2[i2];
14481
- const [x22, y22] = freehandPoints2[i2 + 1];
14482
- sum += x12 * y22 - x22 * y12;
14483
- }
14484
- return Math.abs(sum / 2);
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
- let pos = properties.getPointAtLength(i2 / steps * pixelPerimeter);
14496
- freehandPoints.push([pos.x, pos.y]);
14497
- }
14498
- let areaPixel = computeFreehandArea(freehandPoints);
14499
- let realPerimeter = pixelsToPerMeter(pixelPerimeter, pixelsPerMeter);
14500
- let pixelToMicro = pixelsToPerMeter(1, pixelsPerMeter);
14501
- let realArea = areaPixel * pixelToMicro * pixelToMicro;
14502
- if (firstTag) {
14503
- foreignObject.innerHTML = `
14504
- <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
14505
- <div class="a9s-shape-label">
14506
- <p>${t(`annotation.length`)}:&nbsp;&nbsp;${getWithUnit(realPerimeter, "m")}</p>
14507
- <p>${t(`annotation.area`)}:&nbsp;&nbsp;${getWithUnit(realArea, "m²")}</p>
14508
- <p>${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}</p>
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`)}:&nbsp;&nbsp;${getWithUnit(realPerimeter, "m")}</p>
14516
- <p>${t(`annotation.area`)}:&nbsp;&nbsp;${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")}:&nbsp;&nbsp;${getWithUnit(realPerim, "m")}`,
14348
+ `${t("annotation.area")}:&nbsp;&nbsp;${getWithUnit(realArea, "")}`
14349
+ ],
14350
+ firstTag == null ? void 0 : firstTag.value
14351
+ );
14520
14352
  break;
14353
+ }
14521
14354
  default:
14522
14355
  if (firstTag) {
14523
- foreignObject.innerHTML = `
14524
- <div xmlns="http://www.w3.org/1999/xhtml" class="a9s-shape-label-wrapper">
14525
- <div class="a9s-shape-label">
14526
- <p>
14527
- ${t(`annotation.remark`)}:&nbsp;&nbsp;${firstTag.value}&nbsp;&nbsp;
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
- const injectShapeLabelStyles = () => {
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
- var _a2;
16290
+ if (!engine.selection) {
16291
+ console.warn("[MedToolbar] 截图插件未启用,请在 plugins.selection 中开启");
16292
+ hide();
16293
+ return;
16294
+ }
16469
16295
  console.log("selection toggleState");
16470
- (_a2 = engine.selection) == null ? void 0 : _a2.toggleState();
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",