diff --git a/src/components/@types/global.ts b/src/components/@types/global.ts index 9fb19b5f..f6e3b874 100644 --- a/src/components/@types/global.ts +++ b/src/components/@types/global.ts @@ -56,3 +56,14 @@ export type ForegroundPosition = | 'right' | 'left opposite' | 'right opposite'; + +export type ScrollyVideoForegroundPosition = + | 'top center' + | 'top left' + | 'top right' + | 'bottom center' + | 'bottom left' + | 'bottom right' + | 'center center' + | 'center left' + | 'center right'; diff --git a/src/components/ScrollyVideo/Foreground.svelte b/src/components/ScrollyVideo/Foreground.svelte index e13334a4..c38f0962 100644 --- a/src/components/ScrollyVideo/Foreground.svelte +++ b/src/components/ScrollyVideo/Foreground.svelte @@ -3,7 +3,14 @@ import Block from '../Block/Block.svelte'; import { fade } from 'svelte/transition'; import { getContext } from 'svelte'; + import { Markdown } from '@reuters-graphics/svelte-markdown'; + + // Types import type { ScrollyVideoState } from './js/state.svelte'; + import type { + ContainerWidth, + ScrollyVideoForegroundPosition, + } from '../@types/global'; interface ForegroundProps { id?: string; @@ -11,6 +18,10 @@ startTime?: number; endTime?: number; children?: Snippet; + backgroundColor?: string; + width?: ContainerWidth; + position?: ScrollyVideoForegroundPosition | string; + text?: string | undefined; } let { @@ -19,29 +30,57 @@ startTime = 0, endTime = 1, children, + backgroundColor = '#000', + width = 'normal', + position = 'center center', + text, }: ForegroundProps = $props(); let componentState: ScrollyVideoState = getContext('scrollyVideoState'); - + {#if componentState.generalData.currentTime >= startTime && componentState.generalData.currentTime <= endTime}
- {@render children?.()} +
+ {#if children} + {@render children()} + {/if} +
+ {#if typeof text === 'string' && text.trim() !== ''} + +
+ +
+
+ {/if}
{/if}
diff --git a/src/components/ScrollyVideo/ScrollyVideo.mdx b/src/components/ScrollyVideo/ScrollyVideo.mdx index b6eb85af..d8f4e2d2 100644 --- a/src/components/ScrollyVideo/ScrollyVideo.mdx +++ b/src/components/ScrollyVideo/ScrollyVideo.mdx @@ -365,6 +365,94 @@ The `ScrollyVideo` component can also be used to display different foregrounds b ``` +## With Captions + +The `ScrollyVideo` component can also be used to display captions at specific times in the video. This is useful for providing additional context or information to the viewer. To add captions, you can use the `Foreground` component and pass on the caption as **text** prop. + +To quickly set it up using ArchieML, you can use the following format on your RNGS doc or Google doc: + +```yaml +# ArchieML doc +[blocks] + + type: scrolly-video + id: alps-scrolly + src: videos/alps.mp4 + height: 800svh + + # Array of foregrounds + [.foregrounds] + startTime: 3 + endTime: 7 + text: "#### The Alps\n\nThe Alps stretch across eight countries: France, Switzerland, Italy, Monaco, Liechtenstein, Austria, Germany, and Slovenia, covering about 1,200 kilometers (750 miles)." + :end + + startTime: 9 + endTime: 12 + text: "Mont Blanc, standing at 4,809 meters (15,777 feet), is the highest peak in the Alps and Western Europe, though there's ongoing debate between France and Italy about exactly where the summit lies." + :end + + startTime: 16 + endTime: 20 + text: "#### History\n\nThe Alps were formed around **65 million years** ago when the African and Eurasian tectonic plates collided, pushing the land upward.Over 14 million people live in the Alpine region, with tourism supporting approximately 120 million visitors annually." + :end + [] + :end + +[] +``` + +Then add the following code to your App.svelte or the component where you want to display the scrolly video: + +```svelte + + +{#if block.type == 'scrolly-video'} + + + + + {#each block.foregrounds as caption} + + {/each} + +{/if} + + +``` + ## Advanced usecases For advanced use cases such as looping a particular section of the video, or jumping to a specific time in the video, you can bind `scrollyVideo` prop and take benefits of methods such as `setVideoPercentage` or bindable methods such as `onReady` and `onChange`. This allows for fine-grained control over the video playback and interaction with the scroll position. diff --git a/src/components/ScrollyVideo/ScrollyVideo.stories.svelte b/src/components/ScrollyVideo/ScrollyVideo.stories.svelte index 5daa4714..fbe9f181 100644 --- a/src/components/ScrollyVideo/ScrollyVideo.stories.svelte +++ b/src/components/ScrollyVideo/ScrollyVideo.stories.svelte @@ -3,6 +3,7 @@ import ScrollyVideo from './ScrollyVideo.svelte'; import WithScrollerBase from './demo/WithScrollerBase.svelte'; import WithTimeline from './demo/WithTimeline.svelte'; + import BasicTextBoxes from './demo/BasicTextBoxes.svelte'; const { Story } = defineMeta({ title: 'Components/Graphics/ScrollyVideo', @@ -197,3 +198,11 @@ {/key} {/snippet} + + + {#snippet children(args)} + {#key args} + + {/key} + {/snippet} + diff --git a/src/components/ScrollyVideo/demo/BasicTextBoxes.svelte b/src/components/ScrollyVideo/demo/BasicTextBoxes.svelte new file mode 100644 index 00000000..2f92105b --- /dev/null +++ b/src/components/ScrollyVideo/demo/BasicTextBoxes.svelte @@ -0,0 +1,61 @@ + + + + + + + + + + + + diff --git a/src/components/ScrollyVideo/demo/WithTimeline.svelte b/src/components/ScrollyVideo/demo/WithTimeline.svelte index e4b734c3..3eb4f7cd 100644 --- a/src/components/ScrollyVideo/demo/WithTimeline.svelte +++ b/src/components/ScrollyVideo/demo/WithTimeline.svelte @@ -50,7 +50,13 @@ {/snippet} {#snippet ScrollVideo(height: string, VideoSrc: string)} - + {@render ScrollForeground()} {/snippet} @@ -68,7 +74,7 @@ color: white; } - :global(.scrolly-video-foreground) { + :global(.surf-scrolly .scrolly-video-foreground) { filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.85)); } diff --git a/src/components/ScrollyVideo/videos/drone.mp4 b/src/components/ScrollyVideo/videos/drone.mp4 new file mode 100644 index 00000000..b5fdf747 Binary files /dev/null and b/src/components/ScrollyVideo/videos/drone.mp4 differ