2017-08-27 1 views
1

Je veux que l'utilisateur de dessiner un rectangle sur UIImageView j'ai ajouté deux variables pour les premiers une monotouches dernière J'ai ajouté cette fonction: -Dessiner un rectangle sur UIImageView en utilisant Core Graphics

func draw(from: CGPoint, to: CGPoint) { 
    UIGraphicsBeginImageContext(imageView.frame.size) 
    context = UIGraphicsGetCurrentContext() 
    context?.setStrokeColor(UIColor(red: 0, green: 0, blue: 0, alpha: 1.0).cgColor) 
    context?.setLineWidth(5.0) 
    let currentRect = CGRect(x: from.x, 
          y: from.y, 
          width: to.x - from.x, 
          height: to.y - from.y) 
    context?.addRect(currentRect) 
    context?.drawPath(using: .stroke) 
    context?.strokePath() 
    imageView.image?.draw(in: self.imageView.frame) 
    imageView.image = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
} 

ajouter la méthode (touchMoved), il attire de nombreux rectangles

ajouter la méthode (touchEnded) il tire un, mais il ne semble pas lorsque l'utilisateur déplace la touche

screenshot

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
    if let touch = touches.first { 
     firstTouchLocation = touch.location(in: self.view)    
    } 
} 

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
    if let touch = touches.first { 
     lastTouchLocation = touch.location(in: self.view) 
     draw(from: firstTouchLocation, to: lastTouchLocation) 
    } 
} 

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 
    if let touch = touches.first { 
     lastTouchLocation = touch.location(in: self.view) 
     draw(from: firstTouchLocation, to: lastTouchLocation) 
    } 
} 

Je veux que l'utilisateur puisse étendre le rectangle lorsque touchMoved et tirer lorsque le touchEnded.

Répondre

1

Vous remplacez votre image par une nouvelle image composée du précédent image plus un rectangle dessiné dessus. Plutôt que de dessiner l'image à partir de la vue de l'image, dessinez l'image originale.

Sinon, vous pouvez rendre le rectangle comme une couche de forme et simplement mettre à jour que le chemin de la couche de forme:

class ViewController: UIViewController { 

    @IBOutlet weak var imageView: UIImageView! 

    private let shapeLayer: CAShapeLayer = { 
     let _shapeLayer = CAShapeLayer() 
     _shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor 
     _shapeLayer.strokeColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).cgColor 
     _shapeLayer.lineWidth = 3 
     return _shapeLayer 
    }() 

    private var startPoint: CGPoint! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     imageView.layer.addSublayer(shapeLayer) 
    } 

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
     startPoint = touches.first?.location(in: imageView) 
    } 

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { 
     guard let startPoint = startPoint, let touch = touches.first else { return } 

     let point: CGPoint 

     if let predictedTouch = event?.predictedTouches(for: touch)?.last { 
      point = predictedTouch.location(in: imageView) 
     } else { 
      point = touch.location(in: imageView) 
     } 

     updatePath(from: startPoint, to: point) 
    } 

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 
     guard let startPoint = startPoint, let touch = touches.first else { return } 

     let point = touch.location(in: imageView) 

     updatePath(from: startPoint, to: point) 
     imageView.image = imageView.snapshot(afterScreenUpdates: true) 
     shapeLayer.path = nil 
    } 

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { 
     shapeLayer.path = nil 
    } 

    private func updatePath(from startPoint: CGPoint, to point: CGPoint) { 
     let size = CGSize(width: point.x - startPoint.x, height: point.y - startPoint.y) 
     let rect = CGRect(origin: startPoint, size: size) 
     shapeLayer.path = UIBezierPath(rect: rect).cgPath 
    } 

} 

Où:

extension UIView { 
    func snapshot(afterScreenUpdates: Bool = false) -> UIImage { 
     UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0) 
     drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates) 
     let image = UIGraphicsGetImageFromCurrentImageContext()! 
     UIGraphicsEndImageContext() 
     return image 
    } 
} 

C'est non seulement plus simple, mais plus efficace, aussi.

qui donne:

enter image description here

D'ailleurs, je pourrais suggérer d'utiliser des touches de prévision dans touchesMoved. Sur un périphérique (pas le simulateur) qui peut générer une interface utilisateur légèrement plus réactive.

+0

où je peux trouver des informations sur les "touches prédictives" vous savez où je peux trouver un tutoriel ou quelque chose? –

+1

@ReinierMelian - Voir WWDC 2015 [Advanced Touch Input sur iOS] (https://developer.apple.com/videos/play/wwdc2015/233/). Ou juste google "didacticiel PredictTouches" et vous verrez beaucoup de liens. – Rob

+0

Merci beaucoup, mais il dessine un rectangle et quand un nouvel événement touchBegan commence un nouveau rectangle et supprime le précédent. Je veux enregistrer un dessin après que le toucher se termine et commencer un nouveau –