@niivue/niivue 0.26.2 → 0.28.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.
package/dist/niivue.es.js CHANGED
@@ -111481,6 +111481,8 @@ function Niivue(options = {}) {
111481
111481
  trustCalMinMax: true,
111482
111482
  clipPlaneHotKey: "KeyC",
111483
111483
  viewModeHotKey: "KeyV",
111484
+ doubleTouchTimeout: 500,
111485
+ longTouchTimeout: 1e3,
111484
111486
  keyDebounceTime: 50,
111485
111487
  isNearestInterpolation: false,
111486
111488
  isAtlasOutline: false,
@@ -111495,13 +111497,29 @@ function Niivue(options = {}) {
111495
111497
  isCornerOrientationText: false,
111496
111498
  sagittalNoseLeft: false,
111497
111499
  isSliceMM: false,
111500
+ isHighResolutionCapable: false,
111498
111501
  logging: false,
111499
111502
  loadingText: "waiting for images...",
111500
111503
  dragAndDropEnabled: true,
111501
111504
  drawingEnabled: false,
111502
111505
  penValue: 1,
111503
111506
  isFilledPen: false,
111504
- thumbnail: ""
111507
+ thumbnail: "",
111508
+ maxDrawUndoBitmaps: 8,
111509
+ onLocationChange: () => {
111510
+ },
111511
+ onIntensityChange: () => {
111512
+ },
111513
+ onImageLoaded: () => {
111514
+ },
111515
+ onError: () => {
111516
+ },
111517
+ onInfo: () => {
111518
+ },
111519
+ onWarn: () => {
111520
+ },
111521
+ onDebug: () => {
111522
+ }
111505
111523
  };
111506
111524
  this.canvas = null;
111507
111525
  this.gl = null;
@@ -111509,8 +111527,6 @@ function Niivue(options = {}) {
111509
111527
  this.volumeTexture = null;
111510
111528
  this.drawTexture = null;
111511
111529
  this.drawBitmap = null;
111512
- this.maxDrawUndoBitmaps = 8;
111513
- this.currentDrawUndoBitmap = this.maxDrawUndoBitmaps;
111514
111530
  this.drawUndoBitmaps = [];
111515
111531
  this.drawOpacity = 0.8;
111516
111532
  this.colorbarHeight = 0;
@@ -111580,6 +111596,10 @@ function Niivue(options = {}) {
111580
111596
  this.scene.prevY = 0;
111581
111597
  this.scene.currX = 0;
111582
111598
  this.scene.currY = 0;
111599
+ this.currentTouchTime = 0;
111600
+ this.lastTouchTime = 0;
111601
+ this.touchTimer = null;
111602
+ this.doubleTouch = false;
111583
111603
  this.back = {};
111584
111604
  this.overlays = [];
111585
111605
  this.volumes = [];
@@ -111601,10 +111621,7 @@ function Niivue(options = {}) {
111601
111621
  this.volumeObject3D = null;
111602
111622
  this.pivot3D = [0, 0, 0];
111603
111623
  this.furthestFromPivot = 10;
111604
- this.intensityRange$ = new Subject();
111605
- this.scene.location$ = new Subject();
111606
111624
  this.scene.loading$ = new Subject();
111607
- this.imageLoaded$ = new Subject();
111608
111625
  this.currentClipPlaneIndex = 0;
111609
111626
  this.lastCalled = new Date().getTime();
111610
111627
  this.multiTouchGesture = false;
@@ -111659,6 +111676,7 @@ function Niivue(options = {}) {
111659
111676
  for (let prop in this.defaults) {
111660
111677
  this.opts[prop] = options[prop] === void 0 ? this.defaults[prop] : options[prop];
111661
111678
  }
111679
+ this.currentDrawUndoBitmap = this.opts.maxDrawUndoBitmaps;
111662
111680
  if (this.opts.drawingEnabled) {
111663
111681
  this.createEmptyDrawing();
111664
111682
  }
@@ -111668,10 +111686,7 @@ function Niivue(options = {}) {
111668
111686
  this.loadingText = this.opts.loadingText;
111669
111687
  log.setLogLevel(this.opts.logging);
111670
111688
  this.eventsToSubjects = {
111671
- location: this.scene.location$,
111672
- loading: this.scene.loading$,
111673
- imageLoaded: this.imageLoaded$,
111674
- intensityRange: this.intensityRange$
111689
+ loading: this.scene.loading$
111675
111690
  };
111676
111691
  this.subscriptions = [];
111677
111692
  }
@@ -111852,8 +111867,12 @@ Niivue.prototype.arrayEquals = function(a, b) {
111852
111867
  Niivue.prototype.resizeListener = function() {
111853
111868
  this.canvas.style.width = "100%";
111854
111869
  this.canvas.style.height = "100%";
111855
- this.canvas.width = this.canvas.offsetWidth;
111856
- this.canvas.height = this.canvas.offsetHeight;
111870
+ let dpr = 1;
111871
+ if (this.opts.isHighResolutionCapable)
111872
+ dpr = window.devicePixelRatio || 1;
111873
+ this.canvas.width = this.canvas.offsetWidth * dpr;
111874
+ this.canvas.height = this.canvas.offsetHeight * dpr;
111875
+ console.log("RESIZE" + dpr);
111857
111876
  this.drawScene();
111858
111877
  };
111859
111878
  Niivue.prototype.getRelativeMousePosition = function(event, target) {
@@ -111967,7 +111986,7 @@ Niivue.prototype.calculateNewRange = function(volIdx = 0) {
111967
111986
  var mxScale = intensityRaw2Scaled(hdr, hi);
111968
111987
  this.volumes[volIdx].cal_min = mnScale;
111969
111988
  this.volumes[volIdx].cal_max = mxScale;
111970
- this.intensityRange$.next(this.volumes[volIdx]);
111989
+ this.opts.onIntensityChange(this.volumes[volIdx]);
111971
111990
  };
111972
111991
  Niivue.prototype.mouseUpListener = function() {
111973
111992
  this.scene.mousedown = false;
@@ -111997,7 +112016,27 @@ Niivue.prototype.checkMultitouch = function(e) {
111997
112016
  };
111998
112017
  Niivue.prototype.touchStartListener = function(e) {
111999
112018
  e.preventDefault();
112019
+ if (!this.touchTimer) {
112020
+ this.touchTimer = setTimeout(() => {
112021
+ this.resetBriCon(e);
112022
+ }, this.opts.longTouchTimeout);
112023
+ }
112000
112024
  this.scene.touchdown = true;
112025
+ this.currentTouchTime = new Date().getTime();
112026
+ let timeSinceTouch = this.currentTouchTime - this.lastTouchTime;
112027
+ if (timeSinceTouch < this.opts.doubleTouchTimeout && timeSinceTouch > 0) {
112028
+ this.doubleTouch = true;
112029
+ this.dragStart[0] = e.targetTouches[0].clientX - e.target.getBoundingClientRect().left;
112030
+ this.dragStart[1] = e.targetTouches[0].clientY - e.target.getBoundingClientRect().top;
112031
+ this.resetBriCon(e);
112032
+ this.lastTouchTime = this.currentTouchTime;
112033
+ return;
112034
+ } else {
112035
+ this.doubleTouch = false;
112036
+ this.dragStart = [0, 0];
112037
+ this.dragEnd = [0, 0];
112038
+ this.lastTouchTime = this.currentTouchTime;
112039
+ }
112001
112040
  if (this.scene.touchdown && e.touches.length < 2) {
112002
112041
  this.multiTouchGesture = false;
112003
112042
  } else {
@@ -112005,10 +112044,23 @@ Niivue.prototype.touchStartListener = function(e) {
112005
112044
  }
112006
112045
  setTimeout(this.checkMultitouch.bind(this), 1, e);
112007
112046
  };
112008
- Niivue.prototype.touchEndListener = function() {
112047
+ Niivue.prototype.touchEndListener = function(e) {
112048
+ e.preventDefault();
112009
112049
  this.scene.touchdown = false;
112010
112050
  this.lastTwoTouchDistance = 0;
112011
112051
  this.multiTouchGesture = false;
112052
+ if (this.touchTimer) {
112053
+ clearTimeout(this.touchTimer);
112054
+ this.touchTimer = null;
112055
+ }
112056
+ if (this.isDragging) {
112057
+ this.isDragging = false;
112058
+ if (this.opts.isDragShowsMeasurementTool)
112059
+ return;
112060
+ this.calculateNewRange();
112061
+ this.refreshLayers(this.volumes[0], 0, this.volumes.length);
112062
+ }
112063
+ this.drawScene();
112012
112064
  };
112013
112065
  Niivue.prototype.mouseMoveListener = function(e) {
112014
112066
  if (this.scene.mousedown) {
@@ -112026,11 +112078,22 @@ Niivue.prototype.mouseMoveListener = function(e) {
112026
112078
  }
112027
112079
  };
112028
112080
  Niivue.prototype.resetBriCon = function(msg2 = null) {
112081
+ if (this.isDragging)
112082
+ return;
112029
112083
  let isRender = false;
112030
112084
  if (this.sliceType === this.sliceTypeRender)
112031
112085
  isRender = true;
112086
+ let x2 = 0;
112087
+ let y = 0;
112032
112088
  if (msg2 !== null) {
112033
- if (this.inRenderTile(msg2.offsetX, msg2.offsetY) >= 0)
112089
+ if (msg2.targetTouches !== void 0) {
112090
+ x2 = msg2.targetTouches[0].clientX - msg2.target.getBoundingClientRect().left;
112091
+ y = msg2.targetTouches[0].clientY - msg2.target.getBoundingClientRect().top;
112092
+ } else {
112093
+ x2 = msg2.offsetX;
112094
+ y = msg2.offsetY;
112095
+ }
112096
+ if (this.inRenderTile(x2, y) >= 0)
112034
112097
  isRender = true;
112035
112098
  }
112036
112099
  if (isRender) {
@@ -112039,15 +112102,24 @@ Niivue.prototype.resetBriCon = function(msg2 = null) {
112039
112102
  this.drawScene();
112040
112103
  return;
112041
112104
  }
112105
+ if (this.doubleTouch)
112106
+ return;
112042
112107
  this.volumes[0].cal_min = this.volumes[0].robust_min;
112043
112108
  this.volumes[0].cal_max = this.volumes[0].robust_max;
112044
- this.intensityRange$.next(this.volumes[0]);
112109
+ this.opts.onIntensityChange(this.volumes[0]);
112045
112110
  this.refreshLayers(this.volumes[0], 0, this.volumes.length);
112046
112111
  this.drawScene();
112047
112112
  };
112048
112113
  Niivue.prototype.touchMoveListener = function(e) {
112049
112114
  if (this.scene.touchdown && e.touches.length < 2) {
112050
112115
  var rect = this.canvas.getBoundingClientRect();
112116
+ this.isDragging = true;
112117
+ if (this.doubleTouch && this.isDragging) {
112118
+ this.dragEnd[0] = e.targetTouches[0].clientX - e.target.getBoundingClientRect().left;
112119
+ this.dragEnd[1] = e.targetTouches[0].clientY - e.target.getBoundingClientRect().top;
112120
+ this.drawScene();
112121
+ return;
112122
+ }
112051
112123
  this.mouseClick(e.touches[0].clientX - rect.left, e.touches[0].clientY - rect.top);
112052
112124
  this.mouseMove(e.touches[0].clientX - rect.left, e.touches[0].clientY - rect.top);
112053
112125
  } else {
@@ -112147,6 +112219,9 @@ Niivue.prototype.keyDownListener = function(e) {
112147
112219
  Niivue.prototype.wheelListener = function(e) {
112148
112220
  e.preventDefault();
112149
112221
  e.stopPropagation();
112222
+ if (this.thumbnailVisible) {
112223
+ return;
112224
+ }
112150
112225
  var rect = this.canvas.getBoundingClientRect();
112151
112226
  if (e.deltaY < 0) {
112152
112227
  this.sliceScroll2D(-0.01, e.clientX - rect.left, e.clientY - rect.top);
@@ -112293,17 +112368,23 @@ Niivue.prototype.setSliceMM = function(isSliceMM) {
112293
112368
  Niivue.prototype.getRadiologicalConvention = function() {
112294
112369
  return this.opts.isRadiologicalConvention;
112295
112370
  };
112371
+ Niivue.prototype.setHighResolutionCapable = function(isHighResolutionCapable) {
112372
+ this.opts.isHighResolutionCapable = isHighResolutionCapable;
112373
+ console.log("HighDPI feature is experimental");
112374
+ this.resizeListener();
112375
+ this.drawScene();
112376
+ };
112296
112377
  Niivue.prototype.addVolume = function(volume) {
112297
112378
  this.volumes.push(volume);
112298
112379
  let idx = this.volumes.length === 1 ? 0 : this.volumes.length - 1;
112299
112380
  this.setVolume(volume, idx);
112300
- this.imageLoaded$.next(volume);
112381
+ this.opts.onImageLoaded(volume);
112301
112382
  };
112302
112383
  Niivue.prototype.addMesh = function(mesh) {
112303
112384
  this.meshes.push(mesh);
112304
112385
  let idx = this.meshes.length === 1 ? 0 : this.meshes.length - 1;
112305
112386
  this.setMesh(mesh, idx);
112306
- this.imageLoaded$.next(mesh);
112387
+ this.opts.onImageLoaded(mesh);
112307
112388
  };
112308
112389
  Niivue.prototype.getVolumeIndexByID = function(id) {
112309
112390
  let n = this.volumes.length;
@@ -112389,12 +112470,12 @@ Niivue.prototype.drawAddUndoBitmap = async function(fnm) {
112389
112470
  return false;
112390
112471
  }
112391
112472
  this.currentDrawUndoBitmap++;
112392
- if (this.currentDrawUndoBitmap >= this.maxDrawUndoBitmaps)
112473
+ if (this.currentDrawUndoBitmap >= this.opts.maxDrawUndoBitmaps)
112393
112474
  this.currentDrawUndoBitmap = 0;
112394
112475
  this.drawUndoBitmaps[this.currentDrawUndoBitmap] = encodeRLE(this.drawBitmap);
112395
112476
  };
112396
112477
  Niivue.prototype.drawClearAllUndoBitmaps = async function() {
112397
- this.currentDrawUndoBitmap = this.maxDrawUndoBitmaps;
112478
+ this.currentDrawUndoBitmap = this.opts.maxDrawUndoBitmaps;
112398
112479
  if (this.drawUndoBitmaps.length < 1)
112399
112480
  return;
112400
112481
  for (let i2 = this.drawUndoBitmaps.length - 1; i2 >= 0; i2--)
@@ -113672,6 +113753,8 @@ Niivue.prototype.init = async function() {
113672
113753
  }
113673
113754
  this.updateGLVolume();
113674
113755
  this.initialized = true;
113756
+ if (this.opts.isHighResolutionCapable)
113757
+ this.resizeListener();
113675
113758
  this.drawScene();
113676
113759
  return this;
113677
113760
  };
@@ -114173,15 +114256,16 @@ Niivue.prototype.mouseClick = function(x2, y, posChange = 0, isDelta = true) {
114173
114256
  posFuture = 0;
114174
114257
  this.scene.crosshairPos[2 - axCorSag] = posFuture;
114175
114258
  this.drawScene();
114176
- this.scene.location$.next({
114259
+ this.opts.onLocationChange({
114177
114260
  mm: this.frac2mm(this.scene.crosshairPos),
114178
114261
  vox: this.frac2vox(this.scene.crosshairPos),
114179
114262
  frac: this.scene.crosshairPos,
114263
+ xy: [x2, y],
114180
114264
  values: this.volumes.map((v) => {
114181
114265
  let mm = this.frac2mm(this.scene.crosshairPos);
114182
114266
  let vox = v.mm2vox(mm);
114183
114267
  let val = v.getValue(...vox);
114184
- return val;
114268
+ return { name: v.name, value: val, id: v.id, mm, vox };
114185
114269
  })
114186
114270
  });
114187
114271
  return;
@@ -114208,15 +114292,16 @@ Niivue.prototype.mouseClick = function(x2, y, posChange = 0, isDelta = true) {
114208
114292
  this.refreshDrawing(false);
114209
114293
  }
114210
114294
  this.drawScene();
114211
- this.scene.location$.next({
114295
+ this.opts.onLocationChange({
114212
114296
  mm: this.frac2mm(this.scene.crosshairPos),
114213
114297
  vox: this.frac2vox(this.scene.crosshairPos),
114214
114298
  frac: this.scene.crosshairPos,
114299
+ xy: [x2, y],
114215
114300
  values: this.volumes.map((v) => {
114216
114301
  let mm = this.frac2mm(this.scene.crosshairPos);
114217
114302
  let vox = v.mm2vox(mm);
114218
114303
  let val = v.getValue(...vox);
114219
- return val;
114304
+ return { name: v.name, value: val, id: v.id, mm, vox };
114220
114305
  })
114221
114306
  });
114222
114307
  return;
@@ -114614,7 +114699,7 @@ function deg2rad(deg) {
114614
114699
  }
114615
114700
  Niivue.prototype.calculateMvpMatrix2D = function(leftTopWidthHeight, mn, mx, clipTolerance = Infinity, clipDepth = 0, azimuth = null, elevation = null, isRadiolgical) {
114616
114701
  let gl = this.gl;
114617
- gl.viewport(leftTopWidthHeight[0], this.gl.canvas.clientHeight - (leftTopWidthHeight[1] + leftTopWidthHeight[3]), leftTopWidthHeight[2], leftTopWidthHeight[3]);
114702
+ gl.viewport(leftTopWidthHeight[0], this.gl.canvas.height - (leftTopWidthHeight[1] + leftTopWidthHeight[3]), leftTopWidthHeight[2], leftTopWidthHeight[3]);
114618
114703
  let left = mn[0];
114619
114704
  let right = mx[0];
114620
114705
  let leftTopMM = [left, mn[1]];
@@ -115643,7 +115728,7 @@ Niivue.prototype.canvasPos2frac = function(canvasPos) {
115643
115728
  return [-1, -1, -1];
115644
115729
  };
115645
115730
  Niivue.prototype.scaleSlice = function(w, h, widthPadPixels = 0, heightPadPixels = 0) {
115646
- let canvasW = this.gl.canvas.clientWidth - widthPadPixels;
115731
+ let canvasW = this.canvas.width - widthPadPixels;
115647
115732
  let canvasH = this.effectiveCanvasHeight() - heightPadPixels;
115648
115733
  let scalePix = canvasW / w;
115649
115734
  if (h * scalePix > canvasH)