|
1 | 1 | <script lang="ts">
|
2 |
| - // FORKED to support Svelte 5 cleanly and have access to the latest @lottiefiles/dotlottie-web |
3 |
| - // CHANGED STYLES: To support better responsiveness |
4 |
| - // ORGINAL SOURCE: https://github.com/LottieFiles/dotlottie-web/blob/main/packages/svelte/src/lib/Dotlottie.svelte |
5 |
| - // MIT LICENSED |
| 2 | + // FORKED to support: |
| 3 | + // - Svelte 5 cleanly and have access to the latest @lottiefiles/dotlottie-web |
| 4 | + // - Styles to support better responsiveness |
| 5 | + // - WebWorker for performance `DotLottieWorker as DotLottie`, src to full url if needed for the Worker, and workerId. |
| 6 | + // - playOnVisible: Added support for viewport playing |
| 7 | + // ORGINAL SOURCE (MIT LICENSED): https://github.com/LottieFiles/dotlottie-web/blob/main/packages/svelte/src/lib/Dotlottie.svelte |
6 | 8 | import { onMount } from 'svelte';
|
7 |
| - import { DotLottie, type Config } from '@lottiefiles/dotlottie-web'; |
| 9 | + import { DotLottieWorker as DotLottie, type Config } from '@lottiefiles/dotlottie-web'; |
| 10 | + import viewport from '$lib/util/useViewportAction'; |
8 | 11 |
|
9 | 12 | export function setWasmUrl(url: string): void {
|
10 | 13 | DotLottie.setWasmUrl(url);
|
|
28 | 31 | export let themeId: string = '';
|
29 | 32 | export let themeData: string = '';
|
30 | 33 |
|
| 34 | + export let playOnVisible: boolean = false; |
| 35 | +
|
31 | 36 | export let dotLottieRefCallback: (dotLottie: DotLottie) => void = () => {};
|
32 | 37 |
|
33 | 38 | const hoverHandler = (event: MouseEvent) => {
|
|
44 | 49 | let canvas: HTMLCanvasElement;
|
45 | 50 | let prevSrc: string | undefined = undefined;
|
46 | 51 | let prevData: Config['data'] = undefined;
|
| 52 | + // Render each different src in a different worker |
| 53 | + let workerId = 'lottie-' + src.replace('/', '-'); |
47 | 54 |
|
48 | 55 | onMount(() => {
|
49 | 56 | const shouldAutoplay = autoplay && !playOnHover;
|
50 | 57 | dotLottie = new DotLottie({
|
51 | 58 | canvas,
|
52 |
| - src, |
| 59 | + src: src.includes('://') ? src : new URL(src, self.location.href).toString(), |
53 | 60 | autoplay: shouldAutoplay,
|
54 | 61 | loop,
|
55 | 62 | speed,
|
56 | 63 | data,
|
57 |
| - renderConfig, |
| 64 | + renderConfig: playOnVisible ? { freezeOnOffscreen: false, ...renderConfig } : renderConfig, |
58 | 65 | segment,
|
59 | 66 | useFrameInterpolation,
|
60 | 67 | backgroundColor,
|
61 | 68 | mode,
|
| 69 | + layout, |
| 70 | + workerId, |
62 | 71 | });
|
63 | 72 |
|
64 | 73 | if (dotLottieRefCallback) {
|
|
133 | 142 |
|
134 | 143 | $: if (dotLottie && src !== prevSrc) {
|
135 | 144 | dotLottie.load({
|
136 |
| - src, |
| 145 | + src: src.includes('://') ? src : new URL(src, self.location.href).toString(), |
137 | 146 | autoplay,
|
138 | 147 | loop,
|
139 | 148 | speed,
|
140 | 149 | data,
|
141 |
| - renderConfig, |
| 150 | + renderConfig: playOnVisible ? { freezeOnOffscreen: false, ...renderConfig } : renderConfig, |
142 | 151 | segment,
|
143 | 152 | useFrameInterpolation,
|
144 | 153 | backgroundColor,
|
145 | 154 | mode,
|
146 | 155 | marker,
|
147 | 156 | layout,
|
| 157 | + workerId, |
148 | 158 | });
|
149 | 159 | prevSrc = src;
|
150 | 160 | }
|
|
156 | 166 | loop,
|
157 | 167 | speed,
|
158 | 168 | data,
|
159 |
| - renderConfig, |
| 169 | + renderConfig: playOnVisible ? { freezeOnOffscreen: false, ...renderConfig } : renderConfig, |
160 | 170 | segment,
|
161 | 171 | useFrameInterpolation,
|
162 | 172 | backgroundColor,
|
163 | 173 | mode,
|
164 | 174 | marker,
|
165 | 175 | layout,
|
| 176 | + workerId, |
166 | 177 | });
|
167 | 178 | prevData = data;
|
168 | 179 | }
|
|
180 | 191 | }
|
181 | 192 | </script>
|
182 | 193 |
|
183 |
| -<div> |
184 |
| - <canvas bind:this={canvas}></canvas> |
185 |
| -</div> |
186 |
| - |
187 |
| -<style> |
188 |
| - div { |
189 |
| - width: 100%; |
190 |
| - height: auto; |
191 |
| - display: flex; |
192 |
| - justify-content: center; |
193 |
| - } |
194 |
| - canvas { |
195 |
| - width: 100%; |
196 |
| - height: auto; |
197 |
| - display: block; |
198 |
| - object-fit: contain; |
199 |
| - } |
200 |
| -</style> |
| 194 | +{#if playOnVisible} |
| 195 | + <canvas |
| 196 | + class={`block h-full w-full ${$$restProps.class}`} |
| 197 | + bind:this={canvas} |
| 198 | + use:viewport={{ threshold: 0.3 }} |
| 199 | + on:enterViewport={() => { |
| 200 | + dotLottie?.setFrame(0); |
| 201 | + dotLottie?.play(); |
| 202 | + }} |
| 203 | + on:exitViewport={() => { |
| 204 | + dotLottie?.stop(); |
| 205 | + }} |
| 206 | + > |
| 207 | + </canvas> |
| 208 | +{:else} |
| 209 | + <canvas class={$$restProps.class} bind:this={canvas}></canvas> |
| 210 | +{/if} |
0 commit comments