Skip to content

Commit

Permalink
perf: Add Lottie bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
ebariche committed Jun 12, 2023
1 parent 22daa68 commit 89b89fe
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 0 deletions.
95 changes: 95 additions & 0 deletions src/AddIns/Uno.UI.Lottie/LottieVisualSourceBase.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
using System.Threading.Tasks;
using Uno.Disposables;

#if NET7_0_OR_GREATER
using System.Runtime.InteropServices.JavaScript;
#endif

#pragma warning disable CA1305 // Specify IFormatProvider

namespace Microsoft.Toolkit.Uwp.UI.Lottie
Expand Down Expand Up @@ -40,7 +44,9 @@ async Task InnerUpdate(CancellationToken ct)
return;
}

#if !NET7_0_OR_GREATER
string[] js;
#endif

var sourceUri = UriSource;
if (_lastSource == null || !_lastSource.Equals(sourceUri))
Expand Down Expand Up @@ -72,6 +78,20 @@ void OnJsonChanged(string updatedJson, string updatedCacheKey)

firstLoad = false;

#if NET7_0_OR_GREATER
_isUpdating = true;

NativeMethods.SetAnimationProperties(
player.HtmlId,
null,
play,
player.Stretch.ToString(),
player.PlaybackRate,
updatedCacheKey,
updatedJson);

_isUpdating = false;
#else
js = new[]
{
"Uno.UI.Lottie.setAnimationProperties({",
Expand All @@ -91,6 +111,7 @@ void OnJsonChanged(string updatedJson, string updatedCacheKey)
};

ExecuteJs(js);
#endif

if (_playState != null && _domLoaded)
{
Expand All @@ -105,6 +126,19 @@ void OnJsonChanged(string updatedJson, string updatedCacheKey)
? UriSource.OriginalString
: Windows.Storage.Helpers.AssetsPathBuilder.BuildAssetUri(UriSource?.PathAndQuery);

#if NET7_0_OR_GREATER
_isUpdating = true;

NativeMethods.SetAnimationProperties(
player.HtmlId,
documentPath ?? string.Empty,
player.AutoPlay,
player.Stretch.ToString(),
player.PlaybackRate,
documentPath ?? "-n-");

_isUpdating = false;
#else
js = new[]
{
"Uno.UI.Lottie.setAnimationProperties({",
Expand All @@ -123,6 +157,7 @@ void OnJsonChanged(string updatedJson, string updatedCacheKey)
"\"});"
};
ExecuteJs(js);
#endif

if (player.AutoPlay)
{
Expand All @@ -137,6 +172,7 @@ void OnJsonChanged(string updatedJson, string updatedCacheKey)
ApplyPlayState();
}

#if !NET7_0_OR_GREATER
void ExecuteJs(string[] js)
{
_isUpdating = true;
Expand All @@ -145,6 +181,7 @@ void ExecuteJs(string[] js)

_isUpdating = false;
}
#endif
}

private void ApplyPlayState()
Expand Down Expand Up @@ -200,6 +237,9 @@ public void Play(double fromProgress, double toProgress, bool looped)
return;
}

#if NET7_0_OR_GREATER
NativeMethods.Play(_player.HtmlId, fromProgress, toProgress, looped);
#else
var js = new[]
{
"Uno.UI.Lottie.play(",
Expand All @@ -214,6 +254,7 @@ public void Play(double fromProgress, double toProgress, bool looped)
};

InvokeJs(js);
#endif
}

void IAnimatedVisualSource.Stop()
Expand All @@ -225,6 +266,9 @@ void IAnimatedVisualSource.Stop()
return;
}

#if NET7_0_OR_GREATER
NativeMethods.Stop(_player.HtmlId);
#else
var js = new[]
{
"Uno.UI.Lottie.stop(",
Expand All @@ -233,6 +277,7 @@ void IAnimatedVisualSource.Stop()
};

InvokeJs(js);
#endif
}

void IAnimatedVisualSource.Pause()
Expand All @@ -242,6 +287,9 @@ void IAnimatedVisualSource.Pause()
return;
}

#if NET7_0_OR_GREATER
NativeMethods.Pause(_player.HtmlId);
#else
var js = new[]
{
"Uno.UI.Lottie.pause(",
Expand All @@ -250,6 +298,7 @@ void IAnimatedVisualSource.Pause()
};

InvokeJs(js);
#endif
}

void IAnimatedVisualSource.Resume()
Expand All @@ -259,6 +308,9 @@ void IAnimatedVisualSource.Resume()
return;
}

#if NET7_0_OR_GREATER
NativeMethods.Resume(_player.HtmlId);
#else
var js = new[]
{
"Uno.UI.Lottie.resume(",
Expand All @@ -267,6 +319,7 @@ void IAnimatedVisualSource.Resume()
};

InvokeJs(js);
#endif
}

public void SetProgress(double progress)
Expand All @@ -276,6 +329,9 @@ public void SetProgress(double progress)
return;
}

#if NET7_0_OR_GREATER
NativeMethods.SetProgress(_player.HtmlId, progress);
#else
var js = new[]
{
"Uno.UI.Lottie.setProgress(",
Expand All @@ -286,6 +342,7 @@ public void SetProgress(double progress)
};

InvokeJs(js);
#endif
}

void IAnimatedVisualSource.Load()
Expand All @@ -302,6 +359,9 @@ void IAnimatedVisualSource.Load()

ApplyPlayState();

#if NET7_0_OR_GREATER
NativeMethods.Resume(_player.HtmlId);
#else
var js = new[]
{
"Uno.UI.Lottie.resume(",
Expand All @@ -310,9 +370,12 @@ void IAnimatedVisualSource.Load()
};

InvokeJs(js);
#endif
}

#if !NET7_0_OR_GREATER
private static string InvokeJs(string[] js) => WebAssemblyRuntime.InvokeJS(string.Concat(js));
#endif

void IAnimatedVisualSource.Unload()
{
Expand All @@ -321,6 +384,9 @@ void IAnimatedVisualSource.Unload()
return;
}

#if NET7_0_OR_GREATER
NativeMethods.Pause(_player.HtmlId);
#else
var js = new[]
{
"Uno.UI.Lottie.pause(",
Expand All @@ -329,8 +395,37 @@ void IAnimatedVisualSource.Unload()
};

InvokeJs(js);
#endif
}

private Size CompositionSize => _compositionSize;

#if NET7_0_OR_GREATER
internal static partial class NativeMethods
{
private const string JsType = "globalThis.Uno.UI.Lottie";

[JSImport($"{JsType}.pause")]
internal static partial void Pause(nint htmlId);

[JSImport($"{JsType}.play")]
internal static partial void Play(nint htmlId, double from, double to, bool loop);

[JSImport($"{JsType}.resume")]
internal static partial void Resume(nint htmlId);

[JSImport($"{JsType}.setAnimationPropertiesNative")]
internal static partial void SetAnimationProperties(nint htmlId, string? jsonPath, bool autoplay, string stretch, double playbackRate, string cacheKey);

[JSImport($"{JsType}.setAnimationPropertiesNative")]
internal static partial void SetAnimationProperties(nint htmlId, string? jsonPath, bool autoplay, string stretch, double playbackRate, string cacheKey, string data);

[JSImport($"{JsType}.setProgress")]
internal static partial void SetProgress(nint htmlId, double progress);

[JSImport($"{JsType}.stop")]
internal static partial void Stop(nint htmlId);
}
#endif
}
}
1 change: 1 addition & 0 deletions src/AddIns/Uno.UI.Lottie/Uno.UI.Lottie.Wasm.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<Import Project="../../targetframework-override.props" />

<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Deterministic>true</Deterministic>

<AssemblyName>Uno.UI.Lottie</AssemblyName>
Expand Down
1 change: 1 addition & 0 deletions src/AddIns/Uno.UI.Lottie/WasmScripts/uno-lottie.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare namespace Uno.UI {
private static _runningAnimations;
private static _numberOfFrames;
static setAnimationProperties(newProperties: LottieAnimationProperties, animationData?: AnimationData): string;
static setAnimationPropertiesNative(id: number, path: string, autoplay: boolean, stretch: string, rate: number, cacheKey: string, data?: string): void;
static stop(elementId: number): string;
static play(elementId: number, fromProgress: number, toProgress: number, looped: boolean): string;
static kill(elementId: number): string;
Expand Down
9 changes: 9 additions & 0 deletions src/AddIns/Uno.UI.Lottie/WasmScripts/uno-lottie.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ var Uno;
});
return "ok";
}
static setAnimationPropertiesNative(id, path, autoplay, stretch, rate, cacheKey, data) {
if (data === undefined) {
Lottie.setAnimationProperties({ elementId: id, jsonPath: path, autoplay: autoplay, stretch: stretch, rate: rate, cacheKey: cacheKey });
}
else {
const animationData = data !== null ? JSON.parse(data) : null;
Lottie.setAnimationProperties({ elementId: id, jsonPath: path, autoplay: autoplay, stretch: stretch, rate: rate, cacheKey: cacheKey }, animationData);
}
}
static stop(elementId) {
Lottie.withPlayer(p => {
const a = Lottie._runningAnimations[elementId].animation;
Expand Down
18 changes: 18 additions & 0 deletions src/AddIns/Uno.UI.Lottie/ts/Uno.UI.Lottie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ namespace Uno.UI {
return "ok";
}

public static setAnimationPropertiesNative(
id: number,
path: string,
autoplay: boolean,
stretch: string,
rate: number,
cacheKey: string,
data?: string) {

if (data === undefined) {
Lottie.setAnimationProperties({ elementId: id, jsonPath: path, autoplay: autoplay, stretch: stretch, rate: rate, cacheKey: cacheKey });
} else {
const animationData = data !== null ? <AnimationData>JSON.parse(data) : null;

Lottie.setAnimationProperties({ elementId: id, jsonPath: path, autoplay: autoplay, stretch: stretch, rate: rate, cacheKey: cacheKey }, animationData);
}
}

public static stop(elementId: number): string {
Lottie.withPlayer(p => {
const a = Lottie._runningAnimations[elementId].animation;
Expand Down

0 comments on commit 89b89fe

Please sign in to comment.