adds Foreground component with docs

This commit is contained in:
Sudev Kiyada 2025-06-03 19:15:24 +05:30
parent c4cd974105
commit 9e023db6dc
Failed to extract signature
31 changed files with 1910 additions and 51 deletions

View file

@ -0,0 +1,53 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import Block from '../Block/Block.svelte';
import { fade } from 'svelte/transition';
import { getContext } from 'svelte';
import type { ScrollyVideoState } from './js/state.svelte';
interface ForegroundProps {
id?: string;
class?: string;
startTime?: number;
endTime?: number;
children?: Snippet;
}
let {
id = '',
class: cls = '',
startTime = 0,
endTime = 1,
children,
}: ForegroundProps = $props();
let componentState: ScrollyVideoState = getContext('scrollyVideoState');
</script>
<Block width="fluid">
{#if componentState.generalData.currentTime >= startTime && componentState.generalData.currentTime <= endTime}
<div
{id}
class={`scrolly-video-foreground ${cls}`}
in:fade={{ delay: 100, duration: 200 }}
out:fade={{ delay: 0, duration: 100 }}
>
{@render children?.()}
</div>
{/if}
</Block>
<style lang="scss">
.scrolly-video-foreground {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 2;
}
</style>

View file

@ -2,6 +2,7 @@
import { defineMeta } from '@storybook/addon-svelte-csf';
import ScrollyVideo from './ScrollyVideo.svelte';
import WithScrollerBase from './demo/WithScrollerBase.svelte';
import WithTimeline from './demo/WithTimeline.svelte';
const { Story } = defineMeta({
title: 'Components/Graphics/ScrollyVideo',
@ -123,15 +124,15 @@
</script>
<script>
import V_9_16 from './videos/v_9_16.mp4';
import V_1_1 from './videos/v_1_1.mp4';
import V_16_9 from './videos/v_16_9.mp4';
import Video_SM from './videos/v_9_16.mp4';
import Video_MD from './videos/v_1_1.mp4';
import Video_LG from './videos/v_16_9.mp4';
import Goldengate from './videos/goldengate.mp4';
const videoSrc = {
V_9_16,
V_1_1,
V_16_9,
Video_SM,
Video_MD,
Video_LG,
Goldengate,
};
@ -158,11 +159,11 @@
{#snippet children(args)}
{#key args}
{#if width < 600}
<ScrollyVideo {...args} src={videoSrc.V_9_16} />
<ScrollyVideo {...args} src={videoSrc.Video_SM} />
{:else if width < 1200}
<ScrollyVideo {...args} src={videoSrc.V_1_1} />
<ScrollyVideo {...args} src={videoSrc.Video_MD} />
{:else}
<ScrollyVideo {...args} src={videoSrc.V_16_9} />
<ScrollyVideo {...args} src={videoSrc.Video_LG} />
{/if}
{/key}
{/snippet}
@ -181,10 +182,18 @@
{/snippet}
</Story>
<Story name="inside ScrollerBase" {args}>
<Story name="Inside ScrollerBase" {args}>
{#snippet children(args)}
{#key args}
<WithScrollerBase />
{/key}
{/snippet}
</Story>
<Story name="Time based foregrounds" {args}>
{#snippet children(args)}
{#key args}
<WithTimeline />
{/key}
{/snippet}
</Story>

View file

@ -2,7 +2,8 @@
import { onDestroy } from 'svelte';
import { flattenObject } from './js/utils.js';
import ScrollyVideo from './js/ScrollyVideo.js';
import { scrollyVideoState } from './js/state.svelte.js';
import type { Snippet } from 'svelte';
import { setContext } from 'svelte';
// Define the props interface
interface Props {
@ -48,6 +49,8 @@
embedded?: boolean;
/** Source for the embedded video. If not provided, defaults to `src` */
embeddedSrc?: string;
/** Children render function */
children?: Snippet;
}
let {
@ -61,6 +64,7 @@
id = '',
embedded = false,
embeddedSrc = '',
children,
...restProps
}: Props = $props();
@ -82,6 +86,10 @@
...restProps,
});
// pass on component state to child components
// this controls fade in and out of foregrounds
setContext('scrollyVideoState', scrollyVideo.componentState);
// Save the new props
lastPropsString = JSON.stringify(restProps);
}
@ -103,8 +111,13 @@
if (scrollyVideo && scrollyVideo.destroy) scrollyVideo.destroy();
});
// heightChange drives the height of the component when autoplay is set to true
let heightChange = $derived.by(() => {
return `calc(${height} * ${1 - scrollyVideoState.autoplayProgress})`;
if (scrollyVideo) {
return `calc(${height} * ${1 - scrollyVideo?.componentState.autoplayProgress})`;
} else {
return height;
}
});
</script>
@ -127,13 +140,18 @@
style="height: {heightChange}; width: 100%; min-height: 100svh;"
>
<div bind:this={scrollyVideoContainer} data-scrolly-container>
{#if showDebugInfo}
{#if showDebugInfo && scrollyVideo}
<p class="debug-info text-xxs font-sans">
{@html JSON.stringify(flattenObject(scrollyVideoState))
{@html JSON.stringify(flattenObject(scrollyVideo.componentState))
.replace(/[{}"]/g, '')
.split(',')
.join('<br>')}
</p>
<!-- renders foregrounds -->
{#if children}
{@render children()}
{/if}
{/if}
</div>
</div>

View file

@ -0,0 +1,74 @@
<script lang="ts">
import ScrollyVideo from '../ScrollyVideo.svelte';
import Foreground from '../Foreground.svelte';
import SM from '../videos/v_9_16.mp4';
import MD from '../videos/v_1_1.mp4';
import LG from '../videos/v_16_9.mp4';
import GraphicBlock from '../../GraphicBlock/GraphicBlock.svelte';
import Headline from '../../Headline/Headline.svelte';
import Annotation1 from './graphic/ai2svelte/annotation1.svelte';
import Annotation2 from './graphic/ai2svelte/annotation2.svelte';
import Annotation3 from './graphic/ai2svelte/annotation3.svelte';
import Annotation4 from './graphic/ai2svelte/annotation4.svelte';
let width = $state(1);
</script>
<svelte:window bind:innerWidth={width} />
{#snippet ScrollForeground()}
<Foreground startTime={0} endTime={0.3}>
<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={0.3} endTime={2.2}>
<GraphicBlock title="" description="" width="fluid">
<Annotation1 />
</GraphicBlock>
</Foreground>
<Foreground startTime={2.2} endTime={3.2}>
<GraphicBlock title="" description="" width="fluid">
<Annotation2 />
</GraphicBlock>
</Foreground>
<Foreground startTime={3.2} endTime={4.5}>
<GraphicBlock title="" description="" width="fluid">
<Annotation3 />
</GraphicBlock>
</Foreground>
<Foreground startTime={6.5} endTime={8}>
<GraphicBlock title="" description="" width="fluid">
<Annotation4 />
</GraphicBlock>
</Foreground>
{/snippet}
{#snippet ScrollVideo(height: string, VideoSrc: string)}
<ScrollyVideo {height} src={VideoSrc} useWebCodecs={true} showDebugInfo>
{@render ScrollForeground()}
</ScrollyVideo>
{/snippet}
{#if width < 600}
{@render ScrollVideo('800svh', SM)}
{:else if width < 1200}
{@render ScrollVideo('800svh', MD)}
{:else}
{@render ScrollVideo('800svh', LG)}
{/if}
<style lang="scss">
:global(.custom-headline *) {
color: white;
}
:global(.scrolly-video-foreground) {
filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.85));
}
</style>

View file

@ -0,0 +1,453 @@
<script>
// @ts-ignore img
import chartXs from '../imgs/annotation1-xs.png';
// @ts-ignore img
import chartSm from '../imgs/annotation1-sm.png';
// @ts-ignore img
import chartMd from '../imgs/annotation1-md.png';
// @ts-ignore img
import chartLg from '../imgs/annotation1-md.png';
// @ts-ignore img
import chartXl from '../imgs/annotation1-xl.png';
let width = null;
</script>
<div id="g-annotation1-box" bind:clientWidth={width}>
<!-- Artboard: xs -->
{#if width && width >= 0 && width < 510}
<div id="g-annotation1-xs" class="g-artboard" style="">
<div style="padding: 0 0 187.8788% 0;"></div>
<div
id="g-annotation1-xs-img"
class="g-aiImg"
style={`background-image: url(${chartXs});`}
></div>
<div
id="g-ai0-1"
class="g-text g-aiAbs g-aiPointText"
style="top:16.5284%;margin-top:-8.5px;left:31.2%;width:166px;"
>
<p class="g-pstyle0">Solid southwest swell</p>
</div>
<div
id="g-ai0-2"
class="g-text g-aiAbs"
style="top:56.9355%;left:20.6061%;width:60.303%;"
>
<p>
Tahitian local Vahine Fierro drops into a double overhead wave during
a recentcompetition. Timing and position are critical to make the
take-off and maximize scoring
</p>
<p></p>
<p>&nbsp;</p>
</div>
<div
id="g-ai0-3"
class="g-text g-aiAbs g-aiPointText"
style="top:85.9639%;margin-top:-17px;left:12.7641%;width:156px;"
>
<p class="g-pstyle1">Shallow water hides</p>
<p class="g-pstyle1">a sharp reef</p>
</div>
</div>
{/if}
<!-- Artboard: sm -->
{#if width && width >= 510 && width < 660}
<div id="g-annotation1-sm" class="g-artboard" style="">
<div style="padding: 0 0 56.2745% 0;"></div>
<div
id="g-annotation1-sm-img"
class="g-aiImg"
style={`background-image: url(${chartSm});`}
></div>
<div
id="g-ai1-1"
class="g-text g-aiAbs g-aiPointText"
style="top:18.807%;margin-top:-17px;left:20.9079%;width:247px;"
>
<p class="g-pstyle0">Wave forms from hitting reef, and</p>
<p class="g-pstyle0">tube will track the line of the shelf</p>
</div>
<div
id="g-ai1-2"
class="g-text g-aiAbs g-aiPointText"
style="top:24.9046%;margin-top:-8.5px;left:69.9921%;width:166px;"
>
<p class="g-pstyle1">Solid southwest swell</p>
</div>
<div
id="g-ai1-3"
class="g-text g-aiAbs g-aiPointText"
style="top:81.8732%;margin-top:-57px;left:39.9944%;width:321px;"
>
<p class="g-pstyle0">Tahitian local Vahine Fierro drops into</p>
<p class="g-pstyle0">a double overhead wave during a recent</p>
<p class="g-pstyle0">competition. Timing and position are critical</p>
<p class="g-pstyle0">to make the take-off and maximize scoring</p>
<p class="g-pstyle0"></p>
<p>&nbsp;</p>
</div>
<div
id="g-ai1-4"
class="g-text g-aiAbs g-aiPointText"
style="top:81.5248%;margin-top:-17px;left:6.6905%;width:156px;"
>
<p class="g-pstyle0">Shallow water hides</p>
<p class="g-pstyle0">a sharp reef</p>
</div>
</div>
{/if}
<!-- Artboard: md -->
{#if width && width >= 660 && width < 930}
<div id="g-annotation1-md" class="g-artboard" style="">
<div style="padding: 0 0 56.3636% 0;"></div>
<div
id="g-annotation1-md-img"
class="g-aiImg"
style={`background-image: url(${chartMd});`}
></div>
<div
id="g-ai2-1"
class="g-text g-aiAbs g-aiPointText"
style="top:19.0796%;margin-top:-17px;left:20.696%;width:247px;"
>
<p class="g-pstyle0">Wave forms from hitting reef, and</p>
<p class="g-pstyle0">tube will track the line of the shelf</p>
</div>
<div
id="g-ai2-2"
class="g-text g-aiAbs g-aiPointText"
style="top:21.6334%;margin-top:-7.5px;left:70.3415%;width:166px;"
>
<p class="g-pstyle1">Solid southwest swell</p>
</div>
<div
id="g-ai2-3"
class="g-text g-aiAbs g-aiPointText"
style="top:66.6602%;margin-top:-57px;left:48.1533%;width:321px;"
>
<p class="g-pstyle0">Tahitian local Vahine Fierro drops into</p>
<p class="g-pstyle0">a double overhead wave during a recent</p>
<p class="g-pstyle0">competition. Timing and position are critical</p>
<p class="g-pstyle0">to make the take-off and maximize scoring</p>
<p class="g-pstyle0"></p>
<p>&nbsp;</p>
</div>
<div
id="g-ai2-4"
class="g-text g-aiAbs g-aiPointText"
style="top:81.714%;margin-top:-17px;left:17.2641%;width:156px;"
>
<p class="g-pstyle0">Shallow water hides</p>
<p class="g-pstyle0">a sharp reef</p>
</div>
</div>
{/if}
<!-- Artboard: lg -->
{#if width && width >= 930 && width < 1200}
<div id="g-annotation1-lg" class="g-artboard" style="">
<div style="padding: 0 0 56.0215% 0;"></div>
<div
id="g-annotation1-lg-img"
class="g-aiImg"
style={`background-image: url(${chartLg});`}
></div>
<div
id="g-ai3-1"
class="g-text g-aiAbs g-aiPointText"
style="top:18.3754%;margin-top:-19.7px;left:20.5759%;width:247px;"
>
<p class="g-pstyle0">Wave forms from hitting reef, and</p>
<p class="g-pstyle0">tube will track the line of the shelf</p>
</div>
<div
id="g-ai3-2"
class="g-text g-aiAbs g-aiPointText"
style="top:25.2353%;margin-top:-10.5px;left:73.3785%;width:166px;"
>
<p class="g-pstyle0">Solid southwest swell</p>
</div>
<div
id="g-ai3-3"
class="g-text g-aiAbs g-aiPointText"
style="top:65.458%;margin-top:-66px;left:46.9484%;width:321px;"
>
<p class="g-pstyle0">Tahitian local Vahine Fierro drops into</p>
<p class="g-pstyle0">a double overhead wave during a recent</p>
<p class="g-pstyle0">competition. Timing and position are critical</p>
<p class="g-pstyle0">to make the take-off and maximize scoring</p>
<p class="g-pstyle0"></p>
<p>&nbsp;</p>
</div>
<div
id="g-ai3-4"
class="g-text g-aiAbs g-aiPointText"
style="top:80.1797%;margin-top:-19.7px;left:17.5746%;width:156px;"
>
<p class="g-pstyle0">Shallow water hides</p>
<p class="g-pstyle0">a sharp reef</p>
</div>
</div>
{/if}
<!-- Artboard: xl -->
{#if width && width >= 1200}
<div id="g-annotation1-xl" class="g-artboard" style="">
<div style="padding: 0 0 51.6667% 0;"></div>
<div
id="g-annotation1-xl-img"
class="g-aiImg"
style={`background-image: url(${chartXl});`}
></div>
<div
id="g-ai4-1"
class="g-text g-aiAbs g-aiPointText"
style="top:20.0355%;margin-top:-25.2px;left:20.6647%;width:304px;"
>
<p class="g-pstyle0">Wave forms from hitting reef, and</p>
<p class="g-pstyle0">tube will track the line of the shelf</p>
</div>
<div
id="g-ai4-2"
class="g-text g-aiAbs g-aiPointText"
style="top:27.6162%;margin-top:-13.2px;left:81.5814%;width:202px;"
>
<p class="g-pstyle0">Solid southwest swell</p>
</div>
<div
id="g-ai4-3"
class="g-text g-aiAbs g-aiPointText"
style="top:63.1%;margin-top:-85.2px;left:47.4753%;width:396px;"
>
<p class="g-pstyle0">Tahitian local Vahine Fierro drops into</p>
<p class="g-pstyle0">a double overhead wave during a recent</p>
<p class="g-pstyle0">competition. Timing and position are critical</p>
<p class="g-pstyle0">to make the take-off and maximize scoring</p>
<p class="g-pstyle0"></p>
<p>&nbsp;</p>
</div>
<div
id="g-ai4-4"
class="g-text g-aiAbs g-aiPointText"
style="top:94.0678%;margin-top:-25.2px;left:20.5662%;width:189px;"
>
<p class="g-pstyle0">Shallow water hides</p>
<p
class="g-
pstyle0"
>
a sharp reef
</p>
</div>
</div>
{/if}
</div>
<!-- End ai2html - 2024-07-19 13:12 -->
<!-- Generated by ai2html v0.100.0 - 2024-07-19 13:12 -->
<!-- ai file: annotation1.ai -->
<style lang="scss">
#g-annotation1-box,
#g-annotation1-box .g-artboard {
margin: 0 auto;
}
#g-annotation1-box p {
margin: 0;
}
#g-annotation1-box .g-aiAbs {
position: absolute;
}
#g-annotation1-box .g-aiImg {
position: absolute;
top: 0;
display: block;
width: 100% !important;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
}
#g-annotation1-box .g-aiPointText p {
white-space: nowrap;
}
#g-annotation1-xs {
position: relative;
overflow: hidden;
}
#g-annotation1-xs p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation1-xs .g-pstyle0 {
line-height: 15px;
height: 15px;
}
#g-annotation1-xs .g-pstyle1 {
height: 16px;
}
#g-annotation1-sm {
position: relative;
overflow: hidden;
}
#g-annotation1-sm p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation1-sm .g-pstyle0 {
height: 16px;
}
#g-annotation1-sm .g-pstyle1 {
line-height: 15px;
height: 15px;
}
#g-annotation1-md {
position: relative;
overflow: hidden;
}
#g-annotation1-md p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation1-md .g-pstyle0 {
height: 16px;
}
#g-annotation1-md .g-pstyle1 {
line-height: 13px;
height: 13px;
}
#g-annotation1-lg {
position: relative;
overflow: hidden;
}
#g-annotation1-lg p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 19px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation1-lg .g-pstyle0 {
height: 19px;
}
#g-annotation1-xl {
position: relative;
overflow: hidden;
}
#g-annotation1-xl p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 24px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 20px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation1-xl .g-pstyle0 {
height: 24px;
}
/* Custom CSS */
</style>

View file

@ -0,0 +1,423 @@
<script>
// @ts-ignore img
import chartXs from '../imgs/annotation2-xs.png';
// @ts-ignore img
import chartSm from '../imgs/annotation2-sm.png';
// @ts-ignore img
import chartMd from '../imgs/annotation2-md.png';
// @ts{width}mg
import chartLg from '../imgs/annotation2-md.png';
// @ts-ignore img
import chartXl from '../imgs/annotation2-xl.png';
let width = null;
</script>
<div id="g-annotation2-box" bind:clientWidth={width}>
<!-- Artboard: xs -->
{#if width && width >= 0 && width < 510}
<div id="g-annotation2-xs" class="g-artboard" style="">
<div style="padding: 0 0 187.8788% 0;"></div>
<div
id="g-annotation2-xs-img"
class="g-aiImg"
style={`background-image: url(${chartXs});`}
></div>
<div
id="g-ai0-1"
class="g-text g-aiAbs g-aiPointText"
style="top:9.0284%;margin-top:-41px;left:17.9779%;width:219px;"
>
<p class="g-pstyle0">The wave at Teahupo'o is</p>
<p class="g-pstyle0">known to be very heavy</p>
<p class="g-pstyle0">with a thick lip that can</p>
<p class="g-pstyle0">easily knock a surfer off the</p>
<p class="g-pstyle0">wave and onto the reef below</p>
</div>
<div
id="g-ai0-2"
class="g-text g-aiAbs g-aiPointText"
style="top:68.8671%;margin-top:-25px;left:12.9181%;width:144px;"
>
<p class="g-pstyle0">Surfer speed is up</p>
<p class="g-pstyle0">to 35 km per hour</p>
<p class="g-pstyle0">(20 mph)</p>
</div>
<div
id="g-ai0-3"
class="g-text g-aiAbs g-aiPointText"
style="top:68.8671%;margin-top:-25px;left:62.8912%;width:149px;"
>
<p class="g-pstyle0">One cubic meter</p>
<p class="g-pstyle0">of water weighs</p>
<p class="g-pstyle0">1,000 kg. (2,200 lb)</p>
</div>
<div
id="g-ai0-4"
class="g-text g-aiAbs"
style="top:78.7097%;left:17.9779%;width:59.0909%;"
>
<p>
A surfer will adjust speed to stay in the tube by dragging a hand to
slow, or pumping the board to speed up
</p>
</div>
</div>
{/if}
<!-- Artboard: sm -->
{#if width && width >= 510 && width < 660}
<div id="g-annotation2-sm" class="g-artboard" style="">
<div style="padding: 0 0 56.2745% 0;"></div>
<div
id="g-annotation2-sm-img"
class="g-aiImg"
style={`background-image: url(${chartSm});`}
></div>
</div>
{/if}
<!-- Artboard: md -->
{#if width && width >= 660 && width < 930}
<div id="g-annotation2-md" class="g-artboard" style="">
<div style="padding: 0 0 56.3636% 0;"></div>
<div
id="g-annotation2-md-img"
class="g-aiImg"
style={`background-image: url(${chartMd});`}
></div>
<div
id="g-ai2-1"
class="g-text g-aiAbs g-aiPointText"
style="top:23.9183%;margin-top:-41px;left:67.1629%;width:219px;"
>
<p class="g-pstyle0">The wave at Teahupo'o is</p>
<p class="g-pstyle0">known to be very heavy</p>
<p class="g-pstyle0">with a thick lip that can</p>
<p class="g-pstyle0">easily knock a surfer off the</p>
<p class="g-pstyle0">wave and onto the reef below</p>
</div>
<div
id="g-ai2-2"
class="g-text g-aiAbs g-aiPointText"
style="top:65.585%;margin-top:-17px;left:51.2917%;width:189px;"
>
<p class="g-pstyle0">Surfer speed is up to</p>
<p class="g-pstyle0">35 km per hour (20 mph)</p>
</div>
<div
id="g-ai2-3"
class="g-text g-aiAbs g-aiPointText"
style="top:74.4559%;margin-top:-25px;left:5.9007%;width:263px;"
>
<p class="g-pstyle0">A surfer will adjust speed to stay in</p>
<p class="g-pstyle0">the tube by dragging a hand to slow,</p>
<p class="g-pstyle0">or pumping the board to speed up</p>
</div>
<div
id="g-ai2-4"
class="g-text g-aiAbs g-aiPointText"
style="top:79.5635%;margin-top:-17px;left:70.1381%;width:199px;"
>
<p class="g-pstyle0">One cubic meter of water</p>
<p class="g-pstyle0">weighs 1,000 kg. (2,200 lb)</p>
</div>
</div>
{/if}
<!-- Artboard: lg -->
{#if width && width >= 930 && width < 1200}
<div id="g-annotation2-lg" class="g-artboard" style="">
<div style="padding: 0 0 56.0215% 0;"></div>
<div
id="g-annotation2-lg-img"
class="g-aiImg"
style={`background-image: url(${chartLg});`}
></div>
<div
id="g-ai3-1"
class="g-text g-aiAbs g-aiPointText"
style="top:22.7846%;margin-top:-47.7px;left:73.261%;width:219px;"
>
<p class="g-pstyle0">The wave at Teahupo'o is</p>
<p class="g-pstyle0">known to be very heavy</p>
<p class="g-pstyle0">with a thick lip that can</p>
<p class="g-pstyle0">easily knock a surfer off the</p>
<p class="g-pstyle0">wave and onto the reef below</p>
</div>
<div
id="g-ai3-2"
class="g-text g-aiAbs g-aiPointText"
style="top:22.7846%;margin-top:-47.7px;left:73.261%;width:219px;"
>
<p class="g-pstyle0">The wave at Teahupo'o is</p>
<p class="g-pstyle0">known to be very heavy</p>
<p class="g-pstyle0">with a thick lip that can</p>
<p class="g-pstyle0">easily knock a surfer off the</p>
<p class="g-pstyle0">wave and onto the reef below</p>
</div>
<div
id="g-ai3-3"
class="g-text g-aiAbs g-aiPointText"
style="top:61.187%;margin-top:-19.8px;left:54.1451%;width:189px;"
>
<p class="g-pstyle0">Surfer speed is up to</p>
<p class="g-pstyle0">35 km per hour (20 mph)</p>
</div>
<div
id="g-ai3-4"
class="g-text g-aiAbs g-aiPointText"
style="top:61.187%;margin-top:-19.8px;left:54.1451%;width:189px;"
>
<p class="g-pstyle0">Surfer speed is up to</p>
<p class="g-pstyle0">35 km per hour (20 mph)</p>
</div>
<div
id="g-ai3-5"
class="g-text g-aiAbs g-aiPointText"
style="top:72.3786%;margin-top:-29.1px;left:22.2898%;width:263px;"
>
<p class="g-pstyle0">A surfer will adjust speed to stay in</p>
<p class="g-pstyle0">the tube by dragging a hand to slow,</p>
<p class="g-pstyle0">or pumping the board to speed up</p>
</div>
<div
id="g-ai3-6"
class="g-text g-aiAbs g-aiPointText"
style="top:72.3786%;margin-top:-29.1px;left:22.2898%;width:263px;"
>
<p class="g-pstyle0">A surfer will adjust speed to stay in</p>
<p class="g-pstyle0">the tube by dragging a hand to slow,</p>
<p class="g-pstyle0">or pumping the board to speed up</p>
</div>
<div
id="g-ai3-7"
class="g-text g-aiAbs g-aiPointText"
style="top:79.6131%;margin-top:-19.8px;left:76.246%;width:199px;"
>
<p class="g-pstyle0">One cubic meter of water</p>
<p class="g-pstyle0">weighs 1,000 kg. (2,200 lb)</p>
</div>
<div
id="g-ai3-8"
class="g-text g-aiAbs g-aiPointText"
style="top:79.6131%;margin-top:-19.8px;left:76.246%;width:199px;"
>
<p class="g-pstyle0">One cubic meter of water</p>
<p class="g-pstyle0">weighs 1,000 kg. (2,200 lb)</p>
</div>
</div>
{/if}
<!-- Artboard: xl -->
{#if width && width >= 1200}
<div id="g-annotation2-xl" class="g-artboard" style="">
<div style="padding: 0 0 51.6667% 0;"></div>
<div
id="g-annotation2-xl-img"
class="g-aiImg"
style={`background-image: url(${chartXl});`}
></div>
<div
id="g-ai4-1"
class="g-text g-aiAbs g-aiPointText"
style="top:23.2613%;margin-top:-61.2px;left:79.2253%;width:268px;"
>
<p class="g-pstyle0">The wave at Teahupo'o is</p>
<p class="g-pstyle0">known to be very heavy</p>
<p class="g-pstyle0">with a thick lip that can</p>
<p class="g-pstyle0">easily knock a surfer off the</p>
<p class="g-pstyle0">wave and onto the reef below</p>
</div>
<div
id="g-ai4-2"
class="g-text g-aiAbs g-aiPointText"
style="top:65.3581%;margin-top:-25.2px;left:54.3241%;width:230px;"
>
<p class="g-pstyle0">Surfer speed is up to</p>
<p class="g-pstyle0">35 km per hour (20 mph)</p>
</div>
<div
id="g-ai4-3"
class="g-text g-aiAbs g-aiPointText"
style="top:76.3258%;margin-top:-37.2px;left:22.0662%;width:323px;"
>
<p class="g-pstyle0">A surfer will adjust speed to stay in</p>
<p class="g-pstyle0">the tube by dragging a hand to slow,</p>
<p class="g-pstyle0">or pumping the board to speed up</p>
</div>
<div
id="g-ai4-4"
class="g-text g-aiAbs g-aiPointText"
style="top:83.2613%;
margin-top:-25.2px;left:81.2408%;width:243px;"
>
<p class="g-pstyle0">One cubic meter of water</p>
<p class="g-pstyle0">weighs 1,000 kg. (2,200 lb)</p>
</div>
</div>
{/if}
</div>
<!-- End ai2html - 2024-07-19 13:14 -->
<!-- Generated by ai2html v0.100.0 - 2024-07-19 13:14 -->
<!-- ai file: annotation2.ai -->
<style lang="scss">
#g-annotation2-box,
#g-annotation2-box .g-artboard {
margin: 0 auto;
}
#g-annotation2-box p {
margin: 0;
}
#g-annotation2-box .g-aiAbs {
position: absolute;
}
#g-annotation2-box .g-aiImg {
position: absolute;
top: 0;
display: block;
width: 100% !important;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
}
#g-annotation2-box .g-aiPointText p {
white-space: nowrap;
}
#g-annotation2-xs {
position: relative;
overflow: hidden;
}
#g-annotation2-xs p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation2-xs .g-pstyle0 {
height: 16px;
}
#g-annotation2-sm {
position: relative;
overflow: hidden;
}
#g-annotation2-md {
position: relative;
overflow: hidden;
}
#g-annotation2-md p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation2-md .g-pstyle0 {
height: 16px;
}
#g-annotation2-lg {
position: relative;
overflow: hidden;
}
#g-annotation2-lg p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 19px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation2-lg .g-pstyle0 {
height: 19px;
}
#g-annotation2-xl {
position: relative;
overflow: hidden;
}
#g-annotation2-xl p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 24px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 20px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation2-xl .g-pstyle0 {
height: 24px;
}
/* Custom CSS */
</style>

View file

@ -0,0 +1,431 @@
<script>
// @ts-ignore img
import chartXs from '../imgs/annotation3-xs.png';
// @ts-ignore img
import chartSm from '../imgs/annotation3-sm.png';
// @ts-ignore img
import chartMd from '../imgs/annotation3-md.png';
// @ts{width}mg
import chartLg from '../imgs/annotation3-md.png';
// @ts-ignore img
import chartXl from '../imgs/annotation3-xl.png';
let width = null;
</script>
<div id="g-annotation3-box" bind:clientWidth={width}>
<!-- Artboard: xs -->
{#if width && width >= 0 && width < 510}
<div id="g-annotation3-xs" class="g-artboard" style="">
<div style="padding: 0 0 187.8788% 0;"></div>
<div
id="g-annotation3-xs-img"
class="g-aiImg"
style={`background-image: url(${chartXs});`}
></div>
<div
id="g-ai0-1"
class="g-text g-aiAbs"
style="top:9.8387%;left:19.697%;width:65.4545%;"
>
<p>
Fierro is envelopedin the barrel for over two seconds, which is a long
time in such an unstable environment
</p>
</div>
<div
id="g-ai0-2"
class="g-text g-aiAbs"
style="top:72.2581%;left:20.303%;width:61.2121%;"
>
<p>
In comptitions, more points are scored for being deep inside a barrel
which raises the chance the wave will close out on top of them.
</p>
</div>
</div>
{/if}
<!-- Artboard: sm -->
{#if width && width >= 510 && width < 660}
<div id="g-annotation3-sm" class="g-artboard" style="">
<div style="padding: 0 0 56.2745% 0;"></div>
<div
id="g-annotation3-sm-img"
class="g-aiImg"
style={`background-image: url(${chartSm});`}
></div>
<div
id="g-ai1-1"
class="g-text g-aiAbs"
style="top:1.7422%;left:46.7588%;width:51.1765%;"
>
<p>
Fierro is envelopedin the barrel for over two seconds, which is a long
time in such an unstable environment
</p>
</div>
<div
id="g-ai1-2"
class="g-text g-aiAbs"
style="top:33.4495%;left:66.1788%;width:29.8039%;"
>
<p>
Surfers often say time distorts inside the barrel, slowing down and
that the crashing wave noise falls silent, asthey expereince a sense
of awe
</p>
</div>
<div
id="g-ai1-3"
class="g-text g-aiAbs"
style="top:72.8223%;left:13.3333%;width:48.2353%;"
>
<p>
In comptitions, more points are scored for being deep inside a barrel
which raises the chance the wave will close out on top of them.
</p>
</div>
</div>
{/if}
<!-- Artboard: md -->
{#if width && width >= 660 && width < 930}
<div id="g-annotation3-md" class="g-artboard" style="">
<div style="padding: 0 0 56.3636% 0;"></div>
<div
id="g-annotation3-md-img"
class="g-aiImg"
style={`background-image: url(${chartMd});`}
></div>
<div
id="g-ai2-1"
class="g-text g-aiAbs"
style="top:7.7957%;left:58.355%;width:28.0303%;"
>
<p>
Fierro is envelopedin the barrel for over two seconds, which is a long
time in such an unstable environment
</p>
</div>
<div
id="g-ai2-2"
class="g-text g-aiAbs"
style="top:45.9677%;left:69.837%;width:26.5152%;"
>
<p>
Surfers often say time distorts inside the barrel, slowing down and
that the crashing wave noise falls silent, as they expereince a sense
of awe
</p>
</div>
<div
id="g-ai2-3"
class="g-text g-aiAbs"
style="top:72.3118%;left:31.3158%;width:28.6364%;"
>
<p>
In comptitions, more points are scored for being deep inside a barrel
which raises the chance the wave will close out on top of them.
</p>
</div>
</div>
{/if}
<!-- Artboard: lg -->
{#if width && width >= 930 && width < 1200}
<div id="g-annotation3-lg" class="g-artboard" style="">
<div style="padding: 0 0 56.0215% 0;"></div>
<div
id="g-annotation3-lg-img"
class="g-aiImg"
style={`background-image: url(${chartLg});`}
></div>
<div
id="g-ai3-1"
class="g-text g-aiAbs"
style="top:16.8906%;left:70.7526%;width:20.7527%;"
>
<p>
Fierro is envelopedin the barrel for over two seconds, which is a long
time in such an unstable environment
</p>
</div>
<div
id="g-ai3-2"
class="g-text g-aiAbs"
style="top:51.4395%;left:68.4341%;width:26.9892%;"
>
<p>
Surfers often say time distorts inside the barrel, slowing down and
that the crashing wave noise falls silent, as they expereince a sense
of awe
</p>
</div>
<div
id="g-ai3-3"
class="g-text g-aiAbs"
style="top:68.5221%;left:38.9959%;width:25.2688%;"
>
<p>
In comptitions, more points are scored for being deep inside a barrel
which raises the chance the wave will close out on top of them.
</p>
</div>
</div>
{/if}
<!-- Artboard: xl -->
{#if width && width >= 1200}
<div id="g-annotation3-xl" class="g-artboard" style="">
<div style="padding: 0 0 51.6667% 0;"></div>
<div
id="g-annotation3-xl-img"
class="g-aiImg"
style={`background-image: url(${chartXl});`}
></div>
<div
id="g-ai4-1"
class="g-text g-aiAbs"
style="top:18.0645%;left:70.725%;width:20.6667%;"
>
<p>
Fierro is envelopedin the barrel for over two seconds, which is a long
time in such an unstable environment
</p>
</div>
<div
id="g-ai4-2"
class="g-text g-aiAbs"
style="top:NaN%;left:5.7255%;width:0.1667%;"
>
<p>&nbsp;</p>
<p class="g-pstyle0">Fierro is enveloped</p>
<p>&nbsp;</p>
<p class="g-pstyle0">in the barrel for over</p>
<p>&nbsp;</p>
<p class="g-pstyle0">2 seconds, which is a</p>
<p>&nbsp;</p>
<p class="g-pstyle0">long time in such an</p>
<p>&nbsp;</p>
<p class="g-pstyle0">unstable environment</p>
<p>&nbsp;</p>
<p class="g-pstyle0">Surfers often say time distorts inside</p>
<p>&nbsp;</p>
<p class="g-pstyle0">the barrel, slowing down and that the</p>
<p>&nbsp;</p>
<p class="g-pstyle0">crashing wave noise falls silent, as</p>
<p>&nbsp;</p>
<p class="g-pstyle0">they expereince a sense of awe</p>
<p>&nbsp;</p>
<p class="g-pstyle0">In comptitions, more points are</p>
<p>&nbsp;</p>
<p class="g-pstyle0">scored for being deep inside a</p>
<p>&nbsp;</p>
<p class="g-pstyle0">barrel which raises the chance</p>
<p>&nbsp;</p>
<p class="g-pstyle0">the wave will close out on top of them.</p>
</div>
<div
id="g-ai4-3"
class="g-text g-aiAbs"
style="top:55.4839%;left:68.4081%;width:26.0833%;"
>
<p>
Surfers often say time distorts inside the barrel, slowing down and
that the crashing wave noise falls silent, as they expereince a sense
of awe
</p>
</div>
<div
id="g-ai4-4"
class="g-text g-aiAbs"
style="top:73.871%;left:38.9915%;width:24.6667%;"
>
<p>
In comptitions, more points are scored for being deep inside a barrel
which raises the chance the wave will close out on top of them.
</p>
</div>
</div>
{/if}
</div>
<!-- End ai2html - 2024-07-19 13:15 -->
<!-- Generated by ai2html v0.100.0 - 2024-07-19 13:15 -->
<!-- ai file: annotation3.ai -->
<style lang="scss">
#g-annotation3-box,
#g-annotation3-box .g-artboard {
margin: 0 auto;
}
#g-annotation3-box p {
margin: 0;
}
#g-annotation3-box .g-aiAbs {
position: absolute;
}
#g-annotation3-box .g-aiImg {
position: absolute;
top: 0;
display: block;
width: 100% !important;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
}
#g-annotation3-xs {
position: relative;
overflow: hidden;
}
#g-annotation3-xs p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(252, 252, 252);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation3-sm {
position: relative;
overflow: hidden;
}
#g-annotation3-sm p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(252, 252, 252);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation3-md {
position: relative;
overflow: hidden;
}
#g-annotation3-md p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(252, 252, 252);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation3-lg {
position: relative;
overflow: hidden;
}
#g-annotation3-lg p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(252, 252, 252);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation3-xl {
position: relative;
overflow: hidden;
}
#g-annotation3-xl p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 24px;
opacity: 1;
letter-spacing: 0em;
font-size: 20px;
text-align: left;
color: rgb(252, 252, 252);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation3-xl .g-pstyle0 {
line-height: 11px;
font-size: 9px;
color: rgb(0, 0, 0);
}
/* Custom CSS */
</style>

View file

@ -0,0 +1,392 @@
<script>
// @ts-ignore img
import chartXs from '../imgs/annotation4-xs.png';
// @ts-ignore img
import chartSm from '../imgs/annotation4-sm.png';
// @ts-ignore img
import chartMd from '../imgs/annotation4-md.png';
// @ts{width}mg
import chartLg from '../imgs/annotation4-md.png';
// @ts-ignore img
import chartXl from '../imgs/annotation4-xl.png';
let width = null;
</script>
<div id="g-annotation4-box" bind:clientWidth={width}>
<!-- Artboard: xs -->
{#if width && width >= 0 && width < 510}
<div id="g-annotation4-xs" class="g-artboard" style="">
<div style="padding: 0 0 187.8788% 0;"></div>
<div
id="g-annotation4-xs-img"
class="g-aiImg"
style={`background-image: url(${chartXs});`}
></div>
<div
id="g-ai0-1"
class="g-text g-aiAbs"
style="top:9.5161%;left:16.1999%;width:61.5152%;"
>
<p>The wave path is a short one, only about 100 yards long</p>
</div>
<div
id="g-ai0-2"
class="g-text g-aiAbs"
style="top:73.871%;left:16.1999%;width:61.5152%;"
>
<p>
Fierro exits the barrel with a score of 9.33 out of 10, as she was
deep in the tube, had good speed and went over the foam ball on her
exit
</p>
</div>
</div>
{/if}
<!-- Artboard: sm -->
{#if width && width >= 510 && width < 660}
<div id="g-annotation4-sm" class="g-artboard" style="">
<div style="padding: 0 0 56.2745% 0;"></div>
<div
id="g-annotation4-sm-img"
class="g-aiImg"
style={`background-image: url(${chartSm});`}
></div>
<div
id="g-ai1-1"
class="g-text g-aiAbs"
style="top:8.3624%;left:8.9136%;width:39.8039%;"
>
<p>The wave path is a short one, only about 100 yards long</p>
</div>
<div
id="g-ai1-2"
class="g-text g-aiAbs"
style="top:34.8432%;left:62.1168%;width:32.3529%;"
>
<p>
Fierro exits the barrel with a score of 9.33 out of 10, as she was
deep in the tube, had good speed and went over the foam ball on her
exit
</p>
</div>
<div
id="g-ai1-3"
class="g-text g-aiAbs"
style="top:68.9895%;left:9.1341%;width:47.2549%;"
>
<p>
The wave heaves so quickly that as it forms, it pulls water off the
reef, creating a ride that is often below sea level - seen as the
surfer exits up and over the wave to higher water
</p>
</div>
</div>
{/if}
<!-- Artboard: md -->
{#if width && width >= 660 && width < 930}
<div id="g-annotation4-md" class="g-artboard" style="">
<div style="padding: 0 0 56.3636% 0;"></div>
<div
id="g-annotation4-md-img"
class="g-aiImg"
style={`background-image: url(${chartMd});`}
></div>
<div
id="g-ai2-1"
class="g-text g-aiAbs"
style="top:9.6774%;left:17.6103%;width:30%;"
>
<p>The wave path is a short one, only about 100 yards long</p>
</div>
<div
id="g-ai2-2"
class="g-text g-aiAbs"
style="top:37.3656%;left:62.5253%;width:30.303%;"
>
<p>
Fierro exits the barrel with a score of 9.33 out of 10, as she was
deep in the tube, had good speed and went over the foam ball on her
exit
</p>
</div>
<div
id="g-ai2-3"
class="g-text g-aiAbs"
style="top:71.2366%;left:15.8065%;width:36.8182%;"
>
<p>
The wave heaves so quickly that as it forms, it pulls water off the
reef, creating a ride that is often below sea level - seen as the
surfer exits up and over the wave to higher water
</p>
</div>
</div>
{/if}
<!-- Artboard: lg -->
{#if width && width >= 930 && width < 1200}
<div id="g-annotation4-lg" class="g-artboard" style="">
<div style="padding: 0 0 56.0215% 0;"></div>
<div
id="g-annotation4-lg-img"
class="g-aiImg"
style={`background-image: url(${chartLg});`}
></div>
<div
id="g-ai3-1"
class="g-text g-aiAbs"
style="top:15.3551%;left:24.4264%;width:23.2258%;"
>
<p>The wave path is a short one,</p>
<p>only about 100 yards long</p>
</div>
<div
id="g-ai3-2"
class="g-text g-aiAbs"
style="top:38.5797%;left:69.5876%;width:25.3763%;"
>
<p>
Fierro exits the barrel with a score of 9.33 out of 10, as she was
deep in the tube, had good speed and went over the foam ball on her
exit
</p>
</div>
<div
id="g-ai3-3"
class="g-text g-aiAbs"
style="top:77.1593%;left:30.5554%;width:26.0215%;"
>
<p>
The wave heaves so quickly that as it forms, it pulls water off the
reef, creating a ride that is often below sea level - seen as the
surfer exits up and over the wave to higher water
</p>
</div>
</div>
{/if}
<!-- Artboard: xl -->
{#if width && width >= 1200}
<div id="g-annotation4-xl" class="g-artboard" style="">
<div style="padding: 0 0 51.6667% 0;"></div>
<div
id="g-annotation4-xl-img"
class="g-aiImg"
style={`background-image: url(${chartXl});`}
></div>
<div
id="g-ai4-1"
class="g-text g-aiAbs g-aiPointText"
style="top:19.5123%;margin-top:-17px;left:27.8891%;width:218px;"
>
<p class="g-pstyle0">The wave path is a short one,</p>
<p class="g-pstyle0">only about 100 yards long</p>
</div>
<div
id="g-ai4-2"
class="g-text g-aiAbs g-aiPointText"
style="top:60.48%;margin-top:-33px;left:68.0232%;width:274px;"
>
<p class="g-pstyle0">Fierro exits the barrel with a score of</p>
<p class="g-pstyle0">9.33 out of 10, as she was deep in the</p>
<p class="g-pstyle0">tube, had good speed and went over</p>
<p class="g-pstyle0">the foam ball on her exit</p>
</div>
<div
id="g-ai4-3"
class="g-text g-aiAbs g-aiPointText"
style="top:82.5768%;margin-top:-33px;left:38.7732%;width:319px;"
>
<p class="g-pstyle0">The wave heaves so quickly that as it forms,</p>
<p class="g-pstyle0">
it pulls water off the reef, creating a rid e that
</p>
<p class="g-pstyle0">is often below sea level - seen as the surfer</p>
<p class="g-pstyle0">exits up and over the wave to higher water</p>
</div>
</div>
{/if}
</div>
<!-- End ai2html - 2024-07-19 13:16 -->
<!-- Generated by ai2html v0.100.0 - 2024-07-19 13:16 -->
<!-- ai file: annotation4.ai -->
<style lang="scss">
#g-annotation4-box,
#g-annotation4-box .g-artboard {
margin: 0 auto;
}
#g-annotation4-box p {
margin: 0;
}
#g-annotation4-box .g-aiAbs {
position: absolute;
}
#g-annotation4-box .g-aiImg {
position: absolute;
top: 0;
display: block;
width: 100% !important;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
}
#g-annotation4-box .g-aiPointText p {
white-space: nowrap;
}
#g-annotation4-xs {
position: relative;
overflow: hidden;
}
#g-annotation4-xs p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation4-sm {
position: relative;
overflow: hidden;
}
#g-annotation4-sm p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation4-md {
position: relative;
overflow: hidden;
}
#g-annotation4-md p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation4-lg {
position: relative;
overflow: hidden;
}
#g-annotation4-lg p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
height: auto;
position: static;
}
#g-annotation4-xl {
position: relative;
overflow: hidden;
}
#g-annotation4-xl p {
font-family:
'Source Sans Pro',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
'Helvetica Neue',
Helvetica,
Arial,
sans-serif;
font-weight: 400;
line-height: 16px;
height: auto;
opacity: 1;
letter-spacing: 0em;
font-size: 16px;
text-align: left;
color: rgb(255, 255, 255);
text-transform: none;
padding-bottom: 0;
padding-top: 0;
mix-blend-mode: normal;
font-style: normal;
position: static;
}
#g-annotation4-xl .g-pstyle0 {
height: 16px;
}
/* Custom CSS */
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -1,7 +1,7 @@
import { UAParser } from 'ua-parser-js';
import videoDecoder from './videoDecoder';
import { debounce, isScrollPositionAtTarget, map } from './utils';
import { scrollyVideoState } from './state.svelte';
import { createComponentState, type ScrollyVideoState } from './state.svelte';
interface ScrollyVideoArgs {
src?: string;
@ -55,6 +55,7 @@ class ScrollyVideo {
usingWebCodecs: boolean; // Whether we are using webCodecs
totalTime: number; // The total time of the video, used for calculating percentage
transitioningRaf: number | null;
componentState: ScrollyVideoState; // Placeholder for component state, if needed
updateScrollPercentage: ((jump: boolean) => void) | undefined;
resize: (() => void) | undefined;
@ -107,6 +108,7 @@ class ScrollyVideo {
this.usingWebCodecs = false; // Whether we are using webCodecs
this.totalTime = 0; // The total time of the video, used for calculating percentage
this.transitioningRaf = null;
this.componentState = createComponentState();
// Make sure that we have a DOM
if (typeof document !== 'object') {
@ -223,12 +225,12 @@ class ScrollyVideo {
(containerBoundingClientRect.height - window.innerHeight);
// if autplay, trim the playing time to last locked video position
if (scrollyVideoState.autoplayProgress > 0) {
if (this.componentState.autoplayProgress > 0) {
scrollPercent = map(
scrollPercent,
0,
1,
scrollyVideoState.autoplayProgress,
this.componentState.autoplayProgress,
1
);
}
@ -238,20 +240,20 @@ class ScrollyVideo {
}
// toggle autoplaying state on manual intervention
if (scrollyVideoState.isAutoPlaying && this.frames) {
if (this.componentState.isAutoPlaying && this.frames) {
if (this.debug) console.warn('Stopping autoplay due to manual scroll');
if (this.usingWebCodecs) {
scrollyVideoState.autoplayProgress = parseFloat(
this.componentState.autoplayProgress = parseFloat(
(this.currentFrame / this.frames.length).toFixed(4)
);
} else {
scrollyVideoState.autoplayProgress = parseFloat(
this.componentState.autoplayProgress = parseFloat(
(this.currentTime / this.totalTime).toFixed(4)
);
}
scrollyVideoState.isAutoPlaying = false;
this.componentState.isAutoPlaying = false;
}
this.videoPercentage = scrollPercent;
@ -606,8 +608,9 @@ class ScrollyVideo {
this.currentTime >= this.targetTime
: this.currentTime <= this.targetTime;
if (scrollyVideoState.isAutoPlaying) {
scrollyVideoState.autoplayProgress = this.currentTime / this.totalTime;
if (this.componentState.isAutoPlaying) {
this.componentState.autoplayProgress =
this.currentTime / this.totalTime;
}
// If we are already close enough to our target, pause the video and return.
@ -805,26 +808,26 @@ class ScrollyVideo {
easing: (i) => i,
autoplay: true,
});
scrollyVideoState.isAutoPlaying = true;
this.componentState.isAutoPlaying = true;
}
updateDebugInfo() {
scrollyVideoState.generalData.src = this.src;
scrollyVideoState.generalData.videoPercentage = parseFloat(
this.componentState.generalData.src = this.src;
this.componentState.generalData.videoPercentage = parseFloat(
this.videoPercentage.toFixed(4)
);
scrollyVideoState.generalData.frameRate = parseFloat(
this.componentState.generalData.frameRate = parseFloat(
this.frameRate.toFixed(2)
);
scrollyVideoState.generalData.currentTime = parseFloat(
this.componentState.generalData.currentTime = parseFloat(
this.currentTime.toFixed(4)
);
scrollyVideoState.generalData.totalTime = parseFloat(
this.componentState.generalData.totalTime = parseFloat(
this.totalTime.toFixed(4)
);
scrollyVideoState.usingWebCodecs = this.usingWebCodecs;
scrollyVideoState.framesData.currentFrame = this.currentFrame;
scrollyVideoState.framesData.totalFrames = this.frames?.length || 0;
this.componentState.usingWebCodecs = this.usingWebCodecs;
this.componentState.framesData.currentFrame = this.currentFrame;
this.componentState.framesData.totalFrames = this.frames?.length || 0;
}
}
export default ScrollyVideo;

View file

@ -20,20 +20,24 @@ export type ScrollyVideoState = {
autoplayProgress: number;
};
export const scrollyVideoState = $state<ScrollyVideoState>({
generalData: {
src: '',
videoPercentage: 0,
frameRate: 0,
currentTime: 0,
totalTime: 0,
},
usingWebCodecs: false,
framesData: {
codec: '',
currentFrame: 0,
totalFrames: 0,
},
isAutoPlaying: false,
autoplayProgress: 0,
});
export function createComponentState(): ScrollyVideoState {
const scrollyVideoState = $state<ScrollyVideoState>({
generalData: {
src: '',
videoPercentage: 0,
frameRate: 0,
currentTime: 0,
totalTime: 0,
},
usingWebCodecs: false,
framesData: {
codec: '',
currentFrame: 0,
totalFrames: 0,
},
isAutoPlaying: false,
autoplayProgress: 0,
});
return scrollyVideoState;
}

View file

@ -1,5 +1,4 @@
import * as MP4Box from 'mp4box';
import { scrollyVideoState } from './state.svelte';
interface MP4BoxBuffer extends ArrayBuffer {
fileStart: number;
@ -167,7 +166,7 @@ const decodeVideo = (
if (info && info.videoTracks && info.videoTracks[0]) {
[{ codec }] = info.videoTracks;
if (debug) console.info('Video with codec:', codec);
scrollyVideoState.framesData.codec = codec;
// scrollyVideoState.framesData.codec = codec;
// Define a type for moov to avoid using 'any'
interface AvcCBox {