Мне нужно нарисовать / нарисовать линию в UIImage, как на картинке выше, я вижу много обучающих каракулей линии в UIView, но не в UIImage.
после того, как пользователь нарисовал изображение, я хочу сохранить его как новое изображение (изображение с линиями). как мне это сделать в Swift?
я просто могу найти линию рисования на UIView не в UIImage для рисования в UIView похож на этот в этом учебнике YouTube http://youtube.com/watch?v=gbFHqHHApC4, я меняю его, чтобы наследовать DrawView на 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()
}
}
Я назначил UIImage в раскадровке для использования настраиваемого класса «DrawView», как и мой код выше, но я не знаю, почему строки не отображаются в моем UIImage
Попробуйте использовать 2 изображения 1. Временное изображение, которое содержит текущий рисунок 2. Основное изображение, которое содержит другие уже созданные изображения
Вы что-нибудь пробовали? Если да, покажите код и то, что не работает.
Нарисуйте линии на imageView и снимите с него новый образ?
да мне нужно что-то подобное @TheTiger
@sarah В чем проблема? Вы уже умеете рисовать линию на виду. UIImageView - это сам вид, поэтому вы также можете рисовать на нем линии, а после этого просто сделайте снимок экрана этого imageView.
@TheTiger Ага, я назначил UIImage в раскадровке для использования настраиваемого класса «DrawView», как мой код выше, но я не знаю, почему строки не отображаются в моем UIImage
кажется, что функция touchesBegan никогда не будет выполняться, когда я использую DrawView Class в моем UIImageView
Вы пробовали ответ ниже?
@TheTiger Ага, я новичок, так что все еще работаю над этим,





Вы можете поместить свой UIImageView в фоновый режим и UIView наверх, а затем захватить UIView как образ и объединить его.
Обратитесь к этому, чтобы захватить UIView: Как захватить UIView в UIImage без потери качества на дисплее Retina
А затем объедините его, используя:
func mergeImages (forgroundImage : UIImage, backgroundImage : UIImage, size : CGSize) -> UIImage {
let bottomImage = backgroundImage
UIGraphicsBeginImageContext(size)
let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
bottomImage.draw(in: areaSize)
let topImage = forgroundImage
topImage.draw(in: areaSize, blendMode: .normal, alpha: 1.0)
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
Это может вам помочь. Ссылка
Как нарисовать изображение в Swift?
Сделайте изображение графическим контекстом. (До iOS 10 это можно было сделать, вызвав UIGraphicsBeginImageContextWithOptions. В iOS 10 есть другой способ, UIGraphicsImageRenderer, но вам не нужно его использовать, если вы не хотите.)
Нарисуйте (то есть скопируйте) изображение в контекст. (У UIImage есть методы draw ... именно для этой цели.)
Нарисуйте линию в контексте. (Для этого есть функции CGContext.)
Извлеките полученное изображение из контекста. (Например, если вы использовали UIGraphicsBeginImageContextWithOptions, вы должны использовать UIGraphicsGetImageFromCurrentImageContext.) Затем закройте контекст.
import UIKit
// https://stackoverflow.com/a/41009006/4488252
class DrawnImageView: UIImageView {
private lazy var path = UIBezierPath()
private lazy var previousTouchPoint = CGPoint.zero
private lazy var shapeLayer = CAShapeLayer()
override func awakeFromNib() {
super.awakeFromNib()
setupView()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func setupView(){
layer.addSublayer(shapeLayer)
shapeLayer.lineWidth = 4
shapeLayer.strokeColor = UIColor.white.cgColor
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
}
}
drawingImageView.screenShotDo not forget to add the solution code here
import UIKit
class ViewController: UIViewController {
fileprivate weak var savedImageView: UIImageView?
fileprivate weak var drawnImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
let drawnImageView = addImageView(image: UIImage(named: "swift")) as DrawnImageView
drawnImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
drawnImageView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height/3).isActive = true
self.drawnImageView = drawnImageView
let button = UIButton()
button.setTitle("Save Image", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
button.topAnchor.constraint(equalTo: drawnImageView.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 = drawnImageView?.screenShot
}
}
Хороший ответ!! Но я сохраняю изображение с помощью UIImageWriteToSavedPhotosAlbum в альбоме, и изображение имеет белые границы, как это исправить?
@Beginnerrrrrr трудно понять, что произошло. Я предлагаю вам задать новый вопрос, где вы поделитесь своим кодом, имитирующим проблему. Потому что я не могу понять, в чем может быть проблема в вашем случае.
Отличный код, но он не поддерживает изменение цвета. Как в данном примере. Если я хочу "S", "W", "I", "F" и "T" с красным, зеленым, желтым, синим и белым соответственно, то я не могу использовать ваш код.
@MrugeshTank вы можете изменить цвет shapeLayer.strokeColor = UIColor.white.cgColor. Итак, поэкспериментируйте с этой строкой, чтобы создать необходимую вам функциональность
Уже пробовал это, но если я установил красный цвет и нарисовал "S", а затем, если я установил зеленый, чтобы нарисовать "W", то "S" также изменит его цвет на зеленый.
Попробуйте использовать 2 изображения.