From 93e7df27dfc7bcf98342c12e058485cb55ceeec5 Mon Sep 17 00:00:00 2001 From: Johannes Baiter Date: Fri, 27 Nov 2020 15:50:17 +0100 Subject: [PATCH] Fix fragment rendering on scaled canvases in bookview --- .../src/components/AnnotationsOverlay.test.js | 5 ++++- src/components/AnnotationsOverlay.js | 2 ++ src/lib/CanvasAnnotationDisplay.js | 8 +++++-- src/lib/CanvasWorld.js | 21 +++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/__tests__/src/components/AnnotationsOverlay.test.js b/__tests__/src/components/AnnotationsOverlay.test.js index ce3af69054..8357a4e970 100644 --- a/__tests__/src/components/AnnotationsOverlay.test.js +++ b/__tests__/src/components/AnnotationsOverlay.test.js @@ -183,7 +183,10 @@ describe('AnnotationsOverlay', () => { const context = wrapper.instance().osdCanvasOverlay.context2d; expect(context.strokeStyle).toEqual('yellow'); expect(context.lineWidth).toEqual(20); - expect(strokeRect).toHaveBeenCalledWith(10, 10, 100, 200); + expect(strokeRect.mock.calls[0][0]).toBeCloseTo(24.561); + expect(strokeRect.mock.calls[0][1]).toBeCloseTo(24.561); + expect(strokeRect.mock.calls[0][2]).toBeCloseTo(245.61); + expect(strokeRect.mock.calls[0][3]).toBeCloseTo(491.22); }); }); diff --git a/src/components/AnnotationsOverlay.js b/src/components/AnnotationsOverlay.js index dad600e201..879d23d45b 100644 --- a/src/components/AnnotationsOverlay.js +++ b/src/components/AnnotationsOverlay.js @@ -345,6 +345,7 @@ export class AnnotationsOverlay extends Component { annotation.resources.forEach((resource) => { if (!canvasWorld.canvasIds.includes(resource.targetId)) return; const offset = canvasWorld.offsetByCanvas(resource.targetId); + const scaleFactor = canvasWorld.scaleByCanvas(resource.targetId); const canvasAnnotationDisplay = new CanvasAnnotationDisplay({ hovered: hoveredAnnotationIds.includes(resource.id), offset, @@ -356,6 +357,7 @@ export class AnnotationsOverlay extends Component { }, }, resource, + scaleFactor, selected: selectedAnnotationId === resource.id, zoomRatio, }); diff --git a/src/lib/CanvasAnnotationDisplay.js b/src/lib/CanvasAnnotationDisplay.js index 8f949eae8f..69f0abf38f 100644 --- a/src/lib/CanvasAnnotationDisplay.js +++ b/src/lib/CanvasAnnotationDisplay.js @@ -5,7 +5,7 @@ export default class CanvasAnnotationDisplay { /** */ constructor({ - resource, palette, zoomRatio, offset, selected, hovered, + resource, palette, zoomRatio, offset, selected, hovered, scaleFactor, }) { this.resource = resource; this.palette = palette; @@ -13,6 +13,7 @@ export default class CanvasAnnotationDisplay { this.offset = offset; this.selected = selected; this.hovered = hovered; + this.scaleFactor = scaleFactor; } /** */ @@ -104,9 +105,12 @@ export default class CanvasAnnotationDisplay { /** */ fragmentContext() { - const fragment = this.resource.fragmentSelector; + let fragment = this.resource.fragmentSelector; fragment[0] += this.offset.x; fragment[1] += this.offset.y; + if (this.scaleFactor && this.scaleFactor !== 1) { + fragment = fragment.map(x => x * this.scaleFactor); + } let currentPalette; if (this.selected) { diff --git a/src/lib/CanvasWorld.js b/src/lib/CanvasWorld.js index cb1e0078ce..dc3a8f212f 100644 --- a/src/lib/CanvasWorld.js +++ b/src/lib/CanvasWorld.js @@ -28,9 +28,15 @@ export default class CanvasWorld { } const [dirX, dirY] = this.canvasDirection; + // Smallest dimension in the given direction const scale = dirY === 0 ? Math.min(...this.canvases.map(c => c.getHeight())) : Math.min(...this.canvases.map(c => c.getWidth())); + // Largest dimension in the given direction + const upScale = dirY === 0 + ? Math.max(...this.canvases.map(c => c.getHeight())) + : Math.max(...this.canvases.map(c => c.getWidth())); + let incX = 0; let incY = 0; @@ -38,15 +44,20 @@ export default class CanvasWorld { let canvasHeight = 0; let canvasWidth = 0; + // Factor to scale elements on the canvas by to give the + // world position + let worldScale = 1; if (!isNaN(canvas.aspectRatio)) { if (dirY === 0) { // constant height canvasHeight = scale; canvasWidth = Math.floor(scale * canvas.aspectRatio); + worldScale = upScale / canvas.getHeight(); } else { // constant width canvasWidth = scale; canvasHeight = Math.floor(scale * (1 / canvas.aspectRatio)); + worldScale = upScale / canvas.getWidth(); } } @@ -54,6 +65,7 @@ export default class CanvasWorld { canvas, height: canvasHeight, width: canvasWidth, + worldScale, x: incX, y: incY, }); @@ -198,6 +210,15 @@ export default class CanvasWorld { }; } + /** scaleByCanvas - Get the scaling factor for the given canvas. + * For a given element on the canvas, multiplying its offset coordinates + * (i.e. [elemenX + canvasX, elemY + canvasY, elemWidth, elemHeight]) by + * this factor returns the coordinates of the element in the world + */ + scaleByCanvas(canvasTarget) { + return this.canvasDimensions.find(c => c.canvas.id === canvasTarget).worldScale; + } + /** * worldBounds - calculates the "World" bounds. World in this case is canvases * lined up horizontally starting from left to right.