【问题标题】:Filling circle animation with UIBezierPath and iOS draw rect使用 UIBezierPath 和 iOS 绘制矩形填充圆形动画
【发布时间】:2017-09-14 16:47:43
【问题描述】:

我在 github 上有这个:https://github.com/evertoncunha/EPCSpinnerView

它会做这个动画:

动画中有一个小故障,当圆圈被填充并且视图正在调整大小时,我不想修复它。

出现故障是因为我通过设置图层角来填充圆圈的方式,所以它看起来像一个圆圈,我随着动画进度增加 lineWidth,它看起来像是从外向内填充。来自 EPCDrawnIconSpinner.swift文件:

let ovalPath = UIBezierPath()
ovalPath.addArc(withCenter: CGPoint(x: ovalRect.midX, y: ovalRect.midY),
                radius: ovalRect.width / 2,
                startAngle: start * CGFloat.pi/180,
                endAngle: end * CGFloat.pi/180, clockwise: true)
layer.cornerRadius = rect.size.height/2
ovalPath.lineWidth = 14 + ((frame.size.width) * progress)

有没有更好的方法可以在不执行图层cornerRadius 的情况下实现此动画?如果我只能画这个

【问题讨论】:

  • 像这样的视图应该调整大小似乎很奇怪?是否真的需要在填充时对尺寸变化进行动画处理?像这样的视图肯定会被放置在屏幕上然后离开那里吗?也许方向的改变可能会改变大小,但我不希望它动画。只需更改大小而无需动画。
  • 我实际上在键盘出现时调整了微调器的大小,所以是的,我需要调整大小。但是我有这个问题,我不能为cornerRadius的变化设置动画,所以我认为我应该正确地绘制它,但是我知道如何。

标签: ios swift animation spinner uibezierpath


【解决方案1】:

我可以想到两种方法来摆脱使用cornerRadius

  1. 使用蒙版圆角,使用形状图层填充

您可以创建一个实心圆的CAShapeLayer,并将一个框架设置为您的视图边界,然后将其分配给您图层的mask 属性。您可以在为视图大小设置动画时设置此蒙版的大小。其次,稍后您将需要创建一个额外的形状(可能类似于您的旋转圆圈),并在该图层上制作线宽动画。面具将确保线条不会向外生长,而只会向内生长。

  1. 动画线宽填充形状的半径

您需要创建一个类似于第一个选项中描述的圆形图层,但您不仅需要为线宽设置动画,还需要为半径设置动画。例如:假设您的视图大小为 40x40。当然,在填充动画开始时,您的形状图层也需要为 40x40。然后将线宽设置为 20pts,并将圆的半径从 20pts 设置为 10pts。一个半径为 10pts、线宽为 20pts 的圆将显示为一个半径为 20pts 的实心圆。

希望这会有所帮助。

【讨论】:

  • 我确实尝试过使用蒙版,但我遇到了以下问题: • 调整大小动画是使用 UIView.beginAnimation 完成的... • 蒙版不会与它的超级视图一起调整大小,您必须始终重新创建或手动更改它的帧,我无法使用 UIView.beginAnimation 实现这一点,因为我没有对该动画的逐帧控制。对于第二种方式,我知道该怎么做,我发现的几个例子就像时钟一样填充圆圈,我找不到由外而内
  • dalton 指出要尝试 CADisplayLink,我会在这里检查并更新 ;)
【解决方案2】:

我最终得到了以下解决方案:

fileprivate func drawPathCompleted(_ ovalRect: CGRect) {

     var size: CGFloat = ovalRect.size.width

     var current = size*(1-progress)

     var pos: CGFloat = lineWidth/2

     while size > current {
       let ovalPath = UIBezierPath(ovalIn: CGRect(x: pos, y: pos, width: size, height: size))
       ovalPath.lineCapStyle = .round
       ovalPath.lineWidth = lineWidth
       ovalPath.stroke()
       let decr = lineWidth/2
       size -= decr
       pos += decr/2
     }
}

在这次提交中,第 243 行: https://github.com/evertoncunha/EPCSpinnerView/commit/87d968846d92aa97e85ff4c58b6664ad7b03f00b#diff-8dc22814328ed859a00acfcf2909854bR242

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 2016-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    相关资源
    最近更新 更多