[uwp]缓存lottie动画帧(代码片段)

lonelyxmas lonelyxmas     2023-02-16     739

关键词:

原文:[UWP]缓存Lottie动画帧

在上一篇博文《[UWP]在UWP平台中使用Lottie动画》中我简单介绍了一下LottieUWP项目以及如何使用它呈现Lottie动画,这篇文章里我们来讲点进阶的东西——缓存Lottie动画帧。

为什么会有这样的需求呢?

有两方面原因:

  • 直接在XAML中使用Lottie动画时,是边播放边渲染,计算量比较大,某些Lottie文件会非常吃性能!另外也会存在渲染不正确(有黑色区域)的情况,但是如果我们把每一帧缓存下来,自己控制播放的话,性能会提升很多!
  • 应用于视频合成时(给视频添加Lottie动画挂件),需要获取每一时刻的动画帧图像(UWP媒体编辑以及视频合成的相关知识也很多,有时间我会整理一下,分享点干货)。

获取Lottie动画帧

在上一篇中我们使用了LottieAnimationView控件来播放Lottie动画,其实另一个类LottieDrawable也可以完成同样的工作,并且更易扩展。

下面我们就来修改下LottieDrawable类,让它可以返回给我们某一时刻的帧图像。

LottieDrawable类中,Lottie动画的播放进度由Progress属性控制,而实际上的呈现则是使用了Win2D中的CanvasAnimatedControl控件来承载绘制目标。

这样的话,其实我们要做的就很简单了。我们可以新增一个GetCurrentFrame方法,使用CanvasRenderTarget作为绘制目标,将CanvasAnimatedControl的Draw事件中的绘制逻辑转移过来即可。

具体代码如下:

        /// <summary>
        /// 获取当前进度时的Lottie图像
        /// </summary>
        /// <param name="resourceCreator"></param>
        /// <param name="scaleX">横向缩放倍数</param>
        /// <param name="scaleY">纵向缩放倍数</param>
        /// <returns></returns>
        public CanvasBitmap GetCurrentFrame(ICanvasResourceCreator resourceCreator, float scaleX, float scaleY)
        
            lock (this)
            
                var width = _composition.Bounds.Width * scaleX;
                var height = _composition.Bounds.Height * scaleY;
                var commandList = new CanvasRenderTarget(resourceCreator, (float)width, (float)height, 96f);
                using (var session = commandList.CreateDrawingSession())
                

                    if (_bitmapCanvas == null || _bitmapCanvas.Width < width || _bitmapCanvas.Height < height)
                    
                        _bitmapCanvas?.Dispose();
                        _bitmapCanvas = new BitmapCanvas(width, height);
                    

                    using (_bitmapCanvas.CreateSession(resourceCreator.Device, (float)width,
                        (float)height, session))
                    
                        _bitmapCanvas.Clear(Colors.Transparent);
                        LottieLog.BeginSection("Drawable.Draw");
                        if (_compositionLayer == null)
                        
                            return null;
                        

                        _matrix.Reset();
                        _matrix = MatrixExt.PreScale(_matrix, scaleX, scaleY);
                        _compositionLayer.Draw(_bitmapCanvas, _matrix, _alpha);
                        LottieLog.EndSection("Drawable.Draw");
                    

                

                return commandList;
            
        

有一点要注意的是这里的绘制目标使用了CanvasRenderTarget,切勿使用CanvasCommandList,区别在于CanvasRenderTarget有固定大小的尺寸,而CanvasCommandList则没有固定的尺寸(实际上时无限大的),使用CanvasCommandList作为绘制目标将会引起某些Lottie动画绘制时丢失部分内容,具体可参见我在LottieUWP项目上提的这个Issue

缓存Lottie动画帧

有了上面添加的GetCurrentFrame方法后,我们就可以通过修改Progress来获取Lottie动画中每一时刻的帧图像了。

我编写了一个缓存Lottie动画帧的方法:

        protected List<CanvasBitmap> CacheLottieFrames;
        /// <summary>
        /// 缓存Lottie动画帧
        /// </summary>
        /// <param name="width">缓存图像的宽</param>
        /// <param name="height">缓存图像的高</param>
        /// <param name="frameRate">缓存的帧率</param>
        /// <returns></returns>
        private async Task InitLottieFrame(double width, double height, int frameRate)
        
            await Task.Run(() =>
            
                lock (_lockObj)
                
                    if (lottieDrawable != null)
                    
                        var duration = lottieDrawable.Composition.Duration;
                        var scaleX = width / lottieDrawable.Composition.Bounds.Width;
                        var scaleY = height / lottieDrawable.Composition.Bounds.Height;
                        var timeGap = 1d / frameRate;
                        CacheLottieFrames = new List<CanvasBitmap>();
                        var device = CanvasDevice.GetSharedDevice();
                        for (var i = 0d; i < duration; i += timeGap)
                        
                            lottieDrawable.Progress = (float)(i / duration);
                            var renderTarget =
                                new CanvasRenderTarget(device, (float)CanvasWidth, (float)CanvasHeight, 96f);
                            using (var session = renderTarget.CreateDrawingSession())
                            
                                session.Clear(Colors.Transparent);
                                var effectImg = lottieDrawable.GetCurrentFrame(device, (float)scaleX, (float)scaleY);
                                if (effectImg != null)
                                    session.DrawImage(effectImg);
                            

                            CacheLottieFrames.Add(renderTarget);
                        
                    
                

            );
        

我们也可以在LottieDrawable.Composition中获取到帧的总数量以及帧率,以此为依据来 获取帧,但是我在这个方法里没有使用,因为我想依据传入的帧率来控制获取的帧数量,避免缓存多余的帧占据内存空间。

结尾

有关于UWP使用Lottie动画的相关博文到这里就结束了,这段时间接触下来,我的感受是Lottie动画真的挺好玩效果也很棒。在LottieFiles网站大家可以找到各种有趣好玩的Lottie动画,当然有能力的也可以自己制作。

本篇博客到此结束!谢谢大家阅读!

Uwp.Ui.Lottie 不显示动画

】Uwp.Ui.Lottie不显示动画【英文标题】:Uwp.Ui.Lottiedoesnotshowanimation【发布时间】:2022-01-1520:01:25【问题描述】:我在UWP项目中使用Microsoft.Toolkit.Uwp.UI.Lottie。简单地说,来自lottiefiles的动画文件在此代码中无效。<muxc:AnimatedVisualPla... 查看详情

uwp图片切换动画使用帧动画(代码片段)

原文:uwp图片切换动画使用帧动画上一篇博客使用了Timer来实现图片的切换,@lindexi_gd讨论了一下性能,我本人其实对性能这一方面不太熟,但我觉得还是有必要考虑一下,那么今天我们使用帧动画开实现以下新建项目,添加一个B... 查看详情

lottie动画在项目中的使用总结(代码片段)

...5.使用注意事项1.控制Lottie动画执行的速度和时间2.Lottie的缓存策略6.在项目中使用示例需求场景:开发实现思路:其他实现思路1:其他开发思路2:7.FQA8.未来方向9.参考资料Lottie动画在项目中的使用 查看详情

lottie动画在项目中的使用总结(代码片段)

...5.使用注意事项1.控制Lottie动画执行的速度和时间2.Lottie的缓存策略6.在项目中使用示例需求场景:开发实现思路:其他实现思路1:其他开发思路2:7.FQA8.未来方向9.参考资料Lottie动画在项目中的使用 查看详情

lottie动画详解(代码片段)

Lottie动画详解文章目录Lottie动画详解Lottie的json文件获取Lottie动画实现动画执行过程监听注意事项参考文献Demo实现Lottie的json文件获取主要是美工来提供需要的动效json文件可以参考这篇文章如何生成动画所需的json文件Lottie动画实... 查看详情

reactnative实现lottie动画(代码片段)

Lottie是Airbnb开源的一个面向iOS、Android、ReactNative的动画库,能加载AdobeAfterEffects导出的动画,并且能让原生App像使用静态素材一样使用这些动画,完美实现炫酷的动画效果。使用流程上,Lottie动画需要先使用AdobeAfterEffects做出原... 查看详情

lottie动画详解(代码片段)

Lottie动画详解文章目录Lottie动画详解Lottie的json文件获取Lottie动画实现动画执行过程监听注意事项参考文献Demo实现Lottie的json文件获取主要是美工来提供需要的动效json文件可以参考这篇文章如何生成动画所需的json文件Lottie动画实... 查看详情

reactnative实现lottie动画(代码片段)

Lottie是Airbnb开源的一个面向iOS、Android、ReactNative的动画库,能加载AdobeAfterEffects导出的动画,并且能让原生App像使用静态素材一样使用这些动画,完美实现炫酷的动画效果。使用流程上,Lottie动画需要先使用AdobeAfterEffects做出原... 查看详情

jetpackcompose中使用lottie动画(代码片段)

从事Android开发的都知道airbnb的Lottie库,如今它也支持在JetpackCompose中使用了。http://airbnb.io/lottie/#/android-compose1.引入lottie-compose在build.gradle添加依赖如下:dependencies...implementation"com.airbnb.andro 查看详情

封装android带lottie动画的底部导航栏(代码片段)

什么是Lottie动画Lottie是Airbnb开源的一个面向iOS、Android、ReactNative的动画库,能分析AdobeAfterEffects导出的动画,并且能让原生App像使用静态素材一样使用这些动画,完美实现动画效果,动画效果比原生动画要优美很... 查看详情

解决electron应用中lottie动画无法正常显示(代码片段)

...执行文件,但是在使用时发现了一个问题,Lottie动画无法显示。通过console的日志可以看到,提示lottie是undifine的,lottie是sdk提供的一个全局的对象,通过lottie.loadAnimation(options)可 查看详情

如果在flutterweb项目中使用lottie动画(代码片段)

前言lottie虽然支持很多平台,但是目前还没有flutter版,那么想要在flutter项目中使用lottie就需要通过调用原生sdk的方式。所以在flutterweb项目中我们需要用lottie的js版本,那么具体如何使用呢?本文将会将lottie封装... 查看详情

音视频开发之旅(63)-lottie源码分析之动画与绘制(代码片段)

目录动画和绘制的流程LayerView树ShapeLayer的分析Lottie优劣以及rLottie、PAG的介绍资料收获上一篇我们学习分析了Lottie的json解析部分.这篇我们分析的动画和渲染部分。分析的重点:如何组织多图层layer的关系,控制先后处理... 查看详情

lottie动画实战(仿汽车之家底部tab切换动画)(代码片段)

GitHub地址:https://github.com/kongpf8848/Animation效果如下:主要是自定义View继承LottieAnimationView并实现Checkable接口,代码如下:importandroid.content.Context;importandroid.util.AttributeSet;importandroid.widget.Checkable;importcom.airbnb.lottie.LottieAnimationView;publi... 查看详情

封装android带lottie动画的底部导航栏(代码片段)

什么是Lottie动画Lottie是Airbnb开源的一个面向iOS、Android、ReactNative的动画库,能分析AdobeAfterEffects导出的动画,并且能让原生App像使用静态素材一样使用这些动画,完美实现动画效果,动画效果比原生动画要优美很... 查看详情

这样做动画交互,一点都不费力!(代码片段)

...导语:Lottie是Airbnb开源的一个面向iOS、Android、ReactNative的动画库,可实现非常复杂的动画,使用也及其简单,极大释放人力,值得一试。一、简介Lottie是Airbnb开源的一个面向iOS、Android、ReactNative的动画库,能分析AdobeAfterEffects导... 查看详情

音视频开发之旅(62)-lottie源码分析之json解析(代码片段)

目录Lottie能做什么Lottie动画使用调用流程Json字段介绍解析为LottieComposition资料总结一、Lottie能做什么在实现动画方面,原生的方式开发成本比较高,airbnb开源的lottie有Android、iOS、RN等多个版本的支持,设计师通过AE设... 查看详情

设置 Lottie 动画的约束 - swift

】设置Lottie动画的约束-swift【英文标题】:SettingconstraintsonLottieanimation-swift【发布时间】:2019-02-2804:33:47【问题描述】:我是swift编码的新手(也是一般编码的新手)-并且正在努力将约束应用于Lottie动画。我能够让它在屏幕上居... 查看详情