Skip to content

Commit

Permalink
Add a SKLottieView to play Lottie animations (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattleibow authored Jun 29, 2022
1 parent fe4c7bc commit 9e2015e
Show file tree
Hide file tree
Showing 54 changed files with 1,400 additions and 7 deletions.
27 changes: 27 additions & 0 deletions SkiaSharp.Extended.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Maui", "Maui", "{3BAE904F-F
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharpDemo", "samples\Maui\SkiaSharpDemo\SkiaSharpDemo.csproj", "{2C67033A-2C49-4146-B942-9CDD2E0BA412}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Extended.UI.Maui.Tests", "tests\SkiaSharp.Extended.UI.Maui.Tests\SkiaSharp.Extended.UI.Maui.Tests.csproj", "{4B4EC78C-33B5-456D-BD7D-4358D16272F4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -433,6 +435,30 @@ Global
{2C67033A-2C49-4146-B942-9CDD2E0BA412}.Release|x86.ActiveCfg = Release|Any CPU
{2C67033A-2C49-4146-B942-9CDD2E0BA412}.Release|x86.Build.0 = Release|Any CPU
{2C67033A-2C49-4146-B942-9CDD2E0BA412}.Release|x86.Deploy.0 = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|ARM.Build.0 = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|iPhone.Build.0 = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|x64.Build.0 = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Debug|x86.Build.0 = Debug|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|Any CPU.Build.0 = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|ARM.ActiveCfg = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|ARM.Build.0 = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|iPhone.ActiveCfg = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|iPhone.Build.0 = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|x64.ActiveCfg = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|x64.Build.0 = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|x86.ActiveCfg = Release|Any CPU
{4B4EC78C-33B5-456D-BD7D-4358D16272F4}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -454,6 +480,7 @@ Global
{2C0DAB3F-1246-4AE7-BFA5-E7F5DDD7E1C4} = {5DEC7961-7CE3-44D7-A7FC-6185BA2D37FE}
{3BAE904F-F162-4444-AFB6-EA9D288BCDF7} = {51B0C2C7-732B-4A5C-A4F2-55655D147866}
{2C67033A-2C49-4146-B942-9CDD2E0BA412} = {3BAE904F-F162-4444-AFB6-EA9D288BCDF7}
{4B4EC78C-33B5-456D-BD7D-4358D16272F4} = {5555F827-12DF-4D15-BF07-3A720FC2EF3F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {08D78153-5DD7-4C52-A348-46AA448B2CFC}
Expand Down
3 changes: 3 additions & 0 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Task("build")
.Does(() =>
{
var settings = new MSBuildSettings()
{ AllowPreviewVersion = true }
.EnableBinaryLogger("./output/binlogs/build.binlog")
.SetConfiguration("Release")
.SetMaxCpuCount(0)
Expand All @@ -20,6 +21,7 @@ Task("pack")
.Does(() =>
{
MSBuild("./SkiaSharp.Extended-Pack.slnf", new MSBuildSettings()
{ AllowPreviewVersion = true }
.EnableBinaryLogger("./output/binlogs/pack.binlog")
.SetConfiguration("Release")
.SetMaxCpuCount(0)
Expand All @@ -33,6 +35,7 @@ Task("pack")
}

MSBuild("./SkiaSharp.Extended-Pack.slnf", new MSBuildSettings()
{ AllowPreviewVersion = true }
.EnableBinaryLogger("./output/binlogs/pack-preview.binlog")
.SetConfiguration("Release")
.SetMaxCpuCount(0)
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
<AndroidResource Include="Resources\drawable-xxhdpi\icon.png" />
</ItemGroup>
<ItemGroup>
<AndroidAsset Include="Assets\Lottie\trophy.json" />
<None Include="Properties\AndroidManifest.xml" />
</ItemGroup>
<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions samples/Forms/SkiaSharpDemo.UWP/Lottie/trophy.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions samples/Forms/SkiaSharpDemo.UWP/SkiaSharpDemo.UWP.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
<Content Include="Lottie\trophy.json" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
Expand Down
1 change: 1 addition & 0 deletions samples/Forms/SkiaSharpDemo.WPF/Lottie/trophy.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions samples/Forms/SkiaSharpDemo.WPF/SkiaSharpDemo.WPF.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

<ItemGroup>
<Content Include="logo.png" CopyToOutputDirectory="PreserveNewest" />
<Content Include="Lottie\trophy.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

</Project>

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions samples/Forms/SkiaSharpDemo.iOS/SkiaSharpDemo.iOS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<ITunesArtwork Include="iTunesArtwork" />
<ITunesArtwork Include="iTunesArtwork@2x" />
<BundleResource Include="Resources\Lottie\trophy.json" />
</ItemGroup>
<ItemGroup>
<BundleResource Include="Resources\Default-568h%402x.png" />
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
<ItemGroup>
<None Include="Info.plist" />
<None Include="Entitlements.plist" />
<BundleResource Include="Resources\Lottie\trophy.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
Expand Down
1 change: 1 addition & 0 deletions samples/Forms/SkiaSharpDemo/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

<converters:RoundToIntConverter x:Key="RoundToInt" />
<converters:RoundToConverter x:Key="RoundTo" />
<converters:TimeSpanToDoubleConverter x:Key="TimeSpanToDouble" />

<Style TargetType="StackLayout">
<Setter Property="Spacing" Value="0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using System.Globalization;
using Xamarin.Forms;

namespace SkiaSharpDemo.Converters
{
public class TimeSpanToDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
value switch
{
TimeSpan ts => ts.TotalMilliseconds == 0 && parameter is not null
? double.Parse(parameter.ToString())
: ts.TotalMilliseconds,
_ => throw new ArgumentException("Value was not a TimeSpan.", nameof(value)),
};

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
value switch
{
double d => TimeSpan.FromMilliseconds(d),
_ => throw new ArgumentException("Value was not a double.", nameof(value)),
};
}
}
45 changes: 45 additions & 0 deletions samples/Forms/SkiaSharpDemo/Demos/Lottie/LottiePage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:SkiaSharp.Extended.UI.Controls;assembly=SkiaSharp.Extended.UI"
xmlns:views="clr-namespace:SkiaSharpDemo.Views"
x:Class="SkiaSharpDemo.Demos.LottiePage"
Title="Lottie">

<Grid RowDefinitions="*,Auto">

<controls:SKLottieView x:Name="lottieView"
Source="Lottie/trophy.json"
Duration="{Binding Duration}"
Progress="{Binding Progress}"
IsRunning="{Binding IsBusy}"/>

<BoxView Color="Green" Opacity="0.5" CornerRadius="12"
WidthRequest="25" HeightRequest="24" Margin="24"
HorizontalOptions="End" VerticalOptions="Start"
IsVisible="{Binding IsComplete, Source={Reference lottieView}}" />

<StackLayout Spacing="12" Padding="12" Grid.Row="1">

<Slider Minimum="0"
Maximum="{Binding Duration, Converter={StaticResource TimeSpanToDouble}, ConverterParameter=1}"
Value="{Binding Progress, Converter={StaticResource TimeSpanToDouble}}" />

<Grid ColumnDefinitions="*,*" Margin="0,-12,0,0">
<Label Grid.Column="0"
Text="{Binding Progress, StringFormat='{}{0:mm\\:ss\\.fff}'}" />
<Label Grid.Column="1" HorizontalOptions="End"
Text="{Binding Duration, StringFormat='{}{0:mm\\:ss\\.fff}'}" />
</Grid>

<StackLayout Orientation="Horizontal" HorizontalOptions="Center" Spacing="6">
<Button Text="Reset" Command="{Binding ResetCommand}" />
<Button Text="-100ms" Command="{Binding StepCommand}" CommandParameter="-100" />
<Button Text="Play/Pause" Command="{Binding PlayPauseCommand}" />
<Button Text="+100ms" Command="{Binding StepCommand}" CommandParameter="100" />
<Button Text="End" Command="{Binding EndCommand}" />
</StackLayout>

</StackLayout>
</Grid>

</ContentPage>
68 changes: 68 additions & 0 deletions samples/Forms/SkiaSharpDemo/Demos/Lottie/LottiePage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using System.Windows.Input;
using System.Collections.Generic;
using SkiaSharp.Extended.UI.Controls;
using Xamarin.Forms;

namespace SkiaSharpDemo.Demos
{
public partial class LottiePage : ContentPage
{
private TimeSpan duration;
private TimeSpan progress;

public LottiePage()
{
InitializeComponent();

ResetCommand = new Command(OnReset);
StepCommand = new Command<string>(OnStep);
EndCommand = new Command(OnEnd);
PlayPauseCommand = new Command(OnPlayPause);

IsBusy = true;

BindingContext = this;
}

public TimeSpan Duration
{
get => duration;
set
{
duration = value;
OnPropertyChanged();
}
}

public TimeSpan Progress
{
get => progress;
set
{
progress = value;
OnPropertyChanged();
}
}

public ICommand ResetCommand { get; }

public ICommand StepCommand { get; }

public ICommand PlayPauseCommand { get; }

public ICommand EndCommand { get; }

private void OnReset() =>
Progress = TimeSpan.Zero;

private void OnStep(string step) =>
Progress += TimeSpan.FromMilliseconds(int.Parse(step));

private void OnEnd() =>
Progress = Duration;

private void OnPlayPause() =>
IsBusy = !IsBusy;
}
}
7 changes: 7 additions & 0 deletions samples/Forms/SkiaSharpDemo/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ public MainPage()
Color = Color.SteelBlue,
},
new Demo
{
Title = "Lottie",
Description = "Ooooh! Lottie animations are really cool and now super easy to do!",
PageType = typeof(LottiePage),
Color = Color.SteelBlue,
},
new Demo
{
Title = "ToImage",
Description = "You have that ImageSource and you really want an actual image... What do you do? Well, you ToSKImageAsync that puppy!",
Expand Down
1 change: 1 addition & 0 deletions samples/Maui/SkiaSharpDemo/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

<converters:RoundToIntConverter x:Key="RoundToInt" />
<converters:RoundToConverter x:Key="RoundTo" />
<converters:TimeSpanToDoubleConverter x:Key="TimeSpanToDouble" />

</ResourceDictionary>
</Application.Resources>
Expand Down
22 changes: 22 additions & 0 deletions samples/Maui/SkiaSharpDemo/Converters/TimeSpanToDoubleConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Globalization;

namespace SkiaSharpDemo.Converters;

public class TimeSpanToDoubleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
value switch
{
TimeSpan ts => ts.TotalMilliseconds == 0 && parameter is not null
? double.Parse(parameter.ToString())
: ts.TotalMilliseconds,
_ => throw new ArgumentException("Value was not a TimeSpan.", nameof(value)),
};

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
value switch
{
double d => TimeSpan.FromMilliseconds(d),
_ => throw new ArgumentException("Value was not a double.", nameof(value)),
};
}
45 changes: 45 additions & 0 deletions samples/Maui/SkiaSharpDemo/Demos/Lottie/LottiePage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:SkiaSharp.Extended.UI.Controls;assembly=SkiaSharp.Extended.UI"
xmlns:views="clr-namespace:SkiaSharpDemo.Views"
x:Class="SkiaSharpDemo.Demos.LottiePage"
Title="Lottie">

<Grid RowDefinitions="*,Auto">

<controls:SKLottieView x:Name="lottieView"
Source="Lottie/trophy.json"
Duration="{Binding Duration}"
Progress="{Binding Progress}"
IsRunning="{Binding IsBusy}"/>

<BoxView Color="Green" Opacity="0.5" CornerRadius="12"
WidthRequest="25" HeightRequest="24" Margin="24"
HorizontalOptions="End" VerticalOptions="Start"
IsVisible="{Binding IsComplete, Source={Reference lottieView}}" />

<VerticalStackLayout Spacing="12" Padding="12" Grid.Row="1">

<Slider Minimum="0"
Maximum="{Binding Duration, Converter={StaticResource TimeSpanToDouble}, ConverterParameter=1}"
Value="{Binding Progress, Converter={StaticResource TimeSpanToDouble}}" />

<Grid ColumnDefinitions="*,*" Margin="0,-12,0,0">
<Label Grid.Column="0"
Text="{Binding Progress, StringFormat='{}{0:mm\\:ss\\.fff}'}" />
<Label Grid.Column="1" HorizontalOptions="End"
Text="{Binding Duration, StringFormat='{}{0:mm\\:ss\\.fff}'}" />
</Grid>

<HorizontalStackLayout HorizontalOptions="Center" Spacing="6">
<Button Text="Reset" Command="{Binding ResetCommand}" />
<Button Text="-100ms" Command="{Binding StepCommand}" CommandParameter="-100" />
<Button Text="Play/Pause" Command="{Binding PlayPauseCommand}" />
<Button Text="+100ms" Command="{Binding StepCommand}" CommandParameter="100" />
<Button Text="End" Command="{Binding EndCommand}" />
</HorizontalStackLayout>

</VerticalStackLayout>
</Grid>

</ContentPage>
Loading

0 comments on commit 9e2015e

Please sign in to comment.