简体   繁体   English

使用UIBezierPath和iOS绘制矩形填充圆动画

[英]Filling circle animation with UIBezierPath and iOS draw rect

I have this on github: https://github.com/evertoncunha/EPCSpinnerView 我在github上有这个: https : //github.com/evertoncunha/EPCSpinnerView

It does this animations: 它执行以下动画:

旋转动画

There is a glitch in the animation, when the circle is filling and the view is resizing, and I wan't to fix that. 当圆被填充并且视图调整大小时,动画中会有一个小故障,我将无法修复。

The glitch happens because the way I fill the circle by setting the layer corners, so it looks like a circle, and I increase the lineWidth with the animation progress, and it looks likes it's filling from outside in. From EPCDrawnIconSpinner.swift file: 出现小故障的原因是我通过设置图层角来填充圆的方式,因此它看起来像一个圆,并且随着动画的进行,我增加了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)

Is there a better way that I can achieve this animation without doing the layer cornerRadius thing? 有没有一种更好的方法可以在不执行layer cornerRadius的情况下实现此动画? If I could only draw this 如果我只能画这个

I can think of two ways to get away from using cornerRadius : 我可以想到两种方法来避免使用cornerRadius

  1. Use a mask to round the corners, and use a shape layer to fill 使用蒙版圆角,并使用形状图层填充

You can create a CAShapeLayer of a filled circle, and with a frame set to your view's bounds, then assign it to your layer's mask property. 您可以创建一个实心圆的CAShapeLayer ,并将框架设置为视图的范围,然后将其分配给图层的mask属性。 You can animate the size of this mask as you animate the size of your view. 您可以在为视图的大小设置动画时设置此蒙版的大小。 Secondly, you will need to create an additional shape later (probably similar to your spinning circle), and do the line width animation on this layer. 其次,您将需要稍后创建其他形状(可能与您的旋转圆相似),并在该层上进行线宽动画处理。 The mask will ensure that the line does not grow outwards, but only inwards. 遮罩将确保线条不会向外增长,而只会向内增长。

  1. Animate the line width and radius of the fill shape 动画填充形状的线宽半径

You will need to create a circle shape layer similar to the one described in the first option, but instead of just animating the line width, you'll also need to animate the radius. 您将需要创建一个类似于第一个选项中所述的圆形图层,但是您不仅需要为线宽设置动画,还需要为半径设置动画。 For example: Let's say your view size is 40x40. 例如:假设您的视图尺寸为40x40。 Of course, at the start of the fill animation, your shape layer will also need to be 40x40. 当然,在填充动画开始时,您的形状图层也需要为40x40。 You will then animate the line width to 20pts, and animate the radius of the circle from 20pts to 10pts. 然后,将线宽设置为20pts的动画,并将圆的半径从20pts设置为10pts的动画。 A circle with a radius of 10pts and a line width of 20pts will appear to be a filled circle with a radius of 20pts. 半径为10pts且线宽为20pts的圆似乎是半径为20pts的实心圆。

Hope this helps. 希望这可以帮助。

I ended up with the following solution: 我得到了以下解决方案:

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
     }
}

At this commit, line 243: https://github.com/evertoncunha/EPCSpinnerView/commit/87d968846d92aa97e85ff4c58b6664ad7b03f00b#diff-8dc22814328ed859a00acfcf2909854bR242 在此提交处,第243行: https : //github.com/evertoncunha/EPCSpinnerView/commit/87d968846d92aa97e85ff4c58b6664ad7b03f00b#diff-8dc22814328ed859a00acfcf2909854bR242

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM