diff --git a/Gemfile b/Gemfile index ef835893c..edbf8caf4 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ gem 'jekyll', '~> 4.1.1' # for local development, clone theme + use path loader # gem 'iiifc-theme', path: 'iiifc-theme' -gem 'iiifc-theme', github: 'iiif/iiifc-theme', branch: 'main' +gem 'iiifc-theme', github: 'iiif/iiifc-theme', branch: 'ignore-font-awsome' # For open graph and Twitter Card elements gem 'jekyll-seo-tag' diff --git a/Gemfile.lock b/Gemfile.lock index bf1dc3143..6bb67cb30 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GIT remote: https://github.com/iiif/iiifc-theme.git - revision: afff3ef39910d7454c58abf2b9c9e6a50cc7cb4c - branch: main + revision: a1a48285ca5bbf81d6967cf31fdcdb571da3068b + branch: ignore-font-awsome specs: iiifc-theme (0.1.0) html-proofer @@ -18,7 +18,7 @@ GEM addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) colorator (1.1.0) - concurrent-ruby (1.3.3) + concurrent-ruby (1.3.4) diff-lcs (1.5.1) em-websocket (0.5.3) eventmachine (>= 0.12.9) @@ -84,7 +84,7 @@ GEM racc (~> 1.4) nokogumbo (2.0.5) nokogiri (~> 1.8, >= 1.8.4) - parallel (1.25.1) + parallel (1.26.3) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (6.0.1) @@ -95,7 +95,7 @@ GEM rb-inotify (0.11.1) ffi (~> 1.0) redcarpet (3.6.0) - rexml (3.3.4) + rexml (3.3.6) strscan rouge (3.30.0) rspec (3.13.0) @@ -104,7 +104,7 @@ GEM rspec-mocks (~> 3.13.0) rspec-core (3.13.0) rspec-support (~> 3.13.0) - rspec-expectations (3.13.1) + rspec-expectations (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-mocks (3.13.1) diff --git a/_includes/content-state-viewers.html b/_includes/content-state-viewers.html new file mode 100644 index 000000000..7f66c23b4 --- /dev/null +++ b/_includes/content-state-viewers.html @@ -0,0 +1,39 @@ +{% if include.viewers %} +{% assign viewers = include.viewers | split: "," %} +{% else %} +{% assign viewers = page.viewers %} +{% endif %} +[JSON-LD]({{ include.iiif-content }}) {% for viewerTxt in viewers %}{% assign viewer = viewerTxt | strip %}| {% include viewer_link.html type=viewer manifest=include.iiif-content class="content-state" %}{% endfor %} + +{% if page.code %} +{% include code_links.html %} +{% endif %} + + \ No newline at end of file diff --git a/_includes/links.md b/_includes/links.md index 6e2c2d13b..fa72a7a44 100644 --- a/_includes/links.md +++ b/_includes/links.md @@ -75,7 +75,10 @@ [0466]: {{ site.cookbook_url | absolute_url }}/recipe/0466-link-for-loading-manifest/ "Loading a manifest with a viewer using a link" +[0485]: {{ site.cookbook_url | absolute_url }}/recipe/0485-contentstate-canvas-region/ "Open a specific region of a canvas in a viewer" + [0434]: {{ site.cookbook_url | absolute_url }}/recipe/0434-choice-av/ "Multiple Choice of Audio Formats in a Single View (Canvas)" +[0489]: {{ site.cookbook_url | absolute_url }}/recipe/0489-multimedia-canvas/ "Rendering Multiple Media Types on a Time-Based Canvas" [cookbook-process]: {{site.cookbook_url | absolute_url }}/recipe diff --git a/_includes/viewer_link.html b/_includes/viewer_link.html index 991148bcf..0c192bdac 100644 --- a/_includes/viewer_link.html +++ b/_includes/viewer_link.html @@ -64,4 +64,4 @@ {% else %} {% capture default_text %}Unknown Viewer type '{{ include.type}}'{% endcapture %} {% capture viewer_url %}{{manifest_url |strip}}{% endcapture %} -{% endif %}{{ include.text | default: default_text }} +{% endif %}{{ include.text | default: default_text }} diff --git a/index.md b/index.md index ba3a6aa63..73ae4bb99 100644 --- a/index.md +++ b/index.md @@ -115,6 +115,7 @@ _(leading on to segmentation examples later)_ * [Multiple choice of images in a single view][0033] (29) * [Foldouts, Flaps, and Maps][0035] * [Composition from Multiple Images][0036] (30,31) +* [Rendering Multiple Media Types on a Time-Based Canvas][0489] * Multiple images and multiple choices (32,33,34) * [Annotating part of an image to a Canvas][recipe-segment-image-part] (e.g., crop out scanner) (35,36,37,38) * [Image Rotation Two Ways][0040] @@ -141,6 +142,7 @@ _(leading on to segmentation examples later)_ Recipes using [Content State API](https://iiif.io/api/content-state/1.0/) * [Loading a manifest with a viewer using a link][0466] +* [Open a specific region of a canvas in a viewer][0485] ## Technical diff --git a/recipe/0001-mvm-image/index.md b/recipe/0001-mvm-image/index.md index 9ac30a3c5..8044d2bf2 100644 --- a/recipe/0001-mvm-image/index.md +++ b/recipe/0001-mvm-image/index.md @@ -11,6 +11,7 @@ viewers: - Clover - Glycerine Viewer - Theseus + - Curation topic: - basic - image diff --git a/recipe/0004-canvas-size/index.md b/recipe/0004-canvas-size/index.md index 77a1a38b9..d4ecea891 100644 --- a/recipe/0004-canvas-size/index.md +++ b/recipe/0004-canvas-size/index.md @@ -9,6 +9,7 @@ viewers: - Mirador - Annona - Theseus + - Curation topic: image code: - iiif-prezi3 @@ -39,7 +40,7 @@ The aspect ratio should be consistent between your source image and Canvas. Othe This example shows a Manifest with a single Canvas that has height and width dimensions three times the pixel dimensions of the image in order to construct a Canvas with both dimensions greater than 1000px. -{% include manifest_links.html viewers="UV, Mirador, Annona, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config="data-line='14-15,29-30'"%} # Related recipes diff --git a/recipe/0005-image-service/index.md b/recipe/0005-image-service/index.md index 18652404e..79d301401 100644 --- a/recipe/0005-image-service/index.md +++ b/recipe/0005-image-service/index.md @@ -10,6 +10,7 @@ viewers: - Clover - Glycerine Viewer - Theseus + - Curation topic: - basic - image @@ -37,7 +38,7 @@ Though a version 3 Manifest may specify a service using the version 2 `@id` and ## Example -{% include manifest_links.html viewers="Mirador, Annona, Clover, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="Mirador, Annona, Clover, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config='data-line="36-42"' %} diff --git a/recipe/0006-text-language/index.md b/recipe/0006-text-language/index.md index 6f5f27531..24ca762fe 100644 --- a/recipe/0006-text-language/index.md +++ b/recipe/0006-text-language/index.md @@ -10,6 +10,7 @@ viewers: - Annona - Glycerine Viewer - Theseus + - Curation topic: basic property: label, summary, metadata, requiredStatement code: @@ -38,11 +39,15 @@ In the `metadata` and `requiredStatement` properties, the `label` strings for "C Finally, the `summary` property (lines 49-54) has values in both English and French. -To see the language choice in the linked viewers, open the settings menu (gear icon) and choose either English or French. +With the Universal Viewer, Mirador, and Glycerine you can open the settings menu (gear icon) and choose either English or French. + +For the Curation viewer you need to add a `lang=fr` parameter to access the French properties. You can see the French values on the [IIIF Curation Viewer](http://codh.rois.ac.jp/software/iiif-curation-viewer/demo/?manifest=https://iiif.io/api/cookbook/recipe/0006-text-language/manifest.json&lang=fr) demo site. + +Note not all viewers support all languages and users should check the viewers with their manifests to see if they need to configure the viewer to make the extra languages available. The image in this example was sourced via Wikimedia Commons and is public domain. -{% include manifest_links.html viewers="UV, Mirador, Annona, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config='data-line="6-11, 16-21, 24-26, 31-36, 39-44, 49-54, 58-63, 66-68"' %} diff --git a/recipe/0007-string-formats/index.md b/recipe/0007-string-formats/index.md index 72fc67c7a..113d2cd11 100644 --- a/recipe/0007-string-formats/index.md +++ b/recipe/0007-string-formats/index.md @@ -11,6 +11,7 @@ viewers: - Clover - Glycerine Viewer - Theseus + - Curation topic: property property: label, summary, metadata, requiredStatement code: @@ -33,7 +34,7 @@ For security reasons, clients are expected to allow only `a`, `b`, `br`, `i`, `i ## Example -{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config='data-line="7,12,24,38"' %} diff --git a/recipe/0008-rights/index.md b/recipe/0008-rights/index.md index 7ff438e0f..e6a890cbd 100644 --- a/recipe/0008-rights/index.md +++ b/recipe/0008-rights/index.md @@ -11,6 +11,7 @@ viewers: - Clover - Glycerine Viewer - Theseus + - Curation topic: property property: rights, requiredStatement code: @@ -41,7 +42,7 @@ None known. ## Example -{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config='data-line="15-27"' %} diff --git a/recipe/0009-book-1/index.md b/recipe/0009-book-1/index.md index 1be820589..38c9ff3ad 100644 --- a/recipe/0009-book-1/index.md +++ b/recipe/0009-book-1/index.md @@ -11,6 +11,7 @@ viewers: - Clover - Glycerine Viewer - Theseus + - Curation topic: - image - basic @@ -38,7 +39,7 @@ You should also consider providing a [thumbnail][prezi3-thumbnail] for each Canv ## Example -{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" %} diff --git a/recipe/0010-book-2-viewing-direction/index.md b/recipe/0010-book-2-viewing-direction/index.md index fb728035d..c9718246c 100644 --- a/recipe/0010-book-2-viewing-direction/index.md +++ b/recipe/0010-book-2-viewing-direction/index.md @@ -8,7 +8,10 @@ viewers: - UV - Mirador - Annona - - Theseus + - id: Theseus + support: partial + - id: Curation + support: partial topic: - image - property @@ -41,7 +44,7 @@ None known This Manifest shows the playbill for "Akiba gongen kaisen-banashi," "Futatsu chōchō kuruwa nikki", and "Godairiki koi no fūjime", kabuki performances at the Chikugo Theater in Osaka, from the fifth month of Kaei 2 (May, 1849). -{% include manifest_links.html viewers="UV, Mirador, Annona, Theseus" manifest="manifest-rtl.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Theseus, Curation" manifest="manifest-rtl.json" %} {% include jsonviewer.html src="manifest-rtl.json" config='data-line="15"' %} diff --git a/recipe/0029-metadata-anywhere/index.md b/recipe/0029-metadata-anywhere/index.md index 901f1cb0c..bf4606103 100644 --- a/recipe/0029-metadata-anywhere/index.md +++ b/recipe/0029-metadata-anywhere/index.md @@ -12,6 +12,7 @@ viewers: support: partial - Glycerine Viewer - Theseus + - Curation topic: property property: metadata --- @@ -38,7 +39,7 @@ Note: Clover supports Metadata at the Manifest level but not down at the Canvas. Credit: *John Dee performing an experiment before Queen Elizabeth I*. Oil painting by Henry Gillard Glindoni. Credit: Wellcome Collection. Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) -{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Clover, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config='data-line="10-59, 83-96, 136-149"' %} diff --git a/recipe/0118-multivalue/index.md b/recipe/0118-multivalue/index.md index 42024d447..849ab689b 100644 --- a/recipe/0118-multivalue/index.md +++ b/recipe/0118-multivalue/index.md @@ -10,6 +10,7 @@ viewers: - Annona - Glycerine Viewer - Theseus + - Curation topic: property property: label, summary, metadata, requiredStatement --- @@ -32,7 +33,7 @@ None In this example, the work has multiple titles in both English and French. The Manifest `label` provides a single title in French within a single-value array (lines 6–8). The alternative titles are provided in the `metadata` property in both English and French, each with variants contained within two separate arrays -- one array for English (lines 18–21) and one for French (lines 22–25). In the `summary` property (lines 30–32) the value is included as a single-string array. -{% include manifest_links.html viewers="UV, Mirador, Annona, Glycerine Viewer, Theseus" manifest="manifest.json" %} +{% include manifest_links.html viewers="UV, Mirador, Annona, Glycerine Viewer, Theseus, Curation" manifest="manifest.json" %} {% include jsonviewer.html src="manifest.json" config='data-line="6-8, 18-21, 22-25, 30-32"'%} diff --git a/recipe/0283-missing-image/index.md b/recipe/0283-missing-image/index.md index 6f36a1a88..7c55eae52 100644 --- a/recipe/0283-missing-image/index.md +++ b/recipe/0283-missing-image/index.md @@ -9,6 +9,7 @@ viewers: - Mirador - Glycerine Viewer - Theseus + - Curation topic: - image - basic diff --git a/recipe/0485-contentstate-canvas-region/annotation.json b/recipe/0485-contentstate-canvas-region/annotation.json new file mode 100644 index 000000000..f0e75c0bc --- /dev/null +++ b/recipe/0485-contentstate-canvas-region/annotation.json @@ -0,0 +1,14 @@ +{ + "@context": "http://iiif.io/api/presentation/3/context.json", + "id": "https://example.org/import/1", + "type": "Annotation", + "motivation": ["contentState"], + "target": { + "id": "https://iiif.io/api/cookbook/recipe/0009-book-1/canvas/p2#xywh=1528,3024,344,408", + "type": "Canvas", + "partOf": [{ + "id": "https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json", + "type": "Manifest" + }] + } + } \ No newline at end of file diff --git a/recipe/0485-contentstate-canvas-region/index.md b/recipe/0485-contentstate-canvas-region/index.md new file mode 100644 index 000000000..06b0ba56e --- /dev/null +++ b/recipe/0485-contentstate-canvas-region/index.md @@ -0,0 +1,95 @@ +--- +title: Open a specific region of a Canvas in a viewer +id: 485 +layout: recipe +tags: [annotation, content-state] +summary: "Allows users to use Content State API to open a specific region of a Canvas by means of supported viewers." +viewers: +topic: + - content-state +--- + +## Use Case + +I want to share a link to highlight a detail in a specific region of an image to share a portion of a digitized manuscript text, allowing the user easy access to the rest of the manuscript. + +Institutions might want to use this recipe to share portions of their object through social media, allowing a direct link to the viewer to improve the user's interaction with the digitized content. A scholar who finds a relevant passage in a manuscript might want to share the precise location with other colleagues, allowing them to check the original source. + +## Implementation Notes + +This request can be implemented in a standardized manner using the [IIIF Content State API](https://iiif.io/api/content-state), providing the data as values of the `iiif-content` query string parameter as explained in the [API section](https://iiif.io/api/content-state/1.0/#initialization-mechanisms-link). + +We can use the [Web Annotation Data Model](https://www.w3.org/TR/annotation-model/) to encode the information necessary, as shown in ["A Region of a Canvas in a Manifest"](https://iiif.io/api/content-state/1.0/#51-a-region-of-a-canvas-in-a-manifest) section of the standard. + +However, before passing the data as a query parameter, we must encode it as explained in the [Content State encoding guidelines](https://iiif.io/api/content-state/1.0/#6-content-state-encoding). + +In this example, we want to highlight a portion of an image contained in a book. We will use the following manifest shown in the Simple Manifest Book recipe, which is available at the following link: [https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json](https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json) + +We want to open the viewport to a specific Canvas region using a viewer available on the following page `https://example.org/viewer`. + +First, we create an Annotation: + +```json +{ + "@context": "http://iiif.io/api/presentation/3/context.json", + "id": "https://example.org/import/1", + "type": "Annotation", + "motivation": ["contentState"], + "target": { + "id": "https://iiif.io/api/cookbook/recipe/0009-book-1/canvas/p2#xywh=1528,3024,344,408", + "type": "Canvas", + "partOf": [{ + "id": "https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json", + "type": "Manifest" + }] + } +} +``` + +We can create an Annotation with `motivation` set to `contentState` and a target `type` set to Canvas. The `id` of the target will contain a fragment selector (`#xywh=1528,3024,344,408`) with the coordinates of the Canvas we want to share, while the `partOf` element has the `id` of the Manifest containing the Canvas. + +We can now use one of the methods listed in the [examples of Content State encoding section](https://iiif.io/api/content-state/1.0/#63-examples-of-content-state-encoding) to generate a base64url string (**note: for brevity, we removed new line characters and white space before computing the base64url**). + +We can pass the encoded value, using the `iiif-content` query parameter of the viewer landing page: +[https://example.org/viewer?iiif-content=JTdCJTIyJTQwY29udGV4dCUyMiUzQSUyMmh0dHAlM0ElMkYlMkZpaWlmLmlvJTJGYXBpJTJGcHJlc2VudGF0aW9uJTJGMyUyRmNvbnRleHQuanNvbiUyMiUyQyUyMmlkJTIyJTNBJTIyaHR0cHMlM0ElMkYlMkZleGFtcGxlLm9yZyUyRmltcG9ydCUyRjElMjIlMkMlMjJ0eXBlJTIyJTNBJTIyQW5ub3RhdGlvbiUyMiUyQyUyMm1vdGl2YXRpb24lMjIlM0ElNUIlMjJjb250ZW50U3RhdGUlMjIlNUQlMkMlMjJ0YXJnZXQlMjIlM0ElN0IlMjJpZCUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGaWlpZi5pbyUyRmFwaSUyRmNvb2tib29rJTJGcmVjaXBlJTJGMDAwOS1ib29rLTElMkZjYW52YXMlMkZwMiUyM3h5d2glM0QxNTI4JTJDMzAyNCUyQzM0NCUyQzQwOCUyMiUyQyUyMnR5cGUlMjIlM0ElMjJDYW52YXMlMjIlMkMlMjJwYXJ0T2YlMjIlM0ElNUIlN0IlMjJpZCUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGaWlpZi5pbyUyRmFwaSUyRmNvb2tib29rJTJGcmVjaXBlJTJGMDAwOS1ib29rLTElMkZtYW5pZmVzdC5qc29uJTIyJTJDJTIydHlwZSUyMiUzQSUyMk1hbmlmZXN0JTIyJTdEJTVEJTdEJTdE](https://example.org/) + +We can also create an anchor tag with the link as the `href` attribute for use in a web page: + +```html +Link for visualizing the region of a Canvas using a viewer. +``` + +An alternative way of sharing a region of an image is to use the [Image API](https://iiif.io/api/image/3.0/#41-region). However, the context from which the region is extracted is not easily accessible. Instead, sharing a link to open the specific region with a viewer allows the users to explore another part of the image or related content and metadata in the Manifest. + +## Restrictions + +Note Content State does not define how the viewer should bring the regions of the Canvas to the attention of the user. It only mentions: + +"This data structure can be used by clients to load the resource required, present a particular part of the resource to the user." https://iiif.io/api/content-state/1.0/#content-state + +Viewers may set the viewport to the region or highlight the region with an annotation. + +## Example + +In this example we are aiming to highlight the bug that is on the second page of the [Book in recipe][0009]. The part of the image we are highlighting is as follows: + +![Image of a bug](https://iiif.io/api/image/3.0/example/reference/59d09e6773341f28ea166e9f3c1e674f-gallica_ark_12148_bpt6k1526005v_f19/1528,3024,344,408/pct:50/0/default.jpg) + +and this is located in the following region of the second image: + +![Location of the region to be highlighted.](page.jpg) + +{% include content-state-viewers.html iiif-content="annotation.json" viewers="" %} + +{% include jsonviewer.html src="annotation.json" %} + +## Related Recipes + +* [Simplest Manifest - Image][0001] shows the basic structure of a IIIF Manifest using Presentation API 3.0. +* [A simple book][0009] shows the manifest structure. +* [Link for loading a manifest][0466] another example of Content State API. +* [Addressing a Spatial Region][0299] an example of sharing a region of a Canvas creating a new Manifest. + +{% include acronyms.md %} +{% include links.md %} + diff --git a/recipe/0485-contentstate-canvas-region/page.jpg b/recipe/0485-contentstate-canvas-region/page.jpg new file mode 100644 index 000000000..d3846825f Binary files /dev/null and b/recipe/0485-contentstate-canvas-region/page.jpg differ diff --git a/recipe/0489-multimedia-canvas/index.md b/recipe/0489-multimedia-canvas/index.md new file mode 100644 index 000000000..ee8aafc43 --- /dev/null +++ b/recipe/0489-multimedia-canvas/index.md @@ -0,0 +1,52 @@ +--- +title: Rendering Multiple Media Types on a Time-Based Canvas +id: 499 +layout: recipe +tags: Complex Object +summary: "Paint a still image, a video with sound, and text onto a single Canvas" +viewers: + - Theseus +topic: + - annotation +--- + +## Use Case + +You want to create a digital assignment by providing students with a IIIF image resource to analyze in a fixed amount of time, a timer to show students how long they have, and text instructions for how to complete the assignment. You want to keep everything in one IIIF viewer. + +## Implementation Notes + +This recipe pulls together techniques and structures described in other recipes, and adds new elements. In other recipes, this cookbook shows [how to place multiple resources on a single Canvas][0036] and how to work with [a resource with different dimensions than its Canvas][0004]. Here, the aim is to mix AV and image IIIF resources, restrict Annotations' visibility by time ranges, and resize and position an AV resource on a Canvas. + +Likewise, while other recipes have discussed [simple textual annotations][0266], this recipe uses a `painting` motivation for its textual annotations (rather than `commenting` as the linked recipe does) to include the text directly and visibly on the Canvas. + +A Canvas containing a `duration` property has a notional timeline that can be used to target resources to a time point or range of the Canvas. If a resource's `target` value includes a `t` parameter, the resource can be expected to be shown during only and all of that span of time on the timeline. The order in which resources appear on the Canvas is governed by the `t` parameter of the `target` when specified; they can be entered in the Manifest in any order. (See "Restrictions" below for caveats and see [the Presentation specification][prezi3] for more detail about time and IIIF resources, including [the `duration` property][https://iiif.io/api/presentation/3.0/#duration].) + +The `t` parameter of the `target` value can also serve to trim an AV resource to be displayed for something other than its whole duration. An AV resource can thus have a `target` that governs its placement on the Canvas, its dimensions relative to the Canvas, its appearance duration, and the amount of its total running time that is used. An AV resource can also take [a `timeMode` property](https://iiif.io/api/presentation/3.0/#timemode) that governs its rendering in conjunction with the `t` parameter of its `target` and the `duration` property of a Canvas. + +## Restrictions + +When using timing for showing and hiding resources on a Canvas, a high degree of precision is not likely to be achieved for all people viewing the Canvas. Resources may load slowly for many reasons, including image server issues, network traffic, or browser and client customizations. Except in a very predictable environment, timing should be considered approximate. As well, people interacting with a multimedia Canvas may have greater or lesser control over the Canvas timeline. Consequently, creators cannot assume rigid implementation of timeline manipulation restrictions, even implied ones as in this recipe. + +## Example + +In this example, a still image, a video, and plaintext annotations are combined on a single Canvas to simulate a classroom assignment designed to introduce students to image study and notetaking in a compressed period of time. Note that this example contains material pedagogical design flaws and is not to be used as is for a classroom assignment. + +The simultaneously visible resources are listed in the Manifest from the foreground to the background. The timer video comes first in the Manifest, as the only currently capable viewer places resources on the Canvas so that the first resource is the most foregrounded. + +A person using a viewer that supports this recipe is presented first with the instruction to "Press Play", added using a time-bound plaintext annotation. After pressing play, additional instructions appear, also created using a time-bound plaintext annotation. When the time elapses on this annotation, the person is presented with a clock video overlaid on top of a still image. In the hypothetical assignment, a student would follow the instructions and take notes on the still image while the clock counts up the time allotted. After 30 seconds passes, the still image and clock video disappear, replaced by text instructions to close the browser. These final instructions stay visible for approximately 2-1/2 minutes to avoid an immediate return to the initial instructions. + +{% include manifest_links.html manifest="manifest.json" %} + +{% include jsonviewer.html src="manifest.json" config='data-line="16,40,49-51,54,59,66,71,78,83,90"' %} + +## Related Recipes + +* [Image and Canvas with Differing Dimensions][0004] for relative dimensioning of a resource and a Canvas +* [Table of Contents for Multiple A/V Files on a Single Canvas][0064] for time ranges in `target`s +* [Simplest Annotation][0266] for a basic textual annotation +* [Composition from Multiple Images][0036] for using multiple IIIF resources on a single Canvas + +{% include acronyms.md %} +{% include links.md %} + diff --git a/recipe/0489-multimedia-canvas/manifest.json b/recipe/0489-multimedia-canvas/manifest.json new file mode 100644 index 000000000..cb800a27c --- /dev/null +++ b/recipe/0489-multimedia-canvas/manifest.json @@ -0,0 +1,93 @@ +{ + "@context": "http://iiif.io/api/presentation/3/context.json", + "id": "{{ id.url }}", + "type": "Manifest", + "label": { "en": [ "Multimedia Canvas" ] }, + "items": [ + { + "id": "{{ id.path }}/canvas", + "type": "Canvas", + "height": 31722, + "width": 70399, + "duration": 180, + "items": [ + { + "id": "{{ id.path }}/page/p1/1", + "type": "AnnotationPage", + "items": [ + { + "id": "{{ id.path }}/annotation/p0001-image", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://iiif.io/api/image/3.0/example/reference/36ca0a3370db128ec984b33d71a1543d-100320001004/full/full/0/default.jpg", + "type": "Image", + "format": "image/jpeg", + "height": 31722, + "width": 70399, + "service": [ + { + "id": "https://iiif.io/api/image/3.0/example/reference/36ca0a3370db128ec984b33d71a1543d-100320001004", + "profile": "level1", + "type": "ImageService3" + } + ] + }, + "target": "{{ id.path }}/canvas#t=11,42" + }, + { + "id": "{{ id.path }}/annotation/p0002-video", + "type": "Annotation", + "motivation": "painting", + "body": { + "id": "https://fixtures.iiif.io/video/indiana/30-minute-clock/medium/30-minute-clock.mp4", + "type": "Video", + "height": 360, + "width": 640, + "duration": 1801.055, + "format": "video/mp4" + }, + "target": "{{ id.path }}/canvas#xywh=1000,500,5000,6000&t=11,42" + }, + { + "id": "{{ id.path }}/annotation/p0004-text", + "type": "Annotation", + "motivation": "painting", + "body": { + "type": "TextualBody", + "format": "text/html", + "value": "
Press Play
", + "language": "en" + }, + "target": "{{ id.path }}/canvas#xywh=30200,10200,15000,5000&t=0,1" + }, + { + "id": "{{ id.path }}/annotation/p0005-text", + "type": "Annotation", + "motivation": "painting", + "body": { + "type": "TextualBody", + "format": "text/html", + "value": "In 10 seconds, this text will be replaced by a clock and an image. You will have 30 seconds (shown on the clock) in which to take notes on the image you see. After 30 seconds, the image will be replaced by the start screen. You will not be responsible for the part of the image covered by the clock.
", + "language": "en" + }, + "target": "{{ id.path }}/canvas#xywh=20220,5000,30000,5000&t=1,11" + }, + { + "id": "{{ id.path }}/annotation/p0006-text", + "type": "Annotation", + "motivation": "painting", + "body": { + "type": "TextualBody", + "format": "text/html", + "value": "Close your browser
", + "language": "en" + }, + "target": "{{ id.path }}/canvas#xywh=27000,10200,25000,5000&t=42,180" + } + ] + } + ] + } + ] + } diff --git a/recipe/matrix.md b/recipe/matrix.md index f12808cbd..4a70d9fde 100644 --- a/recipe/matrix.md +++ b/recipe/matrix.md @@ -14,6 +14,7 @@ viewers: - Aviary - Glycerine Viewer - Theseus + - Curation topics: - basic - property