adds quick caption prop
This commit is contained in:
parent
73285cd91b
commit
fbc8d24467
7 changed files with 287 additions and 9 deletions
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
</script>
|
||||
|
||||
<Block width="fluid">
|
||||
<Block class={`scrolly-video-foreground ${cls}`} {id}>
|
||||
{#if componentState.generalData.currentTime >= startTime && componentState.generalData.currentTime <= endTime}
|
||||
<div
|
||||
{id}
|
||||
class={`scrolly-video-foreground ${cls}`}
|
||||
class="scrolly-foreground"
|
||||
in:fade={{ delay: 100, duration: 200 }}
|
||||
out:fade={{ delay: 0, duration: 100 }}
|
||||
>
|
||||
{@render children?.()}
|
||||
<div class="scrolly-video-foreground-item">
|
||||
{#if children}
|
||||
{@render children()}
|
||||
{/if}
|
||||
</div>
|
||||
{#if typeof text === 'string' && text.trim() !== ''}
|
||||
<Block
|
||||
class="scrolly-video-foreground-text {position.split(' ')[1]}"
|
||||
{width}
|
||||
>
|
||||
<div
|
||||
style="background-color: {backgroundColor};"
|
||||
class="foreground-text {position.split(' ')[0]}"
|
||||
>
|
||||
<Markdown source={text} />
|
||||
</div>
|
||||
</Block>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</Block>
|
||||
|
||||
<style lang="scss">
|
||||
.scrolly-video-foreground {
|
||||
@use './../../scss/mixins' as mixins;
|
||||
|
||||
.scrolly-foreground {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:global(.scrolly-video-foreground) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
|
@ -50,4 +89,68 @@
|
|||
justify-content: center;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.scrolly-video-foreground-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:global {
|
||||
.scrolly-video-foreground-text {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
max-width: calc(mixins.$column-width-normal * 0.9);
|
||||
height: 100%;
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 0;
|
||||
}
|
||||
&.right {
|
||||
right: 0;
|
||||
}
|
||||
&.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.foreground-text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 0.25rem;
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
@include mixins.fpy-5;
|
||||
@include mixins.fpx-4;
|
||||
@include mixins.fm-0;
|
||||
|
||||
:global(*) {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.center {
|
||||
top: 50%;
|
||||
}
|
||||
&.top {
|
||||
top: 0;
|
||||
transform: translate(-50%, 50%);
|
||||
}
|
||||
&.bottom {
|
||||
top: 100%;
|
||||
transform: translate(-50%, -150%);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -365,6 +365,94 @@ The `ScrollyVideo` component can also be used to display different foregrounds b
|
|||
</style>
|
||||
```
|
||||
|
||||
## 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
|
||||
<script lang="ts">
|
||||
import {
|
||||
ScrollyVideo,
|
||||
Foreground,
|
||||
} from '@reuters-graphics/graphics-components';
|
||||
import { assets } from '$app/paths';
|
||||
</script>
|
||||
|
||||
{#if block.type == 'scrolly-video'}
|
||||
<ScrollyVideo id={block.id} src={block.src} height={block.height}>
|
||||
<Foreground startTime={0} endTime={2}>
|
||||
<Headline
|
||||
class="custom-headline"
|
||||
hed={content.hed}
|
||||
dek={content.dek}
|
||||
section={content.section}
|
||||
sectionUrl={content.sectionUrl}
|
||||
authors={content.authors}
|
||||
publishTime={content.publishedDate}
|
||||
updateTime={content.updatedDate}
|
||||
/>
|
||||
</Foreground>
|
||||
{#each block.foregrounds as caption}
|
||||
<Foreground
|
||||
startTime={parseFloat(caption.startTime)}
|
||||
endTime={parseFloat(caption.endTime)}
|
||||
text={caption.text}
|
||||
/>
|
||||
{/each}
|
||||
</ScrollyVideo>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
:global {
|
||||
.custom-headline * {
|
||||
color: white;
|
||||
text-shadow: 0 0 10px black;
|
||||
}
|
||||
|
||||
#alps-scrolly .foreground-text {
|
||||
* {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
</Story>
|
||||
|
||||
<Story name="Basic text foreground" {args}>
|
||||
{#snippet children(args)}
|
||||
{#key args}
|
||||
<BasicTextBoxes />
|
||||
{/key}
|
||||
{/snippet}
|
||||
</Story>
|
||||
|
|
|
|||
61
src/components/ScrollyVideo/demo/BasicTextBoxes.svelte
Normal file
61
src/components/ScrollyVideo/demo/BasicTextBoxes.svelte
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<script lang="ts">
|
||||
import ScrollyVideo from '../ScrollyVideo.svelte';
|
||||
import Foreground from '../Foreground.svelte';
|
||||
import Drone from '../videos/drone.mp4';
|
||||
import Headline from '../../Headline/Headline.svelte';
|
||||
</script>
|
||||
|
||||
<ScrollyVideo
|
||||
id="alps-scrolly"
|
||||
height="800svh"
|
||||
src={Drone}
|
||||
useWebCodecs={true}
|
||||
showDebugInfo
|
||||
>
|
||||
<Foreground startTime={0} endTime={2}>
|
||||
<Headline
|
||||
class="custom-headline"
|
||||
hed="ScrollyVideo inside ScrollerBase"
|
||||
dek="This is a demo of ScrollyVideo inside ScrollerBase component."
|
||||
section={'Reuters Graphics'}
|
||||
authors={['Jane Doe']}
|
||||
publishTime={new Date('2020-01-01').toISOString()}
|
||||
/>
|
||||
</Foreground>
|
||||
<Foreground
|
||||
startTime={3}
|
||||
endTime={7}
|
||||
backgroundColor="rgba(0, 0, 0, 0.8)"
|
||||
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).'}
|
||||
position="bottom center"
|
||||
></Foreground>
|
||||
<Foreground
|
||||
startTime={9}
|
||||
endTime={12}
|
||||
backgroundColor="rgba(0, 0, 0, 0.8)"
|
||||
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."}
|
||||
position="bottom center"
|
||||
></Foreground>
|
||||
<Foreground
|
||||
startTime={16}
|
||||
endTime={20}
|
||||
backgroundColor="rgba(0, 0, 0, 0.8)"
|
||||
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.'}
|
||||
position="bottom center"
|
||||
></Foreground>
|
||||
</ScrollyVideo>
|
||||
|
||||
<style lang="scss">
|
||||
:global(.custom-headline *) {
|
||||
color: white;
|
||||
text-shadow: 0 0 10px black;
|
||||
}
|
||||
|
||||
:global {
|
||||
#alps-scrolly .foreground-text {
|
||||
* {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -50,7 +50,13 @@
|
|||
{/snippet}
|
||||
|
||||
{#snippet ScrollVideo(height: string, VideoSrc: string)}
|
||||
<ScrollyVideo {height} src={VideoSrc} useWebCodecs={true} showDebugInfo>
|
||||
<ScrollyVideo
|
||||
class="surf-scrolly"
|
||||
{height}
|
||||
src={VideoSrc}
|
||||
useWebCodecs={true}
|
||||
showDebugInfo
|
||||
>
|
||||
{@render ScrollForeground()}
|
||||
</ScrollyVideo>
|
||||
{/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));
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
BIN
src/components/ScrollyVideo/videos/drone.mp4
Normal file
BIN
src/components/ScrollyVideo/videos/drone.mp4
Normal file
Binary file not shown.
Loading…
Reference in a new issue