Skip to Content

Canvas

<Clover.Canvas /><clover-canvas>43 kB loaded by a page with it alone to first view, gzipped83 kB loaded by a page with it alone to first view, styles included, gzipped

Clover’s own renderer for IIIF Canvases: images, video and sound on one pan and zoom surface.

<div style={{ height:  }}>
  <Clover.Canvas
    iiifContent={url}
    placeholder={}
    controls={}
  />
</div>
<div style="height: px">
  <clover-canvas
    iiif-content="https://clover.iiif.library.northwestern.edu/mocks/standalone-canvas/canvas.json"
    placeholder=""
    controls="">
  </clover-canvas>
</div>

API reference

Draws the Presentation 4 Canvases you hand it, or loads one itself (iiifContentiiif-content), with WebGL2, else Canvas2D. Inside a Root<clover-root>, given nothing to draw, it shows the Root’s current view. It fills its parent, so give the parent a height.

It is experimental: its API may change in any release. A plain wheel scrolls the page, unless options.gestures.scrollToZoom is on.

PropTypeDefaultDescription
iiifContentstring | object—A Canvas to load and draw, or a Manifest’s first: URL or JSON.
canvasesobject[]The Root’s viewPresentation 4 Canvases, drawn together; toPresentation4() upgrades older ones.
bodyobject | object[]—IIIF painting bodies to draw; they win over src.
srcstring | string[]—Image URLs, or image services with isTiledImage.
isTiledImagebooleanfalseRead each src as an image service: its base URI or info.json.
viewingDirection"left-to-right" | "right-to-left" | "top-to-bottom" | "bottom-to-top""left-to-right"How several Canvases line up; in a Root, the Manifest’s.
labellanguage map or stringThe Canvas’s labelThe viewport’s accessible name.
partOflanguage map or stringThe Manifest’s labelUnder the title of a lone recording of sound, which plays as a player.
languagestringThe reader’s, or the Root’sThe language to read labels, Choices and annotations in.
controlsboolean | { zoom, fullPage, rotation, reset, annotations, information }trueAll of Clover’s controls, none, or all but those set false.
navigatorbooleanfalseAn overview of the whole image, to press or drag in.
placeholderbooleantrueOpen on the Canvas’s placeholderContainer, where it has one.
optionsobject—backend, gestures, maxZoomPixelRatio, minZoomImageRatio, animationTime, hideDelay, animation, media, request.
controlButtonsobject—Components of your own for zoomIn, zoomOut, fullPage, rotateRight, rotateLeft, reset, choice.
onReady(handle: CanvasHandle) => void—Once laid out, a handle to zoom, pan and turn it.
onViewportChange(bounds: { x, y, width, height }) => void—The region in view, at most once a frame.
annotations{ annotation, targetIndex, pageLabel?, pageId? }[]The loaded Canvas’s, or the Root’sHotspots on regions, points and shapes; whole-Canvas ones go to its information.
hiddenPagesstring[]—AnnotationPages (pageId) not drawn; its menu still lists them.
onPageVisibilityChange(pageIds: string[], visible: boolean) => void—The reader hid pages, or showed them, from the menu.
selectedAnnotationstring | null—The picked annotation, controlled; null picks none.
onAnnotationSelect(id: string | null) => void—A hotspot or the menu picked one, or null let it go.
highlightedAnnotationstring | null—One to highlight, as hovering it in a list does.
onAnnotationActive(id: string | null) => void—The hotspot hovered or focused, or null.
onAnnotationLink(link: { id, canvasId?, manifestId? }) => void—A linking hotspot was pressed; in a Root or with iiifContent, followed for you.
animateAnnotationsbooleanfalseGlide to a picked annotation, rather than cut to it.
chapters{ id?, label, lang?, start, end? }[]The Ranges, in a RootChapters of the recording, on its seek bar and in a menu.
highlightedChapterstring | null—A chapter (id) to draw out on the seek bar.
onChapterHighlight(id: string | null) => void—The chapter under the pointer on the seek bar, or null.
captionstring | null—The caption file (id) to show while captions are on.
onCaptionChange(caption: { id, language? } | null) => void—The reader chose a caption file, or Off (null).
onMediaElement(element: HTMLVideoElement | null) => void—The recording’s element, for a transcript of your own.
onEnded() => void—Playback reached the end: a cue to move on.
manifestIdstring—The Canvases’ Manifest: a new one clears the Canvas at once.
instanceIdstring—A stable id; a new one remounts the renderer.
classNamestring—Added to clover-canvas, on its figure.
childrenReactNode—Your own controls, after Clover’s.

<clover-canvas>

Clover's renderer for images, video and sound. Alone, it draws what it is given: a IIIF resource by URL (a Manifest gives its first Canvas), image URLs, or Canvases as a property. Inside a clover-root, given nothing, the root's view. As tall as --clover-body-height (60vh) or its own style.

NameTypeDefaultDescription
iiif-contentstring—A Canvas, a Manifest (its first Canvas) or a content state, by URL, in any Presentation version.
srcstring—An image's URL; with tiled, a IIIF Image API service's (its base URI or info.json).
tiledbooleanfalseRead src as a IIIF Image API service.
labelstring—The viewport's name, for an image given by src. A Canvas names it by its own label.
languagestring—The language to read IIIF text in.
controlsbooleantrue"false" leaves out the controls over the Body.
navigatorbooleanfalseA small map of the whole image, while zoomed in.
placeholderbooleantrue"false" opens a Canvas straight away, past its placeholderContainer.
viewing-direction"left-to-right" | "right-to-left" | "top-to-bottom" | "bottom-to-top"left-to-rightHow several Canvases (a spread) are laid out, in reading order.
animate-annotationsbooleanfalseGlide to a picked annotation, rather than frame it in one cut. A reader who asks for reduced motion gets the cut.
.handleCloverCanvasHandle | null—Read-only. The Canvas's handle once its view is laid out (clover-ready), as onReady hands it in React: the camera and its coordinates (handle.zoomBy(2), handle.home()). Null before.
.iiifContentstring | Record<string, unknown> | null—As a property: What to load and draw, as a URL or a IIIF resource.
.canvasesRecord<string, unknown>[] | null—Presentation 4 Canvases to draw, one or several shown together (a spread).
.srcstring | string[] | null—As a property: Image URLs, or image services with tiled.
.annotationsArray<{ id: string; target: string; label?: string; [key: string]: unknown }> | null—Annotations to draw as hotspots, with rectangular (xywh) targets in the image's own coordinates.
.options{ request?: { credentials?: RequestCredentials; headers?: Record<string, string>; fetch?: typeof fetch }; [key: string]: unknown } | null—The Canvas's options: the request it loads with (credentials, headers, a fetch of your own), its gestures and more.
.controlButtonsCloverControlButtons | null—The Body's controls, each replaced by a button you make: a function given the control's name, label and Clover's icon, returning the button. Clover keeps it named, keyed and in its state, presses the control with it, and adds its popover.
.controlsboolean | { zoom?: boolean; fullPage?: boolean; rotation?: boolean; reset?: boolean; annotations?: boolean; information?: boolean; [option: string]: unknown } | null—As a property: Which of the Body's controls it shows, as Canvas's controls takes it: false for none, or some ({ rotation: false }), in place of the attribute.
clover-ready{ handle: CloverCanvasHandle }—An event. The view is laid out and fitted: its handle is here, and works from now on.
clover-annotation-select{ id: string | null }—An event. The reader picked an annotation, on the Body or in its menu; null when they let it go.
clover-annotation-active{ id: string | null }—An event. An annotation is hovered or focused; null when none is.
clover-caption-change{ caption: { id: string; language?: string } | null }—An event. The reader chose a caption file in the Captions menu, or Off (null).
clover-endedRecord<string, never>—An event. A recording played to its end.

Examples

Images

Use src for images that are not on a Canvas: plain URLs, or IIIF image services with isTiledImagetiled, tiled from their info.json.

<Clover.Canvas src="https://iiif.dc.library.northwestern.edu/iiif/3/bcb98b9f-4c44-4fd0-bfa9-673fb904a2b1" isTiledImage label="The Vanishing Race - Navaho" />
<clover-canvas src="https://iiif.dc.library.northwestern.edu/iiif/3/bcb98b9f-4c44-4fd0-bfa9-673fb904a2b1" tiled label="The Vanishing Race - Navaho"></clover-canvas>

Several Canvases

Hand it the Canvases to show together, a spread say; which to show, and moving between them, is yours. groupViews reads a Manifest’s behavior as the Viewer does.

const manifest = await Clover.toPresentation4(json); const views = Clover.groupViews( manifest.items, Clover.resolveBehavior(manifest.behavior), ); <Clover.Canvas canvases={views[view].map((index) => manifest.items[index])} label={manifest.label} />;
<!-- A view of a Manifest: its first Canvas alone, or any view within a root. --> <clover-root iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json" canvas-id="https://clover.iiif.library.northwestern.edu/mocks/paged/canvas/5" > <clover-canvas></clover-canvas> </clover-root>

Video and sound

A Canvas of video or sound plays in Clover’s own transport, with the captions it carries.

<Clover.Canvas iiifContent="https://clover.iiif.library.northwestern.edu/mocks/transcripts/manifest.json" />
<clover-canvas iiif-content="https://clover.iiif.library.northwestern.edu/mocks/transcripts/manifest.json"></clover-canvas>

Annotations on a recording’s time

An annotation on a stretch of a recording (#t=) shows among its captions while that stretch plays; one with a region too (xywh=…&t=…) follows what it marks, frame by frame. Picking one, from the annotations menu or a list beside it, goes to its time.

<Clover.Canvas iiifContent="https://clover.iiif.library.northwestern.edu/mocks/rudolf-hess-nuremberg/manifest.json" />
<clover-canvas iiif-content="https://clover.iiif.library.northwestern.edu/mocks/rudolf-hess-nuremberg/manifest.json"></clover-canvas>

Driving it

onReadyclover-ready hands you a handle (zoomBy, panBy, rotateBy, home, fitBounds and more) to drive the view from controls of your own, and onViewportChange reports the region in view.

Loading…
const canvas = useRef(null); <Clover.Canvas src={service} isTiledImage label={label} onReady={(handle) => (canvas.current = handle)} onViewportChange={(bounds) => setRegion(bounds)} /> <button onClick={() => canvas.current.zoomBy(2)}>Zoom in</button>
<clover-canvas id="picture" src="https://iiif.io/api/image/3.0/example/reference/918ecd18c2592080851777620de9bcb5-gottingen" tiled label="Göttingen's market square" ></clover-canvas> <button type="button" id="zoom">Zoom in</button> <script type="module"> const canvas = document.getElementById("picture"); canvas.addEventListener("clover-ready", ({ detail: { handle } }) => { handle.on("viewport", () => setRegion(handle.getBounds())); }); document .getElementById("zoom") .addEventListener("click", () => canvas.handle?.zoomBy(2)); </script>

Canvas or Body

In a layout, place Body<clover-body> rather than Canvas<clover-canvas>: it draws the Root’s view with this Canvas, and adds a height, your renderers, and the loading mark while the Root loads. A Canvas<clover-canvas> alone in a Root<clover-root> shows the same view, without them.

<Clover.Root iiifContent={url}> <Clover.Body /> </Clover.Root>
<clover-root iiif-content="https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json"> <clover-body></clover-body> </clover-root>

Previous versions

Clover 3.x › Image

  • Canvas<clover-canvas> replaces Image, and the Viewer’s player for video and sound.
  • body, src, label and instanceId carry over.
  • openSeadragonCallback is onReadyclover-ready, which hands you a handle.
  • openSeadragonConfig is options.options.