Skip to main content

A Bookreader viewer, with facing pages

This example builds on the minimal viewer by adding support for 2-up views - facing pages.

One way of doing that would be to use two Canvas Panel instances, next to each other. But the expected behaviour of a 2-up viewer is that there is still only one viewport, the two canvases live in the same "zoom-space".

A generalised way of hoisting the viewport is to use <layout-container/>. This demo uses Sequence panel which has some extra features to deal with paged sequences.

You can see it running at /demos/bookreader.html Bookreader 2-up viewer.

Bookreader 2-up viewer
<html><head>    <title>Bookreader</title>    <style>        #manifest { width: 50vw; }        #th { width:240px; border-right: 1px solid #999; margin: 5px; float:left; height:90%; overflow-y:scroll; }                #main { width:72vw; margin-top:30px; margin-left:10px; float:left; height:90%;}         .tc { display: inline-block; padding:5px; cursor: pointer; min-width: 100; }        #viewportContainer { height:80%; background-color: black; display: flex }        sequence-panel {            display: flex;            flex-direction: column;            flex: 1;            min-width: 0; /* Required for downsizing */            --atlas-container-flex: 1 1 0px;            --atlas-background: #000;        }        /* #cp { height:100% } */    </style>    <script src="https://pkg.csb.dev/digirati-co-uk/iiif-canvas-panel/commit/b239c900/@digirati/canvas-panel-web-components/dist/bundle.js"></script>    <script src="https://cdn.jsdelivr.net/npm/@iiif/vault@latest/dist/index.umd.js"></script>    <script src="https://cdn.jsdelivr.net/npm/@iiif/vault-helpers@latest/dist/index.umd.js"></script></head><body>    <h1>A bookreader using Canvas Panel and Layout Container</h1>    <h2 id="manifestLabel"></h2>    <div>            <input id="manifest" type="text" value="https://iiif.wellcomecollection.org/presentation/b18035723" />        <input id="go" type="button" value="Go" />    </div>        <div>            <div id="th"></div>        <div id="main">            <div id="viewportContainer">            </div>            <p id="cvLabel"></p>        </div>    </div>    <script>            function $(id) { return document.getElementById(id); }        const vault = new IIIFVault.Vault();        const thumbHelper = VaultHelpers.createThumbnailHelper(vault);        let manifest;        async function loadManifest(){            const manifestUri = $("manifest").value;            if(manifestUri){                manifest = await vault.loadManifest(manifestUri);                                     const viewportContainer = $("viewportContainer");                viewportContainer.innerHTML = '';                // New component.                const sequencePanel = document.createElement('sequence-panel');                sequencePanel.vault = vault;                sequencePanel.setAttribute('manifest-id', manifestUri);                sequencePanel.setAttribute('margin', '20');                viewportContainer.appendChild(sequencePanel);                                $("manifestLabel").innerText = VaultHelpers.getValue(manifest.label);                      let thumbsHtml = "";                let counter = 1;                // for brevity we will assume that the manifest is "paged", the viewingDirection is left-to-right.                thumbsHtml += '<div class="tc"></div>';                for(const canvasRef of vault.get(manifest.items)){                      const canvas = vault.get(canvasRef);                                const label = VaultHelpers.getValue(canvas.label);                    thumbsHtml += `<div class="tc">${label}<br/>`;                    thumbsHtml += `<img data-uri="${canvas.id}" data-label="${label}" src="${canvas.thumbnail[0].id}" data-index="${counter}" />`;                    thumbsHtml += '</div>';                       counter++;                }                $('th').innerHTML = thumbsHtml;                    const thumbs = document.querySelectorAll('#th img');                      for(const thumb of thumbs){                    thumb.addEventListener('click', () => {                        if (sequencePanel.sequence) {                            sequencePanel.sequence.setCurrentCanvasId(thumb.getAttribute('data-uri'));                                                }                    });                }                  sequencePanel.addEventListener("sequence-change", () => {                    // Update the page labels for both visible canvases                    const sequence = sequencePanel.sequence;                    const itemIndexes = sequence.sequence[sequence.currentSequenceIndex];                     const canvasRefs = itemIndexes.map(idx => sequence.items[idx]);                    const canvases = vault.get(canvasRefs);                    const labels = canvases.map(canvas => VaultHelpers.getValue(canvas.label));                    $("cvLabel").innerText = labels.join(" | ");                  });                thumbs[0].click();            }        }                $("go").addEventListener('click', loadManifest);        loadManifest();             </script></body></html>
Issue on GitHub