Created By: Debasis Das (29-May-2017)
In this post we will see how CAReplicatorLayer works and create a couple of sample code to play around with CAReplicatorLayer
CAReplicatorLayer is essentially a layer that creates a specified number of copies of its sublayers, each copy potentially having geometric, temporal, and color transformations applied to it.
We can use a CAReplicatorLayer object to build complex layouts based on a single source layer that is replicated with transformation rules that can affect the position, rotation color, and time.
In this post we will create the below samples
To begin with we have added a root CALayer to our view and have set the background color of the root layer to black
import Cocoa class ViewController: NSViewController { let rootLayer = CALayer() override func viewDidLoad() { super.viewDidLoad() rootLayer.frame = self.view.frame rootLayer.backgroundColor = NSColor.black.cgColor self.view.layer = rootLayer self.view.wantsLayer = true //replicatorLayerSampleOne() //replicatorLayerSampleTwo() //replicatorLayerSampleThree() //progressIndicatorSampleOne() //progressIndicatorSampleTwo() //progressIndicatorSampleThree() } //Individual Functions to demonstrate the CAReplicatorLayer }
Simple CAReplicatorLayer example
This creates a square of size 50 * 50 and replicates that 5 times and each instance has a color offset.
Each of the instance is added to the replicator layer at a horizontal distance of 10
func replicatorLayerSampleOne(){ let replicatorLayer = CAReplicatorLayer() let coloredSquare = CALayer() coloredSquare.backgroundColor = NSColor.white.cgColor coloredSquare.frame = CGRect(x: 10, y: 10, width: 50, height: 50) let instanceCount = 5 replicatorLayer.instanceCount = instanceCount replicatorLayer.instanceTransform = CATransform3DMakeTranslation(60, 0, 0) replicatorLayer.instanceGreenOffset = -0.2 replicatorLayer.addSublayer(coloredSquare) rootLayer.addSublayer(replicatorLayer) }
Nesting replicator Layers in X and Y Axis
func replicatorLayerSampleTwo(){ let replicatorLayer = CAReplicatorLayer() let rowLayer = CAReplicatorLayer() replicatorLayer.instanceCount = 4 rowLayer.instanceCount = 5 let coloredSquare = CALayer() coloredSquare.backgroundColor = NSColor.white.cgColor coloredSquare.frame = CGRect(x: 10, y: 10, width: 50, height: 50) rowLayer.instanceTransform = CATransform3DMakeTranslation(60, 0, 0) rowLayer.addSublayer(coloredSquare) rowLayer.instanceGreenOffset = -0.2 replicatorLayer.instanceTransform = CATransform3DMakeTranslation(0, 60, 0) replicatorLayer.instanceRedOffset = -0.2 replicatorLayer.addSublayer(rowLayer) rootLayer.addSublayer(replicatorLayer) }
Nesting replicator Layers in X, Y and Z axis
func replicatorLayerSampleThree(){ let replicatorLayer = CAReplicatorLayer() let rowLayer = CAReplicatorLayer() let zLayer = CAReplicatorLayer() replicatorLayer.instanceCount = 4 rowLayer.instanceCount = 5 zLayer.instanceCount = 5 let coloredSquare = CALayer() coloredSquare.backgroundColor = NSColor.white.cgColor coloredSquare.frame = CGRect(x: 10, y: 10, width: 50, height: 50) zLayer.instanceTransform = CATransform3DMakeTranslation(10, 5, -20) zLayer.instanceBlueOffset = -0.2 zLayer.instanceRedOffset = -0.1 zLayer.addSublayer(coloredSquare) rowLayer.instanceTransform = CATransform3DMakeTranslation(90, 0, 0) rowLayer.addSublayer(zLayer) rowLayer.instanceGreenOffset = -0.2 replicatorLayer.instanceTransform = CATransform3DMakeTranslation(0, 90, 0) replicatorLayer.instanceRedOffset = -0.2 replicatorLayer.addSublayer(rowLayer) rootLayer.addSublayer(replicatorLayer) }
Progress Indicator using CAReplicatorLayer – opacity animation
func progressIndicatorSampleOne(){ let replicatorLayer = CAReplicatorLayer() replicatorLayer.frame = CGRect(x: 20, y: 20, width: 200, height: 200) replicatorLayer.borderColor = NSColor.white.cgColor replicatorLayer.cornerRadius = 5.0 replicatorLayer.borderWidth = 1.0 let circle = CALayer() circle.frame = CGRect(origin: CGPoint.zero, size: CGSize(width: 20, height: 20)) circle.backgroundColor = NSColor.blue.cgColor circle.cornerRadius = 10 circle.position = CGPoint(x: 20, y: 100) replicatorLayer.addSublayer(circle) let fadeOut = CABasicAnimation(keyPath: "opacity") fadeOut.fromValue = 1 fadeOut.toValue = 0 fadeOut.duration = 1 fadeOut.repeatCount = Float.greatestFiniteMagnitude circle.add(fadeOut, forKey: nil) let instanceCount = 20 replicatorLayer.instanceCount = instanceCount replicatorLayer.instanceDelay = fadeOut.duration / CFTimeInterval(instanceCount) let angle = -CGFloat.pi * 2 / CGFloat(instanceCount) replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1) rootLayer.addSublayer(replicatorLayer) }
Progress Indicator using CAReplicatorLayer – scale animation
func progressIndicatorSampleTwo(){ let replicatorLayer = CAReplicatorLayer() replicatorLayer.frame = CGRect(x: 20, y: 20, width: 200, height: 200) replicatorLayer.borderColor = NSColor.white.cgColor replicatorLayer.cornerRadius = 5.0 replicatorLayer.borderWidth = 1.0 let circle = CALayer() circle.frame = CGRect(origin: CGPoint.zero, size: CGSize(width: 20, height: 20)) circle.backgroundColor = NSColor.blue.cgColor circle.cornerRadius = 10 circle.position = CGPoint(x: 20, y: 100) replicatorLayer.addSublayer(circle) let shrinkAnimation = CABasicAnimation(keyPath: "transform.scale") shrinkAnimation.fromValue = 1 shrinkAnimation.toValue = 0.1 shrinkAnimation.duration = 1 shrinkAnimation.repeatCount = Float.greatestFiniteMagnitude circle.add(shrinkAnimation, forKey: nil) let instanceCount = 20 replicatorLayer.instanceCount = instanceCount replicatorLayer.instanceDelay = shrinkAnimation.duration / CFTimeInterval(instanceCount) let angle = -CGFloat.pi * 2 / CGFloat(instanceCount) replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1) rootLayer.addSublayer(replicatorLayer) }
Progress Indicator using CAReplicatorLayer – opacity and scale animation
func progressIndicatorSampleThree(){ let replicatorLayer = CAReplicatorLayer() replicatorLayer.frame = CGRect(x: 20, y: 20, width: 200, height: 200) replicatorLayer.borderColor = NSColor.white.cgColor replicatorLayer.cornerRadius = 5.0 replicatorLayer.borderWidth = 1.0 let circle = CALayer() circle.bounds = CGRect(x: 0, y: 0, width: 30, height: 8) circle.backgroundColor = NSColor.blue.cgColor circle.cornerRadius = 2 circle.position = CGPoint(x: 20, y: 100) replicatorLayer.addSublayer(circle) let fadeOut = CABasicAnimation(keyPath: "opacity") fadeOut.fromValue = 1 fadeOut.toValue = 0 fadeOut.duration = 1 fadeOut.repeatCount = Float.greatestFiniteMagnitude circle.add(fadeOut, forKey: nil) let shrinkAnimation = CABasicAnimation(keyPath: "transform.scale") shrinkAnimation.fromValue = 1 shrinkAnimation.toValue = 0.1 shrinkAnimation.duration = 1 shrinkAnimation.repeatCount = Float.greatestFiniteMagnitude circle.add(fadeOut, forKey: nil) circle.add(shrinkAnimation, forKey: nil) let instanceCount = 20 replicatorLayer.instanceCount = instanceCount replicatorLayer.instanceDelay = 1 / CFTimeInterval(instanceCount) let angle = -CGFloat.pi * 2 / CGFloat(instanceCount) replicatorLayer.instanceTransform = CATransform3DMakeRotation(angle, 0, 0, 1) rootLayer.addSublayer(replicatorLayer) }
You can download the source code from here CAReplicatorLayerSampleCode
[…] code: http://www.knowstack.com/swift-careplicatorlayer-sample-code/ […]