diff --git a/__tests__/src/components/OpenSeadragonViewer.test.js b/__tests__/src/components/OpenSeadragonViewer.test.js index 8d42ce59c0547d54456ed7b833a9cbc0500c85cb..dc5637a9637dd92cd5e2e2dc2b1649b33d79ac89 100644 --- a/__tests__/src/components/OpenSeadragonViewer.test.js +++ b/__tests__/src/components/OpenSeadragonViewer.test.js @@ -285,6 +285,8 @@ describe('OpenSeadragonViewer', () => { it('calls the OSD viewport panTo and zoomTo with the component state and forces a redraw', () => { const panTo = jest.fn(); const zoomTo = jest.fn(); + const setFlip = jest.fn(); + const setRotation = jest.fn(); const forceRedraw = jest.fn(); wrapper.setState({ @@ -293,22 +295,37 @@ describe('OpenSeadragonViewer', () => { viewport: { centerSpringX: { target: { value: 10 } }, centerSpringY: { target: { value: 10 } }, + getFlip: () => false, + getRotation: () => (0), panTo, + setFlip, + setRotation, zoomSpring: { target: { value: 1 } }, zoomTo, }, }, }); - wrapper.setProps({ viewerConfig: { x: 0.5, y: 0.5, zoom: 0.1 } }); - wrapper.setProps({ viewerConfig: { x: 1, y: 0, zoom: 0.5 } }); + wrapper.setProps({ + viewerConfig: { + flip: false, rotation: 90, x: 0.5, y: 0.5, zoom: 0.1, + }, + }); + + wrapper.setProps({ + viewerConfig: { + flip: true, rotation: 0, x: 1, y: 0, zoom: 0.5, + }, + }); expect(panTo).toHaveBeenCalledWith( - { x: 1, y: 0, zoom: 0.5 }, false, + expect.objectContaining({ x: 1, y: 0, zoom: 0.5 }), false, ); expect(zoomTo).toHaveBeenCalledWith( - 0.5, { x: 1, y: 0, zoom: 0.5 }, false, + 0.5, expect.objectContaining({ x: 1, y: 0, zoom: 0.5 }), false, ); + expect(setRotation).toHaveBeenCalledWith(90); + expect(setFlip).toHaveBeenCalledWith(true); expect(forceRedraw).not.toHaveBeenCalled(); }); }); @@ -320,6 +337,8 @@ describe('OpenSeadragonViewer', () => { viewport: { centerSpringX: { target: { value: 1 } }, centerSpringY: { target: { value: 0 } }, + getFlip: () => false, + getRotation: () => 90, zoomSpring: { target: { value: 0.5 } }, }, }, @@ -327,7 +346,9 @@ describe('OpenSeadragonViewer', () => { expect(updateViewport).toHaveBeenCalledWith( 'base', - { x: 1, y: 0, zoom: 0.5 }, + { + flip: false, rotation: 90, x: 1, y: 0, zoom: 0.5, + }, ); }); }); diff --git a/__tests__/src/lib/OpenSeadragonCanvasOverlay.test.js b/__tests__/src/lib/OpenSeadragonCanvasOverlay.test.js index 73ca48ab1fba3ea94a5cc12a2ed777aad4c181d2..23a785b56d3cbaf971b7f3748e6678045a16de64 100644 --- a/__tests__/src/lib/OpenSeadragonCanvasOverlay.test.js +++ b/__tests__/src/lib/OpenSeadragonCanvasOverlay.test.js @@ -17,12 +17,15 @@ describe('OpenSeadragonCanvasOverlay', () => { clientWidth: 200, }, viewport: { - getBounds: jest.fn(() => ({ + getBoundsNoRotate: jest.fn(() => ({ height: 300, width: 200, x: 40, y: 80, })), + getCenter: () => ({ x: 0, y: 0 }), + getFlip: () => false, + getRotation: () => 0, getZoom: jest.fn(() => (0.75)), }, world: { @@ -89,7 +92,7 @@ describe('OpenSeadragonCanvasOverlay', () => { clientWidth: 200, }, viewport: { - getBounds: jest.fn(() => (new OpenSeadragon.Rect(0, 0, 200, 200))), + getBoundsNoRotate: jest.fn(() => (new OpenSeadragon.Rect(0, 0, 200, 200))), }, world: { getItemAt: jest.fn(), diff --git a/src/components/OpenSeadragonViewer.js b/src/components/OpenSeadragonViewer.js index f1fcd154b5ac517a6b3133f8c98ee43baff3eba0..7dbb00736046ea794b828b30aa52272b3fbad94a 100644 --- a/src/components/OpenSeadragonViewer.js +++ b/src/components/OpenSeadragonViewer.js @@ -82,6 +82,8 @@ export class OpenSeadragonViewer extends Component { if (viewerConfig) { viewer.viewport.panTo(viewerConfig, true); viewer.viewport.zoomTo(viewerConfig.zoom, viewerConfig, true); + viewerConfig.degrees !== undefined && viewer.viewport.setRotation(viewerConfig.degrees); + viewerConfig.flip !== undefined && viewer.viewport.setFlip(viewerConfig.flip); } this.addAllImageSources(!(viewerConfig)); @@ -102,11 +104,19 @@ export class OpenSeadragonViewer extends Component { if (viewerConfig.x !== viewport.centerSpringX.target.value || viewerConfig.y !== viewport.centerSpringY.target.value) { - viewer.viewport.panTo(viewerConfig, false); + viewport.panTo(viewerConfig, false); } if (viewerConfig.zoom !== viewport.zoomSpring.target.value) { - viewer.viewport.zoomTo(viewerConfig.zoom, viewerConfig, false); + viewport.zoomTo(viewerConfig.zoom, viewerConfig, false); + } + + if (viewerConfig.rotation !== viewport.getRotation()) { + viewport.setRotation(viewerConfig.rotation); + } + + if (viewerConfig.flip !== viewport.getFlip()) { + viewport.setFlip(viewerConfig.flip); } } } @@ -129,6 +139,8 @@ export class OpenSeadragonViewer extends Component { const { viewport } = event.eventSource; updateViewport(windowId, { + flip: viewport.getFlip(), + rotation: viewport.getRotation(), x: Math.round(viewport.centerSpringX.target.value), y: Math.round(viewport.centerSpringY.target.value), zoom: viewport.zoomSpring.target.value, diff --git a/src/lib/OpenSeadragonCanvasOverlay.js b/src/lib/OpenSeadragonCanvasOverlay.js index 4e23466cda85e50e81d8aecc2e2a0ac00be5e6af..d10bd5014b0da1dc612f778caa049449cda5b8da 100644 --- a/src/lib/OpenSeadragonCanvasOverlay.js +++ b/src/lib/OpenSeadragonCanvasOverlay.js @@ -58,7 +58,7 @@ export default class OpenSeadragonCanvasOverlay { } this.viewportOrigin = new OpenSeadragon.Point(0, 0); - const boundsRect = this.viewer.viewport.getBounds(true); + const boundsRect = this.viewer.viewport.getBoundsNoRotate(true); this.viewportOrigin.x = boundsRect.x; this.viewportOrigin.y = boundsRect.y * this.imgAspectRatio; @@ -93,6 +93,20 @@ export default class OpenSeadragonCanvasOverlay { this.context2d.translate(x, y); this.context2d.scale(zoom, zoom); + const center = this.viewer.viewport.getCenter(); + + const flip = this.viewer.viewport.getFlip(); + if (flip) { + this.context2d.translate(center.x * 2, 0); + this.context2d.scale(-1, 1); + } + + const rotation = this.viewer.viewport.getRotation(); + if (rotation !== 0) { + this.context2d.translate(center.x, center.y); + this.context2d.rotate(rotation * Math.PI / 180); + this.context2d.translate(-1 * center.x, -1 * center.y); + } update(); this.context2d.setTransform(1, 0, 0, 1, 0, 0);