Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(still image): drawing a region does not break mouse nav on canvas (DEV-4445) #2024

Merged
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Injectable } from '@angular/core';
import { Point2D } from '@dasch-swiss/dsp-js';
import { AppError } from '@dasch-swiss/vre/shared/app-error-handler';
import { AccessTokenService } from '@dasch-swiss/vre/shared/app-session';
import OpenSeadragon from 'openseadragon';
import { Subject } from 'rxjs';
import { osdViewerConfig } from './osd-viewer.config';
import { StillImageHelper } from './still-image-helper';

interface Overlay {
startPoint: Point2D;
Expand All @@ -24,6 +24,12 @@ export class OpenSeaDragonService {

private _viewer!: OpenSeadragon.Viewer;

private _drawing = false;

get drawing() {
return this._drawing;
}

private _rectangleInDrawing: {
overlayElement: HTMLElement;
startPos: OpenSeadragon.Point;
Expand All @@ -50,77 +56,94 @@ export class OpenSeaDragonService {
}

this._viewer = new OpenSeadragon.Viewer(viewerConfig);
this._trackClickEvents(this._viewer);
this._addCustomHandlers(this._viewer);
}

toggleDrawing(): void {
this._drawing = !this._drawing;

if (this._drawing) {
this._disableDefaultDragging();
this._disableDoubleClickZooming();
} else {
this._enableDefaultDragging();
this._enableDoubleClickZooming();
}
}

private _disableDefaultDragging(): void {
this._viewer.addHandler('canvas-drag', StillImageHelper.preventDefault);
}

private _disableDoubleClickZooming(): void {
this._viewer.addHandler('canvas-double-click', StillImageHelper.preventDefault);
}

private _enableDefaultDragging(): void {
this._viewer.removeHandler('canvas-drag', StillImageHelper.preventDefault);
}

private _enableDoubleClickZooming(): void {
this._viewer.removeHandler('canvas-double-click', StillImageHelper.preventDefault);
}

zoom(direction: 1 | -1) {
this._viewer.viewport.zoomBy(1 + direction * this.ZOOM_FACTOR);
}

private _trackClickEvents(viewer: OpenSeadragon.Viewer) {
return new OpenSeadragon.MouseTracker({
element: viewer.canvas,
pressHandler: event => {
if (viewer.isMouseNavEnabled()) {
return;
}

const overlayElement: HTMLElement = document.createElement('div');
overlayElement.style.background = this._OVERLAY_COLOR;
const viewportPos = viewer.viewport.pointFromPixel((event as OpenSeadragon.ViewerEvent).position!);
viewer.addOverlay(overlayElement, new OpenSeadragon.Rect(viewportPos.x, viewportPos.y, 0, 0));
this._rectangleInDrawing = {
overlayElement,
startPos: viewportPos,
};
},
dragHandler: event => {
if (viewer.isMouseNavEnabled()) {
return;
}

if (!this._rectangleInDrawing) {
throw new AppError('Rectangle is not set');
}

const viewPortPos = viewer.viewport.pointFromPixel((event as OpenSeadragon.ViewerEvent).position!);
const diffX = viewPortPos.x - this._rectangleInDrawing.startPos.x;
const diffY = viewPortPos.y - this._rectangleInDrawing.startPos.y;
const location = new OpenSeadragon.Rect(
Math.min(this._rectangleInDrawing.startPos.x, this._rectangleInDrawing.startPos.x + diffX),
Math.min(this._rectangleInDrawing.startPos.y, this._rectangleInDrawing.startPos.y + diffY),
Math.abs(diffX),
Math.abs(diffY)
);

viewer.updateOverlay(this._rectangleInDrawing.overlayElement, location);
this._rectangleInDrawing.endPos = viewPortPos;
},
releaseHandler: () => {
if (viewer.isMouseNavEnabled()) {
return;
}

if (!this._rectangleInDrawing) {
throw new AppError('Rectangle is not set');
}

if (!this._rectangleInDrawing.endPos) {
return;
}

const imageSize = viewer.world.getItemAt(0).getContentSize();
const startPoint = viewer.viewport.viewportToImageCoordinates(this._rectangleInDrawing.startPos);
const endPoint = viewer.viewport.viewportToImageCoordinates(this._rectangleInDrawing.endPos);
this._createdRectangleSubject.next({
startPoint,
endPoint,
imageSize,
overlay: this._rectangleInDrawing.overlayElement,
});

this._rectangleInDrawing = null;
},
private _addCustomHandlers(viewer: OpenSeadragon.Viewer): void {
viewer.addHandler('canvas-press', event => this._onCanvasPress(event, viewer));
viewer.addHandler('canvas-drag', event => this._onCanvasDrag(event, viewer));
viewer.addHandler('canvas-release', () => this._onCanvasRelease(viewer));
}

private _onCanvasPress(event: OpenSeadragon.ViewerEvent, viewer: OpenSeadragon.Viewer): void {
if (!this._drawing) {
return;
}
const overlayElement: HTMLElement = document.createElement('div');
overlayElement.style.background = this._OVERLAY_COLOR;
const viewportPos = viewer.viewport.pointFromPixel((event as OpenSeadragon.ViewerEvent).position!);
viewer.addOverlay(overlayElement, new OpenSeadragon.Rect(viewportPos.x, viewportPos.y, 0, 0));
this._rectangleInDrawing = {
overlayElement,
startPos: viewportPos,
};
}

private _onCanvasDrag(event: OpenSeadragon.ViewerEvent, viewer: OpenSeadragon.Viewer): void {
if (!this._drawing || !this._rectangleInDrawing) {
return;
}
const viewPortPos = viewer.viewport.pointFromPixel((event as OpenSeadragon.ViewerEvent).position!);
const diffX = viewPortPos.x - this._rectangleInDrawing.startPos.x;
const diffY = viewPortPos.y - this._rectangleInDrawing.startPos.y;
const location = new OpenSeadragon.Rect(
Math.min(this._rectangleInDrawing.startPos.x, this._rectangleInDrawing.startPos.x + diffX),
Math.min(this._rectangleInDrawing.startPos.y, this._rectangleInDrawing.startPos.y + diffY),
Math.abs(diffX),
Math.abs(diffY)
);

viewer.updateOverlay(this._rectangleInDrawing.overlayElement, location);
this._rectangleInDrawing.endPos = viewPortPos;
}

private _onCanvasRelease(viewer: OpenSeadragon.Viewer): void {
if (!this._drawing || !this._rectangleInDrawing?.endPos) {
return;
}

const imageSize = viewer.world.getItemAt(0).getContentSize();
const startPoint = viewer.viewport.viewportToImageCoordinates(this._rectangleInDrawing.startPos);
const endPoint = viewer.viewport.viewportToImageCoordinates(this._rectangleInDrawing.endPos);
this._createdRectangleSubject.next({
startPoint,
endPoint,
imageSize,
overlay: this._rectangleInDrawing.overlayElement,
});
this._rectangleInDrawing = null;
this.toggleDrawing();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ export class OsdDrawerService implements OnDestroy {
)
.pipe(
switchMap(({ data, overlay }) => {
this._osd.viewer.setMouseNavEnabled(true);
this._osd.viewer.removeOverlay(overlay.overlay);
this._cdr.detectChanges();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
RegionGeometry,
} from '@dasch-swiss/dsp-js';
import { DspResource } from '@dasch-swiss/vre/shared/app-common';
import OpenSeadragon from 'openseadragon';
import { Region } from '../region';
import { GeometryForRegion } from './geometry-for-region';
import { PolygonsForRegion } from './polygons-for-region.interface';
Expand Down Expand Up @@ -155,4 +156,8 @@ export class StillImageHelper {

return w * h;
}

static preventDefault(event: OpenSeadragon.ViewerEvent): void {
event.preventDefaultAction = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
matTooltip="Draw Region"
[disabled]="!userCanEdit || isReadStillImageExternalFileValue"
(click)="toggleDrawMode()"
[class.active]="osd.viewer.isMouseNavEnabled()">
[class.active]="osd.drawing">
<mat-icon svgIcon="draw_region_icon"></mat-icon>
</button>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class StillImageToolbarComponent {
}

toggleDrawMode(): void {
this.osd.viewer.setMouseNavEnabled(!this.osd.viewer.isMouseNavEnabled());
this.osd.toggleDrawing();
}

download() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ import { StillImageHelper } from './still-image-helper';

@Component({
selector: 'app-still-image',
template: ` <div
class="osd-container"
[class.drawing]="isViewInitialized && !osdService.viewer.isMouseNavEnabled()"
#osdViewer>
template: ` <div class="osd-container" [class.drawing]="isViewInitialized && osdService.drawing" #osdViewer>
<div *ngIf="compoundMode">
<app-compound-arrow-navigation [forwardNavigation]="false" class="arrow" />
<app-compound-arrow-navigation [forwardNavigation]="true" class="arrow" />
Expand Down
Loading