Sergio
Sergio

Reputation: 82

UIImage Inside Custom Shape and animation

I need to draw a shape like that one: enter image description here And animate the color path when you are scrolling. I have been for 2 hours trying several things but don't reach the final way to overcome that. I have tried creating a custom UIView, create a CShapeLayer and then a UIBezierPath to that layer, and finally adding the subview to a view in the viewdidload, but this does not work. What else can I do to approach that? I will start with the shapes that are the most complex things, as the label will be just aligned to the shape.

----FIRST PART SOLVED, DRAWRECT NOW APPEARS, BUT HOW DO I ANIMATE?----

That's my updated code in my drawRect method.

class CustomOval: UIView {

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)!
}

override func drawRect(rect: CGRect) {

    //SHAPE 2
    let rectanglePath2 = UIBezierPath(roundedRect: CGRectMake(135, 177, 20, 70), cornerRadius: 0)

    let shapeLayer2 = CAShapeLayer()
    shapeLayer2.path = rectanglePath2.CGPath
    shapeLayer2.bounds = CGRect(x: 135, y: 177, width: 20, height: 70)
    shapeLayer2.lineWidth = 5.0

    let label2 = UILabel()
    label2.frame = CGRectMake(150 + rectanglePath2.bounds.width, rectanglePath2.bounds.height + 120, 100, 50)
    label2.text = "Label 2"

    self.addSubview(label2)

    //// Rectangle Drawing
    UIColor.blueColor().setFill()
    rectanglePath2.fill()

    //SHAPE 3
    let rectanglePath3 = UIBezierPath(roundedRect: CGRectMake(135, 237, 20, 70), cornerRadius: 0)

    let shapeLayer3 = CAShapeLayer()
    shapeLayer3.path = rectanglePath3.CGPath
    shapeLayer3.bounds = CGRect(x: 135, y: rectanglePath2.bounds.maxY, width: 20, height: 70)
    shapeLayer3.lineWidth = 5.0

    //// Rectangle Drawing
    UIColor.redColor().setFill()
    rectanglePath3.fill()

    let label3 = UILabel()
    label3.frame = CGRectMake(rectanglePath3.bounds.width + 150, rectanglePath3.bounds.height + 190, 100, 50)
    label3.text = "Label 3"

    self.addSubview(label3)

    //SHAPE 1
    let rectanglePath = UIBezierPath(roundedRect: CGRectMake(104, 24, 80, 155), cornerRadius: 40)

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = rectanglePath.CGPath
    shapeLayer.bounds = CGRect(x: 104, y: 24, width: 80, height: 155)
    shapeLayer.lineWidth = 5.0

    //// Rectangle Drawing
    UIColor.grayColor().setFill()
    rectanglePath.fill()

}

}

-UPDATE ANIMATION-

var shapeLayer = CAShapeLayer()

override init(frame: CGRect) {
    shapeLayer = CAShapeLayer()
    super.init(frame: frame)
    animateShape1()

}

required init(coder aDecoder: NSCoder) {
    shapeLayer = CAShapeLayer()
    super.init(coder: aDecoder)!
    animateShape1()
}

func animateShape1(){

    let animation = CABasicAnimation(keyPath: "fillColor")

    animation.fromValue = UIColor.whiteColor().CGColor
    animation.toValue = UIColor.redColor().CGColor
    animation.duration = 5 //2 sec

    shapeLayer.fillColor = UIColor.redColor().CGColor //color end value
    layer.addAnimation(animation, forKey: "somekey")


}

My main questions now are:

func addImage(){

    let imageSubLayer = CALayer()
    let image = UIImage(named: "paint.png")
    imageSubLayer.contents = image?.CGImage
    imageSubLayer.bounds = (frame: CGRect(x: shapeLayer.bounds.width/2, y:   shapeLayer.bounds.height/2, width: 50, height: 50))
    shapeLayer.addSublayer(imageSubLayer)

}

I have also tried, and the one that has worked is: But i dont want a tiled image. I have also tried without tiled and this does not work

CGContextSaveGState(context)
rectanglePath.addClip()
CGContextScaleCTM(context, 0, (image?.size.height)!)
CGContextDrawTiledImage(context, CGRectMake(20, 20, 50, 50), image!.CGImage)
CGContextRestoreGState(context)

Upvotes: 0

Views: 552

Answers (1)

s0urcer
s0urcer

Reputation: 332

  1. You should never add sublayers inside drawRect method. It would be much better to do this inside init or initWithFrame: method of a view or at least inside viewDidLoad method of view controller.

  2. You need to set bounds of CAShapeLayer otherwise it would be CGRectZero. Don't forget that points of UIBezierPath should be in the coordinate system of CAShapeLayer.

Color animation sample code:

let animation = CABasicAnimation(keyPath: "fillColor")

animation.fromValue = UIColor.whiteColor().CGColor
animation.toValue = UIColor.redColor().CGColor
animation.duration = 2 //2 sec

layer.fillColor = UIColor.redColor().CGColor //color end value
layer.addAnimation(animation, forKey: "somekey")

Upvotes: 1

Related Questions