diff --git a/perf-test/app/page.tsx b/perf-test/app/page.tsx index 038a1c8..bb8a6af 100644 --- a/perf-test/app/page.tsx +++ b/perf-test/app/page.tsx @@ -2,20 +2,10 @@ import { Listbox, ListboxOption, ListboxOptions, Transition } from '@headlessui/react'; import { Fragment, useEffect, useState } from 'react'; import { CheckIcon, ChevronUpDownIcon } from '@heroicons/react/20/solid'; -import { DotLottieReact, setWasmUrl as setDotLottieWasmUrl } from '@lottiefiles/dotlottie-react'; -import { Player } from '@lottiefiles/react-lottie-player'; -import { isMobile } from 'react-device-detect'; -import reactLottiePlayerPkg from "@lottiefiles/react-lottie-player/package.json"; -import dotLottieReactPkg from "@lottiefiles/dotlottie-react/package.json"; -import dotLottieWasmUrl from "../node_modules/@lottiefiles/dotlottie-web/dist/dotlottie-player.wasm"; -import SkottiePlayer, { setCanvasKit } from '../components/SkottiePlayer'; -import skottieWasmUrl from "../node_modules/canvaskit-wasm/bin/full/canvaskit.wasm"; -import InitCanvasKit from 'canvaskit-wasm/bin/full/canvaskit'; +import { isDesktop } from 'react-device-detect'; // import wasmUrl from "../node_modules/@thorvg/lottie-player/dist/thorvg-wasm.wasm"; const wasmUrl = '/thorvg-wasm.wasm'; -setDotLottieWasmUrl(dotLottieWasmUrl); - const animations = [ '1643-exploding-star.json', '5317-fireworkds.json', @@ -117,47 +107,42 @@ const animations = [ 'water_filling.json', 'waves.json', 'yarn_loading.json' -]; - -const urlPrefix = 'https://raw.githubusercontent.com/thorvg/thorvg/main/examples/resources/lottie/'; - -const countOptions = [ - { id: 0, name: 10 }, - { id: 1, name: 20 }, - { id: 2, name: 50 }, - { id: 3, name: 100 }, - //{ id: 4, name: 200 }, - //{ id: 5, name: 500 }, - //{ id: 6, name: 1000 }, -]; - -const playerOptions = [ - { id: 1, name: 'ThorVG(Software)' }, - { id: 2, name: 'ThorVG(WebGPU)' }, - //{ id: 3, name: `dotlottie-web@${dotLottieReactPkg.dependencies["@lottiefiles/dotlottie-web"]}` }, - //{ id: 4, name: `lottie-web@${reactLottiePlayerPkg.dependencies["lottie-web"]}` }, - //{ id: 5, name: 'skia/skottie' }, -]; +] as const; + +enum PlayerOption { + ThorVG_Software = 'ThorVG(Software)', + ThorVG_WebGPU = 'ThorVG(WebGPU)', +} + +interface Animation { + name: string; + lottieURL: string; +} + +const DEFAULT_COUNT = 20; +const EXAMPLE_URL_PREFIX = 'https://raw.githubusercontent.com/thorvg/thorvg/main/examples/resources/lottie/'; +const COUNT_OPTIONS = [10, 20, 50, 100] as const; function classNames(...classes: any) { - return classes.filter(Boolean).join(' ') + return classes.filter(Boolean).join(' '); } -function setQueryStringParameter(name: string, value: any) { +function setQueryStringParameter(name: string, value: string) { const params = new URLSearchParams(window.location.search); params.set(name, value); window.history.replaceState({}, '', decodeURIComponent(`${window.location.pathname}?${params}`)); } +let initialized = false; export default function Home() { - const size = isMobile ? { width: 150, height: 150 } : { width: 180, height: 180}; - let initialized = false; - - const [count, setCount] = useState(countOptions[1]); - const [player, setPlayer] = useState(playerOptions[0]); - const [playerId, setPlayerId] = useState(1); + const size = isDesktop ? 180 : 150; + + const [count, setCount] = useState(DEFAULT_COUNT); + const [player, setPlayer] = useState(PlayerOption.ThorVG_Software); + const [activePlayer, setActivePlayer] = useState(PlayerOption.ThorVG_Software); + const [text, setText] = useState(''); - const [animationList, setAnimationList] = useState([]); + const [animationList, setAnimationList] = useState([]); useEffect(() => { if (initialized) { @@ -165,37 +150,30 @@ export default function Home() { } initialized = true; - // @ts-ignore - import("/public/lottie-player.js"); - - let count: number = countOptions[1].name; - let seed: string = ''; - let playerId = 1; - + let seed: string | null = null; + let count = DEFAULT_COUNT; if (window.location.search) { const params = new URLSearchParams(window.location.search); - const player = params.get('player'); - count = parseInt(params.get('count') ?? '20'); - seed = params.get('seed') ?? ''; + const playerString = params.get('player'); + const countString = params.get('count'); + seed = params.get('seed'); - if (count) { - const _count = countOptions.find((c) => c.name === count) || countOptions[1]; - setCount(_count); + if (countString) { + count = parseInt(countString); + setCount(count); } - if (player) { - const _player = playerOptions.find((p) => p.name === player) || playerOptions[0]; - playerId = _player.id; - setPlayer(_player); - setPlayerId(_player.id); + if (playerString) { + const player = playerString as PlayerOption; + setPlayer(player); + setActivePlayer(player); } } - - setTimeout(async () => { - if (playerId === 4) { - await loadCanvasKit(); - } + // @ts-ignore + import("/public/lottie-player.js"); + + requestAnimationFrame(async () => { loadProfiler(); if (seed) { @@ -204,15 +182,8 @@ export default function Home() { } loadAnimationByCount(count); - }, 500); - }, []); - - const loadCanvasKit = async () => { - const canvasKit = await InitCanvasKit({ - locateFile: (_) => skottieWasmUrl, }); - setCanvasKit(canvasKit); - } + }, []); const loadProfiler = () => { const script = document.createElement("script"); @@ -220,46 +191,46 @@ export default function Home() { document.body.appendChild(script); } - const loadAnimationByCount = async (_count = count.name) => { + const loadAnimationByCount = async (count = DEFAULT_COUNT) => { const newAnimationList = []; - for (let i = 0; i < _count; i++) { + for (let i = 0; i < count; i++) { const _anim = animations[Math.floor(Math.random() * animations.length)]; newAnimationList.push({ name: _anim.split('/').pop()?.split('.')[0] || 'Unknown', - lottieURL: `${urlPrefix}${_anim}`, + lottieURL: `${EXAMPLE_URL_PREFIX}${_anim}`, }); } - // @ts-ignore - await setAnimationList([]); - await setAnimationList(newAnimationList); - + setAnimationList([...newAnimationList]); saveCurrentSeed(newAnimationList); }; - const saveCurrentSeed = (animationList: any[]) => { - const nameList = animationList.map((v: any) => v.name).join(','); + const saveCurrentSeed = (animationList: Animation[]) => { + const nameList = animationList.map((animation) => animation.name).join(','); const seed = btoa(nameList); setQueryStringParameter('seed', seed); } const loadSeed = (seed: string) => { const nameList = atob(seed).split(','); - console.log(nameList); const newAnimationList = nameList.map((name: string) => { - const _anim = animations.find((anim) => anim === `${name.trim()}.json`) || animations[0]; - + const anim = animations.find((anim) => anim === `${name.trim()}.json`) || animations[0]; return { name: name, - lottieURL: `${urlPrefix}${_anim}`, + lottieURL: `${EXAMPLE_URL_PREFIX}${anim}`, }; }); setAnimationList(newAnimationList); } + const setNewOption = () => { + setQueryStringParameter('seed', ''); + window.location.reload(); + } + const spawnAnimation = () => { if (!text.trimEnd().trimStart()) { alert("Please enter a valid link"); @@ -272,9 +243,18 @@ export default function Home() { animationList[randomIndex].name = text.split('/').pop()?.split('.')[0] || 'Unknown'; setAnimationList(animationList.slice()); - setTimeout(() => { - document.querySelector(`.${animationList[randomIndex].name}-${randomIndex}`)?.scrollIntoView({ behavior: 'smooth' }); - }, 150); + requestAnimationFrame(() => { + const animationSelector = `.${animationList[randomIndex].name}-${randomIndex} > lottie-player`; + const targetPlayer = document.querySelector(animationSelector); + + if (targetPlayer) { + targetPlayer.scrollIntoView({ behavior: 'smooth' }); + // @ts-ignore + targetPlayer.destroy(); + // @ts-ignore + targetPlayer.load(text); + } + }); }; return ( @@ -285,15 +265,15 @@ export default function Home() {

Player:

- { - setPlayer(v); - setQueryStringParameter('player', v.name); + { + setPlayer(selectedPlayer as PlayerOption); + setQueryStringParameter('player', selectedPlayer); }}> {({ open }) => ( <>
- {player.name} + {player} @@ -307,10 +287,10 @@ export default function Home() { leaveTo="opacity-0" > - {playerOptions.map((player) => ( + {Object.values(PlayerOption).map((player) => ( + key={player} + className={({ active }: { active: boolean }) => classNames( active ? 'bg-indigo-600 text-white' : 'text-gray-900', 'relative cursor-default select-none py-2 pl-3 pr-9' @@ -321,7 +301,7 @@ export default function Home() { {({ selected, active }) => ( <> - {player.name} + {player} {selected ? ( @@ -345,15 +325,15 @@ export default function Home() { )} - { - setCount(v); - setQueryStringParameter('count', v.name); + { + setCount(selectedCount); + setQueryStringParameter('count', selectedCount.toString()); }}> {({ open }) => ( <>
- {count.name} + {count} @@ -367,10 +347,10 @@ export default function Home() { leaveTo="opacity-0" > - {countOptions.map((option) => ( + {COUNT_OPTIONS.map((option) => ( + key={option} + className={({ active }: { active: boolean }) => classNames( active ? 'bg-indigo-600 text-white' : 'text-gray-900', 'relative cursor-default select-none py-2 pl-3 pr-9' @@ -381,10 +361,10 @@ export default function Home() { {({ selected, active }) => ( <> - {option.name} + {option} - {selected ? ( + {selected && ( - ) : null} + )} )} @@ -404,18 +384,15 @@ export default function Home() { )} - - -
+ + +