This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FreedrawingImageViewCG: UIImageView { | |
var currentTouchPosition: CGPoint? | |
override func layoutSubviews() { | |
super.layoutSubviews() | |
isUserInteractionEnabled = true | |
} | |
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FreedrawingView: UIView { | |
// we use a multi-dimensional array to store separate lines, otherwise | |
// all your lines will be connected | |
var lines = [[CGPoint]]() | |
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { | |
// create a new line | |
lines.append([CGPoint]()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func calculateRectBetween(lastPoint: CGPoint, newPoint: CGPoint) -> CGRect { | |
let originX = min(lastPoint.x, newPoint.x) - (lineWidth / 2) | |
let originY = min(lastPoint.y, newPoint.y) - (lineWidth / 2) | |
let maxX = max(lastPoint.x, newPoint.x) + (lineWidth / 2) | |
let maxY = max(lastPoint.y, newPoint.y) + (lineWidth / 2) | |
let width = maxX - originX | |
let height = maxY - originY |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { | |
guard let newTouchPoint = touches.first?.location(in: self) else { return } | |
var lastTouchPoint: CGPoint = .zero | |
if let lastIndex = lines.indices.last { | |
// get reference to last point | |
if let lastPoint = lines[lastIndex].last { lastTouchPoint = lastPoint } | |
// add new point |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var flattenedImage: UIImage? | |
var line = [CGPoint]() { | |
didSet { | |
checkIfTooManyPointsIn(&line) | |
} | |
} | |
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { | |
super.touchesBegan(touches, with: event) | |
flattenImage() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override func draw(_ rect: CGRect) { | |
super.draw(rect) | |
guard let context = UIGraphicsGetCurrentContext() else { return } | |
// draw the flattened image if it exists | |
if let image = flattenedImage { | |
image.draw(in: self.bounds) | |
} | |
context.setStrokeColor(lineColor.cgColor) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { | |
guard let newTouchPoint = touches.first?.location(in: self) else { return } | |
let lastTouchPoint: CGPoint = line.last ?? .zero | |
line.append(newTouchPoint) | |
let rect = calculateRectBetween(lastPoint: lastTouchPoint, newPoint: newTouchPoint) | |
layer.setNeedsDisplay(rect) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
override func draw(_ layer: CALayer, in ctx: CGContext) { | |
// 1 | |
let drawingLayer = self.drawingLayer ?? CAShapeLayer() | |
// 2 | |
drawingLayer.contentsScale = UIScreen.main.scale | |
// 3 | |
let linePath = UIBezierPath() | |
// 4 | |
for (index, point) in line.enumerated() { | |
if index == 0 { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func checkIfTooManyPoints() { | |
let maxPoints = 25 | |
if line.count > maxPoints { | |
updateFlattenedLayer() | |
// we leave two points to ensure no gaps or sharp angles | |
_ = line.removeFirst(maxPoints - 2) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func updateFlattenedLayer() { | |
// 1 | |
guard let drawingLayer = drawingLayer, | |
// 2 | |
let optionalDrawing = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData( | |
NSKeyedArchiver.archivedData(withRootObject: drawingLayer, requiringSecureCoding: false)) | |
as? CAShapeLayer, | |
// 3 | |
let newDrawing = optionalDrawing else { return } | |
// 4 |
OlderNewer