언젠가 전자칠판 프로젝트를 준비하며 만들었던 그림판 앱입니다
( 프로젝트는 엎어졌다고 합니다 ... )
Canvas는 마우스 드래그 이벤트마다 선을 그리는 메서드를 호출합니다
class Canvas: NSView {
var lastPoint = CGPoint.zero;
var mode : CGBlendMode = .normal;
@IBOutlet var imageView: NSImageView!;
@IBAction func onClickEraseButton(_ sender: Any){
self.mode = .clear
}
@IBAction func onClickDrawButton(_ sender: Any){
self.mode = .normal
}
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
}
override func mouseDown(with event: NSEvent) {
lastPoint = CGPoint(x: event.locationInWindow.x, y: event.locationInWindow.y)
}
override func mouseDragged(with event: NSEvent) {
let currentPoint = CGPoint(x: event.locationInWindow.x, y: event.locationInWindow.y)
self.drawLine( from: self.lastPoint, to: currentPoint)
self.lastPoint = currentPoint
}
}
이 메서드는 직전 이벤트에서 저장된 이미지를 뷰 위에 그린 후, 그 위에 선을 그립니다
그리고, 다시 이 화면을 이미지화하여 저장합니다
extension Canvas {
func drawLine(from: CGPoint, to: CGPoint){
let compression_factor = 1
let options: [NSBitmapImageRep.PropertyKey: Any] = [.compressionFactor: compression_factor]
guard let rep = bitmapImageRepForCachingDisplay(in: self.bounds) else { return }
guard let context = NSGraphicsContext(bitmapImageRep: rep) else { return }
NSGraphicsContext.current = context
self.imageView.image?.draw(in: self.bounds)
let cgContext = context.cgContext
cgContext.move(to: from)
cgContext.addLine(to: to)
cgContext.setLineCap(.round)
cgContext.setLineWidth(5)
cgContext.setStrokeColor(NSColor.red.cgColor)
cgContext.setBlendMode(mode)
cgContext.strokePath()
if let data = rep.representation(using: .png, properties: options) {
imageView.image = NSImage(data: data)!
}
}
}
이렇게 빠르게 선을 그리게 되면,
CPU 사용량이 빠르게 올라가는 것을 확인할 수 있었습니다
NSView의 draw(_ rect:) 메서드를 이용하기로 했습니다