如何将插入符号形状动画化为平滑的弧线?

Posted

技术标签:

【中文标题】如何将插入符号形状动画化为平滑的弧线?【英文标题】:How do I animate a caret shape into a smooth arc? 【发布时间】:2021-04-20 03:17:07 【问题描述】:

我想创建一个动画,其中插入符号 (">") 动画成圆弧。它适用于一个应用程序,其中一个插入符号转换为 3/4 圆弧,然后在网络事务运行时旋转。

动画应该是这样的:

每当我尝试做这样的路径动画时,都会得到非常奇怪的结果。如何制作流畅的动画?

【问题讨论】:

【参考方案1】:

这种动画的秘诀是在CAShapeLayer 中安装一个路径,并在路径上使用CABasicAnimation,将路径从起始状态转换为结束状态。棘手的部分是起点和终点路径需要具有相同数量和类型的控制点。

我编写了一个演示应用程序,可以准确地创建上面的动画。你可以download it from Github(链接)

这是来自 repo 的自述文件,其中详细解释了它的工作原理:


CaretToArcAnimation

该项目将插入符号的简单变换动画化为跨越 3/4 圆的弧。它看起来像这样:

它通过动画安装到 CAShapeLayer 中的路径来工作。

为了让路径动画正常工作,起始路径和结束路径需要具有相同数量和类型的控制点。

为了从插入符号到圆弧进行动画处理,它将插入符号创建为 2 条三次贝塞尔曲线。第一条“曲线”(实际上是一条直线)从插入符号的左下角开始,沿着下线段穿过路径的 1/3 和 2/3 点,并在插入符号。这将创建一个呈现为线段的贝塞尔曲线。第二条曲线也是直线贝塞尔曲线。第二个从插入符号的拐角处开始,到左上角结束。

圆弧也由 2 条三次贝塞尔曲线组成,绘制方向与插入符号中的方向相同。但是,选择弧的 Bezier 曲线的控制点以使生成的曲线非常接近 3π/2 弧度或 270 度或圆的 3/4 的弧。圆弧比它替换的插入符号稍大,并且朝向相同。

如果您添加贝塞尔控制点的可视化表示,则更容易理解,如下所示:

插入符号/曲线上的红点是 2 条贝塞尔曲线的端点。圆弧外侧的红点是定义曲线形状的控制点。对于插入符号形状,控制点在直线上,这导致贝塞尔曲线呈直线形状。

我使用this article 来获取两条贝塞尔曲线的控制点。我不想弄清楚数学,所以我只是在该页面的交互式弧形渲染器上设置曲线以绘制 3/8 圆,记下所有控制点的坐标,然后翻转它们以获得第二个贝塞尔曲线。

这是我用来查找 Bezier 控制点的 Bezier Arc approximator web 模拟的屏幕截图:

(在该屏幕截图中,角度滑块以弧度表示。3/4 圆弧的一半是整圆的 3/8,或 2π 的 3/8。2π * 3/8 约为 2.36,所以这是我选择的弧角。)

CaretToArcAnimation 应用定义了一个CaretToArcView 类,它是UIView 的子类。

大部分有趣的工作都是在CaretToArcView 类中完成的。

它有一个静态变量layerClass,它返回CAShapeLayer.self。这会导致视图的支持层被设置为 CAShapeLayer。

class override var layerClass: AnyClass 
        return CAShapeLayer.self
    

CaretToArcView.swift 文件定义了一个枚举 ViewState:

enum ViewState: Int 
    case none
    case caret
    case arc

自定义视图类有一个ViewState 类型的变量viewState。它的初始值为.none,表示视图中没有安装路径。

如果将状态设置为.caret.arc,它会检查当前层路径是否为零。如果是,它会在没有动画的情况下将适当的路径安装到图层中。

如果之前的路径是其他路径类型,它会使用新形状构建路径,并使用之前路径的 fromState 和新路径的 toState 创建一个 CABasicAnimation。动画的持续时间是使用实例变量animationDuration 设置的。动画使用缓入缓出时间,虽然很容易改变。

该类还具有公共函数rotate(_ doRotate: Bool)。如果你用doRotate == false 调用它,它会从视图层移除所有动画。如果你用doRotate == true 调用它,它会向层添加一个无限重复的旋转动画,使用线性时序将其旋转 360°,一遍又一遍。

应用程序的视图控制器驱动CaretToArcView 中的设置,并且它具有防止自定义视图同时调用两个动画的逻辑(如果你这样做会发生奇怪的事情。不要。)

应用程序的屏幕如下图所示。

视图控制器在切换动画期间禁用按钮和开关,并在旋转开关打开且形状正在旋转时禁用“切换”按钮。

【讨论】:

以上是关于如何将插入符号形状动画化为平滑的弧线?的主要内容,如果未能解决你的问题,请参考以下文章

如何沿弧线为图像设置动画

UIView 圆形遮罩动画

如何在 HTML5 中动画和擦除弧线

jQuery,沿弧线制作动画

如何将 svg 路径变形动画合并到 React 应用程序中

如何平滑地将 CSS 动画恢复到当前状态?