画圆的动画 [英] Animate drawing of a circle

查看:110
本文介绍了画圆的动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种动画制作圆形图的方法。我已经能够创建圆,但是将其全部绘制。

I'm looking for a way to animate the drawing of a circle. I have been able to create the circle, but it draws it all together.

这是我的 CircleView 类:

import UIKit

class CircleView: UIView {
  override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.clearColor()
  }

  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }


  override func drawRect(rect: CGRect) {
    // Get the Graphics Context
    var context = UIGraphicsGetCurrentContext();

    // Set the circle outerline-width
    CGContextSetLineWidth(context, 5.0);

    // Set the circle outerline-colour
    UIColor.redColor().set()

    // Create Circle
    CGContextAddArc(context, (frame.size.width)/2, frame.size.height/2, (frame.size.width - 10)/2, 0.0, CGFloat(M_PI * 2.0), 1)

    // Draw
    CGContextStrokePath(context);
  }
}

这是将其添加到视图层次结构中的方法在我的视图控制器中:

And here is how I add it to the view hierarchy in my view controller:

func addCircleView() {
    let diceRoll = CGFloat(Int(arc4random_uniform(7))*50)
    var circleWidth = CGFloat(200)
    var circleHeight = circleWidth
    // Create a new CircleView
    var circleView = CircleView(frame: CGRectMake(diceRoll, 0, circleWidth, circleHeight))

    view.addSubview(circleView)
}

是否有办法在1秒内对圆的绘制进行动画处理?

Is there a way to animate the drawing of the circle over 1 second?

例如,在动画过程的一部分,它看起来像这张图中的蓝线:

Example, part way through the animation it would look something like the blue line in this image:

< img src = https://i.stack.imgur.com/FP4Hum.png alt =局部动画>

推荐答案

最简单的方法是利用核心动画的力量为您完成大部分工作。为此,我们必须将您的圆图绘制代码从您的 drawRect 函数移动到 CAShapeLayer 。然后,我们可以使用 CABasicAnimation CAShapeLayer strokeEnd 属性来自 0.0 1.0 strokeEnd 是这里魔术的重要组成部分;来自文档:

The easiest way to do this is to use the power of core animation to do most of the work for you. To do that, we'll have to move your circle drawing code from your drawRect function to a CAShapeLayer. Then, we can use a CABasicAnimation to animate CAShapeLayer's strokeEnd property from 0.0 to 1.0. strokeEnd is a big part of the magic here; from the docs:


与strokeStart属性结合使用,该属性定义了描边路径的
子区域。此属性中的值指示
沿行程的相对点,在该路径上完成笔划,而
strokeStart属性定义起点。值0.0
表示路径的开始,而值1.0表示
路径的结束。中间的值沿路径长度
线性解释。

Combined with the strokeStart property, this property defines the subregion of the path to stroke. The value in this property indicates the relative point along the path at which to finish stroking while the strokeStart property defines the starting point. A value of 0.0 represents the beginning of the path while a value of 1.0 represents the end of the path. Values in between are interpreted linearly along the path length.

如果我们设置 strokeEnd 0.0 ,它不会画任何东西。如果我们将其设置为 1.0 ,它将画一个完整的圆圈。如果将其设置为 0.5 ,它将画一个半圆。等等。

If we set strokeEnd to 0.0, it won't draw anything. If we set it to 1.0, it'll draw a full circle. If we set it to 0.5, it'll draw a half circle. etc.

因此,首先在 CircleView中创建 CAShapeLayer code>的 init 函数并将该层添加到视图的子层中(也请确保删除 drawRect 函数,因为该图层现在将绘制圆):

So, to start, lets create a CAShapeLayer in your CircleView's init function and add that layer to the view's sublayers (also be sure to remove the drawRect function since the layer will be drawing the circle now):

let circleLayer: CAShapeLayer!

override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = UIColor.clearColor()

    // Use UIBezierPath as an easy way to create the CGPath for the layer.
    // The path should be the entire circle.
    let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0), radius: (frame.size.width - 10)/2, startAngle: 0.0, endAngle: CGFloat(Double.pi * 2.0), clockwise: true)

    // Setup the CAShapeLayer with the path, colors, and line width
    circleLayer = CAShapeLayer()
    circleLayer.path = circlePath.CGPath
    circleLayer.fillColor = UIColor.clearColor().CGColor
    circleLayer.strokeColor = UIColor.redColor().CGColor
    circleLayer.lineWidth = 5.0;

    // Don't draw the circle initially
    circleLayer.strokeEnd = 0.0

    // Add the circleLayer to the view's layer's sublayers
    layer.addSublayer(circleLayer)
}

注意:我们将 circleLayer.strokeEnd = 0.0 设置为不会立即绘制圆圈。

Note: We're setting circleLayer.strokeEnd = 0.0 so that the circle isn't drawn right away.

现在,让我们添加一个可以调用以触发圆形动画的函数:

Now, lets add a function that we can call to trigger the circle animation:

func animateCircle(duration: NSTimeInterval) {
    // We want to animate the strokeEnd property of the circleLayer
    let animation = CABasicAnimation(keyPath: "strokeEnd")

    // Set the animation duration appropriately
    animation.duration = duration

    // Animate from 0 (no circle) to 1 (full circle)
    animation.fromValue = 0
    animation.toValue = 1

    // Do a linear animation (i.e. the speed of the animation stays the same)
    animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)

    // Set the circleLayer's strokeEnd property to 1.0 now so that it's the
    // right value when the animation ends.
    circleLayer.strokeEnd = 1.0

    // Do the actual animation
    circleLayer.addAnimation(animation, forKey: "animateCircle")
}

然后,我们要做的就是更改您的 addCircleView 函数,以便当您将 CircleView 添加到其 superview 时,它会触发动画:

Then, all we need to do is change your addCircleView function so that it triggers the animation when you add the CircleView to its superview:

func addCircleView() {
    let diceRoll = CGFloat(Int(arc4random_uniform(7))*50)
     var circleWidth = CGFloat(200)
     var circleHeight = circleWidth

        // Create a new CircleView
     var circleView = CircleView(frame: CGRectMake(diceRoll, 0, circleWidth, circleHeight))

     view.addSubview(circleView)

     // Animate the drawing of the circle over the course of 1 second
     circleView.animateCircle(1.0)
}

所有内容应如下所示:

注意:它不会像这样重复,它会在动画后保持完整的圆圈。

Note: It won't repeat like that, it'll stay a full circle after it animates.

这篇关于画圆的动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆