How to draw an animated path with multiple colors in ios?

I need to draw something like the following image in an iOS app, except that the arc can contain more colors:

Path to draw

I know how to draw, but I am looking for a way to animate the drawing of a path.

There is a similar question here , except that the circle is not animated. This is another question that explains how to animate the circle, and it works fine in my case, except it doesn't handle multiple colors in the path.

How to do it?

+3


source to share


2 answers


I found a general solution that works really well. Since there is no way to draw a unique different color path, I just draw, without animation, all the different color paths that make up the path I want. After that, I drew a unique backward path that spans all of these paths and applied animation to that path.

For example, in the above example, I draw both arcs with the following code:

class CircleView: UIView {

    let borderWidth: CGFloat = 20

    let startAngle = CGFloat(M_PI)
    let middleAngle = CGFloat(M_PI + M_PI / 2)
    let endAngle = CGFloat(2 * M_PI)
    var primaryColor = UIColor.redColor()
    var secondaryColor = UIColor.blueColor()
    var currentStrokeValue = CGFloat(0)

    override func drawRect(rect: CGRect) {

        var center = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
        var radius = CGFloat(self.frame.width / 2 - borderWidth)

        var path1 = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: middleAngle, clockwise: true)

        var path2 = UIBezierPath(arcCenter: center, radius: radius, startAngle: middleAngle, endAngle: endAngle, clockwise: true)

        path1.lineWidth = borderWidth
        primaryColor.setStroke()
        path1.stroke()
        path2.lineWidth = borderWidth
        path1.stroke()
        secondaryColor.setStroke()
        path2.stroke()
    }
}

      

After that, I get the path path3

and then add it to the layer that will be added to the view:



var path3 = UIBezierPath(arcCenter: center, radius: radius, startAngle: endAngle, endAngle: startAngle, clockwise: true)

      

Note that this path spans the two previous paths in reverse order, since its startAngle is equal to the value endAngle

, its endAngle is equal startAngle

, and the clockwise property is set to.This true

path is the one I'm going to animate.

For example, if I want to show 40% of the entire (imaginary) path (the one made up of different color paths), I will outweigh that to show 60% of my coverage path path3

. The way we can animate path3

can be found in the link given in the question.

+3


source


import UIKit
import QuartzCore
import CoreGraphics

class ViewController: UIViewController,UIGestureRecognizerDelegate {
var btnview : UIButton!
var buttonCenter = CGPoint.zero
var firstlayerpoint = CGPoint.zero
var firstLayer = CAShapeLayer()
var secondLayer = CAShapeLayer()
var thirdLayer = CAShapeLayer()
var initialPosition = CGRect()
let label = UILabel()
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var blueLabel: UILabel!
@IBOutlet weak var greenLabel: UILabel!
@IBOutlet weak var redLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()


        firstLayer = self.createCircleWithBounds(bounds: CGRect(x:0, y:0, width:100,height:100), Position: self.view.center, StrokeColor: UIColor.blue, LineWidth: 20.0)
        firstLayer.strokeStart = 0.00
        firstLayer.strokeEnd = 0.33

        self.view.layer.addSublayer(firstLayer)


        secondLayer = self.createCircleWithBounds(bounds: CGRect(x:0, y:0, width:100,height:100), Position: self.view.center, StrokeColor: UIColor.red, LineWidth: 20.0)
        secondLayer.strokeStart = 0.33
        secondLayer.strokeEnd = 0.66
        self.view.layer.addSublayer(secondLayer)


        thirdLayer = self.createCircleWithBounds(bounds:  CGRect(x:0, y:0, width:100,height:100), Position: self.view.center, StrokeColor: UIColor.green, LineWidth: 20.0)
        thirdLayer.strokeStart = 0.66
        thirdLayer.strokeEnd = 1.00
        self.view.layer.addSublayer(thirdLayer)

    btnview = UIButton(frame: CGRect(x: self.view.center.x - 20 , y: self.view.center.y - 20 , width: 40, height: 40))
    btnview.backgroundColor = UIColor.gray
    btnview.isUserInteractionEnabled = true
    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panButton(panGesture:)))
    // panGesture.minimumNumberOfTouches = 1

    btnview.addGestureRecognizer(panGesture)

    self.view.addSubview(btnview)
    // Do any additional setup after loading the view, typically from a nib.
        nameLabel.isHidden = true
        blueLabel.isHidden = true
        greenLabel.isHidden = true
        redLabel.isHidden = true
}


func panButton(panGesture: UIPanGestureRecognizer) {

    //let translation = panGesture.translation(in: self.btnview)
    panGesture.view!.center =  btnview.center
    panGesture.setTranslation(CGPoint.zero, in: self.view)
    // var point = CGPoint.zero
    //  point = firstLayer.frame.size.center


    if panGesture.state == .began {


        label.isHidden = false
        buttonCenter = btnview.center // store old button center
    }
    else if panGesture.state == .ended || panGesture.state == .failed || panGesture.state == .cancelled {

        print(btnview.frame.origin.x)
        print(greenLabel.frame.origin.x)
        if btnview.frame.origin.x > greenLabel.frame.origin.x
        {
            //    lblflayer.isHidden = false
            //    lblsecondlayer.isHidden = true
            //    lblthirdlayer.isHidden = true
            nameLabel.isHidden = false
            nameLabel.text = "Blue"
            nameLabel.backgroundColor = UIColor.blue

        }
        else if btnview.frame.origin.x > blueLabel.frame.origin.x
        {
            // print(btnview.frame.origin.x)
            //  print(lblsecondlayer.frame.origin.x)
            //     lblsecondlayer.isHidden = false
            //   lblflayer.isHidden = true
            //    lblthirdlayer.isHidden = true
            nameLabel.isHidden = false
            nameLabel.text = "Red"
            nameLabel.backgroundColor = UIColor.red

        }

        else  if btnview.frame.origin.x > redLabel.frame.origin.x
        {
            print(btnview.frame.origin.x)
            print(redLabel.frame.origin.x)
            greenLabel.isHidden = true
            //  lblsecondlayer.isHidden = true
            //  lblthirdlayer.isHidden = false

            nameLabel.isHidden = false
            nameLabel.text = "Green"
            nameLabel.backgroundColor = UIColor.green
        }
        else
        {
            nameLabel.isHidden = true
            // lblflayer.isHidden = true
            // lblsecondlayer.isHidden = true
            //  lblthirdlayer.isHidden = true
        }

        btnview.center = buttonCenter // restore button center
    }
    else
    {
        let location = panGesture.location(in: view) // get pan location
        btnview.center = location // set button to where finger is
    }


}



func createCircleWithBounds(bounds: CGRect, Position position: CGPoint, StrokeColor color: UIColor, LineWidth lineWidth: CGFloat) -> CAShapeLayer {
    //let shapelayer = CAShapeLayer.layer
    let shapelayer = CAShapeLayer()
    shapelayer.strokeColor = color.cgColor
    shapelayer.fillColor = UIColor.clear.cgColor
    shapelayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: bounds.width / 2).cgPath
    shapelayer.bounds = bounds
    shapelayer.position = position
    shapelayer.lineCap = kCALineCapButt
    shapelayer.lineWidth = lineWidth
    return shapelayer
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

      



0


source







All Articles