Skip to content
Snippets Groups Projects
Commit 1d06e46a authored by Jack Reed's avatar Jack Reed Committed by Chris Beer
Browse files

Support Annotations in bookview for right-to-left viewing fixes #2956

parent 8eddcfe1
No related branches found
No related tags found
No related merge requests found
......@@ -19,7 +19,7 @@
},
{
manifestId: 'https://iiif.bodleian.ox.ac.uk/iiif/manifest/748a9d50-5a3a-440e-ab9d-567dd68b6abb.json',
canvasId: 'https://iiif.bodleian.ox.ac.uk/iiif/canvas/4a4d7347-0c32-4e3d-b517-5042eba06c25.json',
canvasIndex: 6,
}
],
window: {
......
......@@ -55,13 +55,19 @@ describe('CanvasAnnotationDisplay', () => {
describe('svgContext', () => {
it('draws the paths with selected arguments', () => {
const context = {
restore: jest.fn(),
save: jest.fn(),
stroke: jest.fn(),
translate: jest.fn(),
};
const subject = createSubject({
resource: new AnnotationResource(dualStrategyAnno),
});
subject.svgContext(context);
expect(context.stroke).toHaveBeenCalledWith({});
expect(context.save).toHaveBeenCalledWith();
expect(context.restore).toHaveBeenCalledWith();
expect(context.translate).toHaveBeenCalledWith(-100, 0);
expect(context.strokeStyle).toEqual('blue');
expect(context.lineWidth).toEqual(20);
});
......
......@@ -17,15 +17,27 @@ describe('CanvasWorld', () => {
expect(new CanvasWorld(canvasSubset).worldBounds()).toEqual([0, 0, 9153, 4288]);
});
});
describe('contentResourceToWorldCoordinates', () => {
it('converts canvas coordinates to world offset by location', () => {
expect(new CanvasWorld([canvases[1]]).contentResourceToWorldCoordinates({ id: 'https://stacks.stanford.edu/image/iiif/fr426cg9537%2FSC1094_s3_b14_f17_Cats_1976_0005/full/full/0/default.jpg' }))
.toEqual([0, 0, 6501, 4421]);
expect(new CanvasWorld(canvasSubset).contentResourceToWorldCoordinates({ id: 'https://stacks.stanford.edu/image/iiif/rz176rt6531%2FPC0170_s3_Tree_Calendar_20081101_152516_0410/full/full/0/default.jpg' }))
.toEqual([6305, 0, 2848, 4288]);
});
it('supports RTL orientations', () => {
expect(new CanvasWorld(canvasSubset, null, 'right-to-left').contentResourceToWorldCoordinates({ id: 'https://stacks.stanford.edu/image/iiif/rz176rt6531%2FPC0170_s3_Tree_Calendar_20081101_152516_0410/full/full/0/default.jpg' }))
.toEqual([0, 0, 2848, 4288]);
});
});
describe('canvasToWorldCoordinates', () => {
it('converts canvas coordinates to world offset by location', () => {
expect(new CanvasWorld([canvases[1]]).canvasToWorldCoordinates({ id: 'https://stacks.stanford.edu/image/iiif/fr426cg9537%2FSC1094_s3_b14_f17_Cats_1976_0005/full/full/0/default.jpg' }))
expect(new CanvasWorld([canvases[1]]).canvasToWorldCoordinates('https://purl.stanford.edu/fr426cg9537/iiif/canvas/fr426cg9537_1'))
.toEqual([0, 0, 6501, 4421]);
expect(new CanvasWorld(canvasSubset).canvasToWorldCoordinates({ id: 'https://stacks.stanford.edu/image/iiif/rz176rt6531%2FPC0170_s3_Tree_Calendar_20081101_152516_0410/full/full/0/default.jpg' }))
expect(new CanvasWorld(canvasSubset).canvasToWorldCoordinates('https://purl.stanford.edu/rz176rt6531/iiif/canvas/rz176rt6531_1'))
.toEqual([6305, 0, 2848, 4288]);
});
it('supports RTL orientations', () => {
expect(new CanvasWorld(canvasSubset, null, 'right-to-left').canvasToWorldCoordinates({ id: 'https://stacks.stanford.edu/image/iiif/rz176rt6531%2FPC0170_s3_Tree_Calendar_20081101_152516_0410/full/full/0/default.jpg' }))
expect(new CanvasWorld(canvasSubset, null, 'right-to-left').canvasToWorldCoordinates('https://purl.stanford.edu/rz176rt6531/iiif/canvas/rz176rt6531_1'))
.toEqual([0, 0, 2848, 4288]);
});
});
......@@ -36,14 +48,7 @@ describe('CanvasWorld', () => {
).toEqual({ x: 0, y: 0 });
expect(
new CanvasWorld(canvasSubset).offsetByCanvas('https://purl.stanford.edu/rz176rt6531/iiif/canvas/rz176rt6531_1'),
).toEqual({ x: 6501, y: 0 });
});
});
describe('indexOfTarget', () => {
it('returns the index of a target in canvases', () => {
expect(
new CanvasWorld(canvasSubset).indexOfTarget('https://purl.stanford.edu/rz176rt6531/iiif/canvas/rz176rt6531_1'),
).toEqual(1);
).toEqual({ x: 6305, y: 0 });
});
});
......
......@@ -226,7 +226,7 @@ export class OpenSeadragonViewer extends Component {
this.viewer.addSimpleImage({
error: event => reject(event),
fitBounds: new OpenSeadragon.Rect(
...canvasWorld.canvasToWorldCoordinates(contentResource),
...canvasWorld.contentResourceToWorldCoordinates(contentResource),
),
index: canvasWorld.layerIndexOfImageResource(contentResource),
opacity: canvasWorld.layerOpacityOfImageResource(contentResource),
......@@ -253,7 +253,7 @@ export class OpenSeadragonViewer extends Component {
this.viewer.addTiledImage({
error: event => reject(event),
fitBounds: new OpenSeadragon.Rect(
...canvasWorld.canvasToWorldCoordinates(contentResource),
...canvasWorld.contentResourceToWorldCoordinates(contentResource),
),
index: canvasWorld.layerIndexOfImageResource(contentResource),
opacity: canvasWorld.layerOpacityOfImageResource(contentResource),
......
......@@ -36,6 +36,8 @@ export default class CanvasAnnotationDisplay {
* TODO: Support multi canvas offset
* One example: https://developer.mozilla.org/en-US/docs/Web/API/Path2D/addPath
*/
context.save();
context.translate(this.offset.x, this.offset.y);
const p = new Path2D(element.attributes.d.nodeValue);
/**
* Note: we could do something to return the svg styling attributes as
......@@ -47,6 +49,7 @@ export default class CanvasAnnotationDisplay {
context.strokeStyle = this.color; // eslint-disable-line no-param-reassign
context.lineWidth = this.lineWidth(); // eslint-disable-line no-param-reassign
context.stroke(p);
context.restore();
});
}
......@@ -54,6 +57,7 @@ export default class CanvasAnnotationDisplay {
fragmentContext(context) {
const fragment = this.resource.fragmentSelector;
fragment[0] += this.offset.x;
fragment[1] += this.offset.y;
context.strokeStyle = this.color; // eslint-disable-line no-param-reassign
context.lineWidth = this.lineWidth(); // eslint-disable-line no-param-reassign
context.strokeRect(...fragment);
......
......@@ -21,10 +21,10 @@ export default class CanvasWorld {
}
/**
* canvasToWorldCoordinates - calculates the canvas coordinates respective to
* the world.
* contentResourceToWorldCoordinates - calculates the contentResource coordinates
* respective to the world.
*/
canvasToWorldCoordinates(contentResource) {
contentResourceToWorldCoordinates(contentResource) {
const wholeBounds = this.worldBounds();
const manifestoCanvasIndex = this.canvases.findIndex(c => (
c.imageResources.find(r => r.id === contentResource.id)
......@@ -43,6 +43,24 @@ export default class CanvasWorld {
];
}
/** */
canvasToWorldCoordinates(canvasId) {
const wholeBounds = this.worldBounds();
const manifestoCanvasIndex = this.canvases.findIndex(c => (c.id === canvasId));
const { aspectRatio } = this.canvases[manifestoCanvasIndex];
const scaledWidth = Math.floor(wholeBounds[3] * aspectRatio);
let x = 0;
if (manifestoCanvasIndex === this.secondCanvasIndex) {
x = wholeBounds[2] - scaledWidth;
}
return [
x,
0,
scaledWidth,
wholeBounds[3],
];
}
/**
* secondCanvasIndex - index of the second canvas used for determining which
* is first
......@@ -51,10 +69,6 @@ export default class CanvasWorld {
return this.viewingDirection === 'right-to-left' ? 0 : 1;
}
/** */
indexOfTarget(canvasTarget) {
return this.canvases.map(canvas => canvas.id).indexOf(canvasTarget);
}
/** Get the IIIF content resource for an image */
contentResource(infoResponseId) {
......@@ -115,12 +129,11 @@ export default class CanvasWorld {
* assumes a horrizontal only layout.
*/
offsetByCanvas(canvasTarget) {
const offset = { x: 0, y: 0 };
let i;
for (i = 0; i < this.indexOfTarget(canvasTarget); i += 1) {
offset.x += this.canvases[i].getWidth();
}
return offset;
const coordinates = this.canvasToWorldCoordinates(canvasTarget);
return {
x: coordinates[0],
y: coordinates[1],
};
}
/**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment