Hand drawing animation with NSBezierPath

81 Views Asked by At

I draw a notch stroke on macOS with NSBezierPath. How is it possible to make a "hand-drawing" animation for this path?

Thank you

//
//  NotchOutlineView.swift
//  DynamicLake Pro
//
//  Created by Avior Rokach on 12/13/23.
//

import Foundation
import Cocoa

 class NotchOutlineView: NSView {
       private var shapeLayer: CAShapeLayer!
       var thePath:CGPath?
       var isAnimated = false
open var outlineColor: NSColor = .clear {
      didSet {
        // Redraw the view when the notch radius changes
        self.needsDisplay = true
    }
}

open var notchRadius: CGFloat = 19.0 {
      didSet {
          // Redraw the view when the notch radius changes
          self.needsDisplay = true
      }
  }

override func draw(_ dirtyRect: NSRect) {
    //super.draw(dirtyRect)
    drawOutline()
}

private func drawOutline() {
    let size = self.frame.size
    
    let gap: CGFloat = 0.8
    let notch = NSBezierPath()
    notch.move(to: NSPoint(x: 0.0, y: size.height + 1.0))
    notch.curve(to: NSPoint(x: notchRadius, y: size.height - notchRadius),
                controlPoint1: NSPoint(x: notchRadius - gap, y: size.height),
                controlPoint2: NSPoint(x: notchRadius, y: size.height - gap))
    notch.line(to: NSPoint(x: notchRadius , y: notchRadius))
    notch.curve(to: NSPoint(x: notchRadius * 2.0, y: 1.0),
                controlPoint1: NSPoint(x: notchRadius, y: gap),
                controlPoint2: NSPoint(x: notchRadius + gap, y: 1.0))
    notch.line(to: NSPoint(x: size.width - 2 * notchRadius, y: 1.0))
    notch.curve(to: NSPoint(x: size.width - notchRadius, y: notchRadius),
                controlPoint1: NSPoint(x: size.width - notchRadius - gap, y: 1.0),
                controlPoint2: NSPoint(x: size.width - notchRadius, y: gap))
    notch.line(to: NSPoint(x: size.width - notchRadius, y: size.height - notchRadius))
    notch.curve(to: NSPoint(x: size.width, y: size.height + 1.0),
                controlPoint1: NSPoint(x: size.width - notchRadius, y: size.height - gap),
                controlPoint2: NSPoint(x: size.width - notchRadius + gap, y: size.height))
    notch.close()
    
    
    /*Fill the notch in gradeint
    let gradient = NSGradient(starting: NSColor.red, ending: NSColor.blue)
    gradient?.draw(in: notch, angle: 90.0) */
    // Create a gradient with two colors for the stroke
    
    notch.lineWidth = 1.6
    outlineColor.setStroke()
    notch.stroke()
    thePath = notch.cgPath
    
    // Create a CAShapeLayer for animation
    if shapeLayer == nil {
        shapeLayer = CAShapeLayer()
        shapeLayer.path = notch.cgPath
        shapeLayer.lineWidth = notch.lineWidth
        shapeLayer.strokeColor = NSColor.notchPurple.cgColor
        shapeLayer.fillColor = NSColor.clear.cgColor
        
        // Set shadow properties for outer glow
         shapeLayer.shadowColor = NSColor.white.cgColor // Color of the outer glow
         shapeLayer.shadowOffset = CGSize(width: 0, height: 0) // No offset for a centered glow
         shapeLayer.shadowRadius = 6.0 // Adjust the radius to control the size of the outer glow
        shapeLayer.shadowOpacity = 0.0 // CURRENTLY I DISBALED THE OUTHER GLOW
        
        self.layer?.addSublayer(shapeLayer)
    
    }
    
    animatePathDrawing()
    
}

    func animatePathDrawing() {
    self.alphaValue  = 1.0
    // Set initial state
    shapeLayer.strokeEnd = 0.0
    
    // Create a CABasicAnimation for strokeEnd
    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = 0.0
    animation.toValue = 1.0
    animation.duration = 2.0  // Animation duration in seconds
    animation.timingFunction = CAMediaTimingFunction(name: .linear)
    animation.repeatCount = .infinity
    animation.autoreverses = true
        
    // Add the animation to the shape layer
    shapeLayer.add(animation, forKey: "strokeEndAnimation")
    isAnimated = true
        
    }

    func stopPathDrawing () {
    shapeLayer?.removeAllAnimations()
    self.isAnimated = false
   }
}
0

There are 0 best solutions below