Swift-animate CAshapeLayer stroke color
Updated to Swift 5.
Found out the solution. Enjoy. After you create the CAShapeLayer of course :
let animcolor = CABasicAnimation(keyPath: "strokeColor")
animcolor.fromValue = UIColor.green.cgColor
animcolor.toValue = UIColor.orange.cgColor
animcolor.duration = 1.0
animcolor.repeatCount = 0
animcolor.autoreverses = true
myLayer.add(animcolor, forKey: "strokeColor")
Swift- animate CAshapeLayer stroke color
Found out the solution. Enjoy. After you create the CAShapeLayer of course :
let animcolor = CABasicAnimation(keyPath: "strokeColor")
animcolor.fromValue = UIColor.greenColor().CGColor
animcolor.toValue = UIColor.orangeColor().CGColor
animcolor.duration = 1.0;
animcolor.repeatCount = 0;
animcolor.autoreverses = true
circleLayer.addAnimation(animcolor, forKey: "strokeColor")
CAShapeLayer stroke issue
edit/update:
It would be easier to multiply the line width by 2 and add a mask to your shape:
class Triangle: NSView {
let shapeLayer = CAShapeLayer()
var lineWidth: CGFloat
var strokeColor: NSColor = .clear
var fillColor: NSColor = .clear
init(size: CGSize, lineWidth: CGFloat = 10, strokeColor: NSColor = .white, fillColor: NSColor = .black) {
self.lineWidth = lineWidth*2
self.strokeColor = strokeColor
self.fillColor = fillColor
super.init(frame: .init(origin: .zero, size: size))
wantsLayer = true
let path = NSBezierPath()
path.move(to: .zero)
path.line(to: .init(x: size.width/2 , y: size.height))
path.line(to: .init(x: size.width, y: .zero))
path.close()
let mask = CAShapeLayer()
mask.path = path.cgPath
shapeLayer.mask = mask
shapeLayer.path = path.cgPath
shapeLayer.lineWidth = self.lineWidth
shapeLayer.strokeColor = strokeColor.cgColor
shapeLayer.fillColor = fillColor.cgColor
// layer?.borderWidth = 1
// layer?.borderColor = NSColor.red.cgColor
layer?.addSublayer(shapeLayer)
}
convenience init(width: CGFloat, height: CGFloat, lineWidth: CGFloat = 10, strokeColor: NSColor = .white, fillColor: NSColor = .black) {
self.init(size: .init(width: width, height: height), lineWidth: lineWidth, strokeColor: strokeColor, fillColor: fillColor)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension NSBezierPath {
var cgPath: CGPath {
let path = CGMutablePath()
var points: [CGPoint] = .init(repeating: .zero, count: 3)
for i in 0..<elementCount {
switch element(at: i, associatedPoints: &points) {
case .moveTo: path.move(to: points[0])
case .lineTo: path.addLine(to: points[0])
case .curveTo: path.addCurve(to: points[2], control1: points[0], control2: points[1])
case .closePath: path.closeSubpath()
@unknown default: fatalError()
}
}
return path
}
}
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
let triangle = Triangle(width: 200, height: 200, lineWidth: 1)
view.addSubview(triangle)
}
}
How to set CAShapeLayer 's strokeColor in swift
Here is the code snippet:
let path = UIBezierPath()
path.move(to: CGPoint.zero)
path.addLine(to: CGPoint(x: 50, y: 50))
let view = UIView(frame: CGRect(x: 100, y: 100, width: 50, height: 50))
view.backgroundColor = UIColor.green
let diagonal = CAShapeLayer()
diagonal.frame = view.bounds
diagonal.path = path.cgPath
diagonal.strokeColor = UIColor.orange.cgColor
diagonal.lineWidth = 15
diagonal.backgroundColor = UIColor.blue.cgColor
// view.layer.mask = mask
view.layer.addSublayer(diagonal)
self.view.addSubview(view)
This results in:
Animating CAShapeLayer's strokeColor with CABasicAnimation
The code below works great for me. What is the lineWidth of your shapeLayer stroke path? Could that be the issue?
- (void)viewDidLoad
{
[super viewDidLoad];
UIBezierPath * circle = [UIBezierPath bezierPathWithOvalInRect:self.view.bounds];
CAShapeLayer * shapeLayer = [CAShapeLayer layer];
shapeLayer.path = circle.CGPath;
shapeLayer.strokeColor =[UIColor blueColor].CGColor;
[shapeLayer setLineWidth:15.0];
[self.view.layer addSublayer:shapeLayer];
CABasicAnimation *strokeAnim = [CABasicAnimation animationWithKeyPath:@"strokeColor"];
strokeAnim.fromValue = (id) [UIColor redColor].CGColor;
strokeAnim.toValue = (id) [UIColor greenColor].CGColor;
strokeAnim.duration = 3.0;
strokeAnim.repeatCount = 0;
strokeAnim.autoreverses = YES;
[shapeLayer addAnimation:strokeAnim forKey:@"animateStrokeColor"];
}
Let me know if it works for you...
How to animate CAShapeLayer path and fillColor
To animate path
//setup the CAShapeLayer
myShapeLayer.strokeColor = [[UIColor blueColor] CGColor];
myShapeLayer.lineWidth = 5;
myShapeLayer.fillColor = [[UIColor yellowColor] CGColor];
//Display it!
[self.view.layer addSublayer:myShapeLayer];
//Animate path
CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnimation.duration = 1.5f;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
pathAnimation.repeatCount = 10;
pathAnimation.autoreverses = YES;
[myShapeLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
//Animate colorFill
CABasicAnimation *fillColorAnimation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
fillColorAnimation.duration = 1.5f;
fillColorAnimation.fromValue = (id)[[UIColor clearColor] CGColor];
fillColorAnimation.toValue = (id)[[UIColor yellowColor] CGColor];
fillColorAnimation.repeatCount = 10;
fillColorAnimation.autoreverses = YES;
[myShapeLayer addAnimation:fillColorAnimation forKey:@"fillColor"];
I hope this helps :)
2021 Update
Swift
myShapeLayer.strokeColor = UIColor.blue.cgColor
myShapeLayer.lineWidth = 5
myShapeLayer.fillColor = UIColor.yellow.cgColor
//Display it!
view.layer.addSublayer(myShapeLayer)
//Animate path
let pathAnimation = CABasicAnimation(keyPath: "strokeEnd")
pathAnimation.duration = 1.5
pathAnimation.fromValue = NSNumber(value: 0.0)
pathAnimation.toValue = NSNumber(value: 1.0)
pathAnimation.repeatCount = 10
pathAnimation.autoreverses = true
myShapeLayer.add(pathAnimation, forKey: "strokeEnd")
//Animate colorFill
let fillColorAnimation = CABasicAnimation(keyPath: "fillColor")
fillColorAnimation.duration = 1.5
fillColorAnimation.fromValue = UIColor.clear.cgColor
fillColorAnimation.toValue = UIColor.yellow.cgColor
fillColorAnimation.repeatCount = 10
fillColorAnimation.autoreverses = true
myShapeLayer.add(fillColorAnimation, forKey: "fillColor")
the strokeColor of CAShapeLayer not work
You are adding your shape layer as a mask layer. That allows the brightness of the mask layer's pixels to determine the opacity of the layer it's masking. It sounds like that's not what you want.
Instead, add your shape layer as a sublayer of your view's layer. Change
self.layer.mask = shapeLayer;
to
[self.layer addSublayer: shapeLayer];
That will cause your shape layer to drawn on top of your view's layer.
Related Topics
Cannot Assign Value of Type 'Menuview' to Type 'some View'
Firebase Authentication: Linking Multiple Accounts in Swift
In Swift Can You Trap "Fatal Error Unexpectedly Found Nil While Unwrapping an Optional Value"
How to Get Alphabetic Tableview Sections from an Object
How to Put a View with Loadmore Button in UItableview After The Cell
How to Use Protocols for Stucts to Emulate Classes Inheritance
Create Tab Bar Controller and Navigation Controller
Implementing a Custom Viewmodifier Where Output Is Conditional on Concrete View Type (Swiftui)
Streaming .M3U8 Using Mpmovieplayercontroller Does Not Work
Prefix(_ Maxlength:) Is Type-Erased When Used with a Struct That Conforms to Lazysequenceprotocol
Write Data to Firebase in The Background After Retrieving Steps with Healthkit's Background Delivery
Swiftui Navigationview Starting Inside Itself
Validatemenuitem or Menuwillopen Not Called for Nsmenu
Swift Nstimer Dynamically Changing Interval
How to Make an Ellipse/Circular UIimage with Transparent Background