如何在swift中在UIImage上绘制/涂鸦线? [英] how to draw / doodle line on UIImage in swift?
问题描述
我需要在UIImage中绘制/涂鸦一行,如上图所示,我看到很多教程在UIView上涂鸦线但不在UIImage中。
用户在图像上涂鸦后,我想将其保存为新图像(图像有线条) 。我怎么在Swift中做到这一点?
我只能在UIView上找到绘制线而不是在UIImage
中用于绘制UIView就像这样的youtube教程
I need to draw / doodle a line in UIImage like the picture above , I see a lot of tutorials doodle line on the UIView but not in the UIImage.
after the user doodle on the Image, I want to save it as the new image (Image that has lines). how do I do that in Swift?
i just can find draw line on UIView not in the UIImage the for drawing on UIView is like this one in this youtube tutorial http://youtube.com/watch?v=gbFHqHHApC4 , I change it to inherit DrawView to UIImageView
struct Stroke {
let startPoint : CGPoint
let endPoint : CGPoint
let strokeColor : CGColor
}
class DrawView : UIImageView {
var isDrawing = false
var lastPoint : CGPoint!
var strokeColor : CGColor! = UIColor.black.cgColor
var strokes = [Stroke]()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard !isDrawing else { return }
isDrawing = true
guard let touch = touches.first else {return}
let currentPoint = touch.location(in: self)
lastPoint = currentPoint
print(currentPoint)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard isDrawing else { return}
guard let touch = touches.first else {return}
let currentPoint = touch.location(in: self)
let stroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, strokeColor: strokeColor)
strokes.append(stroke)
lastPoint = currentPoint
setNeedsDisplay()
print(currentPoint)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard isDrawing else { return}
isDrawing = false
guard let touch = touches.first else {return}
let currentPoint = touch.location(in: self)
let stroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, strokeColor: strokeColor)
strokes.append(stroke)
setNeedsDisplay()
lastPoint = nil
print(currentPoint)
}
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.setLineWidth(5)
context?.setLineCap(.round)
for stroke in strokes {
context?.beginPath()
context?.move(to: stroke.startPoint)
context?.addLine(to: stroke.endPoint)
context?.setStrokeColor(stroke.strokeColor)
context?.strokePath()
}
}
func erase() {
strokes = []
strokeColor = UIColor.black.cgColor
setNeedsDisplay()
}
}
I have assigned the UIImage in storyboard to use custom class "DrawView" like my code above, but I don't know why the lines doesn't appear on my UIImage
Details
Xcode 9.3, Swift 4.1
Solution
// https://stackoverflow.com/a/41009006/4488252
class DrawingImageView: UIImageView {
var path = UIBezierPath()
var previousTouchPoint = CGPoint.zero
var shapeLayer = CAShapeLayer()
override func awakeFromNib() {
super.awakeFromNib()
setupView()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupView(){
self.layer.addSublayer(shapeLayer)
self.shapeLayer.lineWidth = 4
self.shapeLayer.strokeColor = UIColor.white.cgColor
self.isUserInteractionEnabled = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
if let location = touches.first?.location(in: self){
previousTouchPoint = location
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
if let location = touches.first?.location(in: self){
path.move(to: location)
path.addLine(to: previousTouchPoint)
previousTouchPoint = location
shapeLayer.path = path.cgPath
}
}
}
// https://stackoverflow.com/a/40953026/4488252
extension UIView {
var screenShot: UIImage? {
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
if let context = UIGraphicsGetCurrentContext() {
layer.render(in: context)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenshot
}
return nil
}
}
Usage
- Add DrawingImageView to your root (parent) view (drawing by touch will be enabled automatically)
- To save UIImage use
drawingImageView.screenShot
Full sample
Do not forget to add the solution code here
import UIKit
class ViewController: UIViewController {
fileprivate weak var savedImageView: UIImageView!
fileprivate weak var drawingImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let drawingImageView = addImageView(image: UIImage(named: "swift")) as DrawingImageView
drawingImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
drawingImageView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height/3).isActive = true
self.drawingImageView = drawingImageView
let button = UIButton()
button.setTitle("Save Image", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
button.topAnchor.constraint(equalTo:drawingImageView.bottomAnchor, constant: 60).isActive = true
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
button.heightAnchor.constraint(equalToConstant: 44).isActive = true
button.addTarget(self, action: #selector(saveImageButtonTouchUpInside), for: .touchUpInside)
let savedImageView = addImageView()
savedImageView.topAnchor.constraint(equalTo: button.bottomAnchor, constant: 60).isActive = true
savedImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
self.savedImageView = savedImageView
}
private func addImageView<T: UIImageView>(image: UIImage? = nil) -> T {
let imageView = T(frame: .zero)
imageView.contentMode = .scaleAspectFit
imageView.image = image
view.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
return imageView
}
@objc func saveImageButtonTouchUpInside(sender: UIButton) {
savedImageView.image = drawingImageView.screenShot
}
}
Results
这篇关于如何在swift中在UIImage上绘制/涂鸦线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!