关键帧 1.1.0

关键帧 1.1.0

测试已测试
语言语言 Obj-CObjective C
许可证 BSD
发布最后发布2017年6月

刘仁玉维护。



关键帧 1.1.0

关键帧

关键帧是将(1)从After Effects文件中提取图像动画数据的一个ExtendScript脚本来与一个对应Android和iOS的渲染库结合起来。关键帧可以用于导出和渲染具有复杂形状和路径曲线的矢量动画,所有这些都在最小的文件体积下实现。

使用方法

在After Effects中开发动画

有关如何使用Keyframes库开发动画的详细约束,请参阅关键帧 After Effects 指令

图像数据提取

使用提取脚本需要安装Adobe After Effects以及Adobe ExtendScript Toolkit。如果已经存在Keyframes JSON文件,则只需要相应的iOS和Android库。

有关在您的AE组件上运行ExtendScript脚本的详细步骤,请参阅此处的详细说明。

iOS渲染

安装

渲染设置

使用从“图像数据提取”步骤生成的JSON blob提供的反序列化程序来创建一个KFVector模型对象。如果您的JSON blob位于assets目录中,可能看起来像这样

NSString *filePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"asset_name" ofType:@"json" inDirectory:nil];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSDictionary *vectorDictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
KFVector *vector = KFVectorFromDictionary(vectorDictionary);

然后可以使用这个KFVector创建一个KFVectorLayerKFVectorLayer可以像正常CALayer一样使用。

KFVectorLayer *layer = [KFVectorLayer layer];
// Set a non-zero layer frame before setting the KFVector is required.
layer.frame = $AnyNonZeroCGRect$;
layer.faceModel = vector;

如果您不希望控制动画并希望使用UIView,还可以使用KFVector创建一个KFVectorView

KFVectorView *view = [[KFVectorView alloc] initWithFrame:$AnyNonZeroCGRect$ faceVector:vector];

播放!

您可以通过在KFVectorLayer上使用startAnimationpauseAnimationresumeAnimationseekToProgress来控制动画。

// Animation will start from beginning.
[layer startAnimation];

// Pause the animation at current progress.
[layer pauseAnimation];

// Resume the animation from where we paused last time.
[layer resumeAnimation];

// Seek to a given progress in range [0, 1]
[layer seekToProgress:0.5]; // seek to the mid point of the animation

Android渲染

下载

下载最新的 JAR 文件 或通过 Gradle 获取

compile 'com.facebook.keyframes:keyframes:1.0'

或 Maven

<dependency>
  <groupId>com.facebook.keyframes</groupId>
  <artifactId>keyframes</artifactId>
  <version>1.0</version>
</dependency>

渲染设置

使用生成的 JSON blob 中的提供反序列化器在 影像数据提取 步骤中创建一个 KFImage 模型对象。如果您的 JSON blob 存在于 assets 目录中,它可能看起来像这样

InputStream stream = getResources().getAssets().open("asset_name");
KFImage kfImage = KFImageDeserializer.deserialize(stream);

现在可以使用这个 KFImage 创建一个 KeyframesDrawable 对象,并将此可绘制对象用作正常的可绘制对象。强烈建议在任何显示 Keyframes 动画的视图中使用软件层。

Drawable kfDrawable = new KeyframesDrawableBuilder().withImage(kfImage).build();

ImageView imageView = (ImageView) findViewById(R.id.some_image_view);
imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
imageView.setImageDrawable(kfDrawable);
imageView.setImageAlpha(0);

播放!

在适当的时候使用可绘制对象的开始和停止动画来开始播放动画或结束当前循环之后的动画。

// Starts a loop that progresses animation from the beginning and invalidates the drawable.
kfDrawable.startAnimation();

// Pause the animation at current progress.
kfDrawable.pauseAnimation();

// Resume the animation from where we paused last time.
kfDrawable.resumeAnimation();

// Stops the animation.
kfDrawable.stopAnimation();

// Stops the animation when the current animation ends.
kfDrawable.stopAnimationAtLoopEnd();

// Starts the animation and plays it once. Will stop at the end
kfDrawable.playOnce();

移动框架

现有的移动框架实现

框架 平台 作者 链接
React Native (命令式 API) Android/IOS Thomas Roos https://github.com/ptomasroos/react-native-keyframes/
Appcelerator Titanium iOS Hans Knoechel https://github.com/hansemannn/ti.keyframes
Appcelerator Titanium Android Michael Gangolf https://github.com/m1ga/ti.keyframes
React Native Android/iOS Underscope https://github.com/underscopeio/react-native-facebook-keyframes
NativeScript Android/IOS Eddy Verbruggen https://github.com/EddyVerbruggen/nativescript-keyframes

理解关键帧模型对象

图像

关键帧中的 Image 包含多个重要字段,这些字段共同描述了一个可动画和可缩放的图像。在最顶层,一个图像包含了如何缩放 (canvas_size) 图像的信息,以及如何以正确的速度播放动画 (frame_rateframe_count)。动画本身并不绑定到图像提取时的离散 frame_rate,因为 Keyframes 渲染库支持分数帧。除了这些 Image 的全局参数之外,一个 Image 还包含一系列 Feature,这些 Feature 描述了要绘制的不同形状,以及 Animation Group,这些 Animation Group 描述了可以一次性应用于多个 Feature 或其他 Animation Group 的变换。

让我们分析这个简单的图像,其中一颗星星在圆圈中上下缩放。动画以 24FPS 导出,帧数显示在左上角,而星星的缩放比例显示在底部。 Star, Real Time

我们一点一点地放慢这个动画。

Star, Slowwwww

特征

Feature 是图像中的任何独立视觉对象。最重要的是,它包括类似 SVG 类型命令的形状绘制命令,这些命令描述了 Feature 在任何给定时间的形状。一个 Feature 可能属于一个更大的 Animation Group,也可以包含它自己的特定动画,包括专用的 STROKE_WIDTH 动画。一个 Feature 的形状也可以随时间变化,使用以下描述的相同的 关键帧插值器 模式。

形状

形状是指一系列的线绘图命令列表,将这些命令连接起来可以描述一段连续的线或可以填充或描边的闭合形状。命令以MoveLineQuadraticCubic命令的序列给出,一个接一个。

以下是上述图像的重要形状,包括相关顶点(正方形)和控制点(圆形)。

Circle Shape Star Shape

动画

变换

Keyframes渲染库支持常见的基于矩阵的变换操作,包括SCALEROTATETRANSLATE。对于特定的Feature,还有一个额外的非矩阵的STROKE_WIDTH可用。Animation可能属于特定的Feature,或者作为更大Animation Group的一部分。

动画进度

动画变换的值以及它们在动画播放过程中的变化由两个关键字段确定:关键帧和计时曲线。通过这两个字段的组合,我们可以计算动画中任何指定时间点变换的值。

关键帧是指动画中具有特定目标值的特定帧。例如,在10帧内对形状进行放大再缩小,我们希望在第0帧和第10帧的缩放值为100%,在第7帧达到最大缩放值150%。在这个例子中,该形状的SCALE变换的关键帧为[0, 7, 10],值分别为[100%, 150%, 100%

计时曲线描述了变换在关键帧之间变化的速度。每个计时曲线被建模为一个从点[0, 0][1, 1]的三次贝塞尔曲线,其中X值是从起点关键帧到终点关键帧的时间进度,Y值描述了特定时间点的值变化:origValue + (destValue - origValue) * Y

对于我们的缩放星星图像,缩放随时间变化的图表如下,显示了顶点和计时曲线的进/出值。

Scale Animation Curve

综合在一起

有了这些来自Image对象的字段以及进度值,我们可以在给定的时间构建出Image的所有形状,以及要应用到形状上的任何变换,并在该帧重新绘制出Image。因为动画由灵活的timing_curves驱动,关键帧Image并不限于离散的整数帧进行播放,但需要注意的是,所有进度值都是相对于帧数给出的。这意味着10帧的动画接受的范围在[0..10]

贡献

请参阅CONTRIBUTING.md以了解如何通过改进此库来帮助我们!