Supporting SwiftUI with Core Graphics

Nov 22 2022 Swift 5.5, iOS 15, Xcode 13

Part 1: Supporting SwiftUI with Core Graphics

6. Shading with Pencil

Episode complete

Play next episode

Next
Save for later
About this episode
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 5. Drawing with Pencil Next episode: 7. Create a Thumbnail

This video Shading with Pencil was last updated on Nov 22 2022

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

You can unlock the rest of this video course, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.

Azimuth & Altitude

As well as detecting force and giving us coalesced touches, Pencil is able to give us the tilt in three dimensions. Using this tilt information, we can shade instead of just draw.

Assets

When we shade, instead of drawing a stroke, we’re going to draw a image that looks like a pencil shading.

CanvasView.swift

In CanvasView, right under the color property, add a shading color property that sets up the pencil texture as a UImage with the correct color.

var shadingColor: UIColor = .black {
  didSet {
    let image = UIImage(named: "pencilTexture")!
  }
}
let tintedImage = UIGraphicsImageRenderer(size: image.size).image { _ in
  color.set()
  image.draw(at: .zero)
}
shadingColor = UIColor(patternImage: tintedImage)
var color: UIColor = .black {
  didSet {
    shadingColor = color
  }
}
shadingColor.setStroke()
private let tiltThreshold: CGFloat = .pi / 6
if touch.altitudeAngle < tiltThreshold {
  shadingColor.setStroke()
} else {
  if touch.force > 0 {
    lineWidth = touch.force * forceSensitivity
  }
  color.setStroke()
}
private func lineWidthForShading(touch: UITouch) -> CGFloat {
  
}
let maxLineWidth: CGFloat = 60
let minAltitudeAngle: CGFloat = 0.25
let maxAltitudeAngle = tiltThreshold
let altitudeAngle = max(minAltitudeAngle, touch.altitudeAngle)
let normalizedAltitude = (altitudeAngle - minAltitudeAngle) / (maxAltitudeAngle - minAltitudeAngle)
return max(maxLineWidth * (1 - normalizedAltitude), minLineWidth)
🟩var lineWidth: CGFloat

if touch.altitudeAngle < tiltThreshold {
  🟩lineWidth = lineWidthForShading(touch: touch)
  ...
} else {
  🟩lineWidth = defaultLineWidth
  ...
}
let minForce: CGFloat = 0
let maxForce: CGFloat = 4
let normalizedAlpha = (touch.force - minForce) / (maxForce - minForce)
context.setAlpha(normalizedAlpha)