lottie动画以及动态修改tabbaritem显示问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lottie动画以及动态修改tabbaritem显示问题相关的知识,希望对你有一定的参考价值。
参考技术A 最近好久没写点东西了,因为公司业务需要,之前做tabbar相关需求,都是很简单的一些需求,这次遇到点问题,所以在此记录下首先关于lottie动画不多叙述,CocoaPods接入库即可使用。
产品的需求是在tabbar加上动画,所以接到需求立刻着手处理,一开始是参考https://blog.csdn.net/weixin_30457065/article/details/102434546这篇文章,这篇文章的实现原理是遍历出tabbaritem的UITabBarSwappableImageView,然后将其隐藏, 待动画结束后在显示出来,刚引入在公司项目中开始是没什么问题的,但是后面UI,产品提出一些问题,
1.在动画结束后UITabBarSwappableImageView才结束,底部tabbar来回不停切换有时候会导致UITabBarSwappableImageView显示不出来。可能正常人都不会不停来会点,但是产品挑出来这毛病必须改不是。
2.由于底部tabbar不是一成不变的,比如说常见的飞猪等首页需要在滑动的时候动态修改底部tab的title,image,selectedImg,tabBarController.tabBar.subviews的控件顺序发生变化,修改后的tabbar首页tabbaritem会跑到subvies的最后,导致根据index获取到的 UITabBarSwappableImageView不是当前选中控制器的tabbaritem的frame ,导致lottie动画出现的位置不对
3.当底部tabbar的某个根视图控制器有许多业务逻辑处理时,切换会出现延迟和卡桢现象。
所以根据上面几个问题做出了相应的优化,自定义了tabbar,需要自取
https://github.com/373748211/yxkTabar
主要方法是在tabbar上添加了7个lottie动画view,然后在设置tabbar时,将选中image设为nil。通过点击tabbaritem代理方法,显示哪个lottieview。
[UWP]缓存Lottie动画帧
原文:[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动画,当然有能力的也可以自己制作。
本篇博客到此结束!谢谢大家阅读!
以上是关于lottie动画以及动态修改tabbaritem显示问题的主要内容,如果未能解决你的问题,请参考以下文章
如何优雅的展示动态图标lottie-react-native
音视频开发之旅(63) -Lottie 源码分析之动画与绘制
音视频开发之旅(63) -Lottie 源码分析之动画与绘制