[Résolu] Zoom et masque dans un UIScrollView ou UIView

busterTheobusterTheo Membre
mars 2015 modifié dans API UIKit #1

Bonjour,


le but de l'opération est de pouvoir zoomer sur une image qui se trouve masquée par un masque.


 


J'ai mis deux UIImageViews (imageView pour la photo et myMaskView pour le masque) dans un UIView (myView), et j'ai bien mon image masquée à  l'aide de



myView.maskView = myMaskView

Le problème est que, pour implémenter un zoom avec (minimumZoomScale, maximumZoomScale, scrollViewDidZoom, viewForZoomingInScrollView, etc),  je dois utiliser un UIScrollView, et dans ce cas là , évidemment, l'image ne se déplace pas ou ne se zoome pas dans le masque, mais c'est le tout qui réagit.


 


Ma question est, comment faire un zoom sans UIScrollView ?


Ou, comment faire que le masque ne bouge pas dans un UIScrollView ?


 


Merci d'avance


Réponses

  • AliGatorAliGator Membre, Modérateur
    Implémente la méthode "viewForZoomingInScrollView:" de ton UIScrollViewDelegate.
  • merci Alligator pour ta réponse, mais je l'ai déjà  implémenté. Peut-être dois-je en faire d'avantage ?



    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return imageView
    }
  • Pour mieux comprendre, j'ai mis deux vidéos en ligne.


     


    a.mov est l'image bien masquée :  image et masques sont dans un UIView


    b.mov : tout est dans un UIScrollView avec ses méthodes delegate


    On remarque que ça ne fonctionne qu'après avoir enclenché le zoom arrière - Super bizarre ce truc, non ?


     


    http://www.magnitude-6.net/ge/a.mov


     


    http://www.magnitude-6.net/ge/b.mov


     


    Merci d'avance


  • Désolé, en fait l'effet bizarre a lieu lorsque je garde cette fonction (construction()), (celle qui permet de déplacer l'image dans son masque correctement, dans a.mov - version UIView) , active dans le viewDidLoad.



    func construction() {
    // Le pan
    let panGesture: UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: "monActionPan:")
    panGesture.maximumNumberOfTouches = 1
    panGesture.minimumNumberOfTouches = 1
    imageView.addGestureRecognizer(panGesture)
    imageView.userInteractionEnabled = true
    }

    // PanGestureRecognizer
    func monActionPan(recognizer: UIPanGestureRecognizer) {
    switch(recognizer.state) {
    case .Began:
    self.imageViewOriginX = imageView.frame.origin.x
    self.imageViewOriginY = imageView.frame.origin.y

    self.recognizerBeganX = recognizer.locationInView(myView).x as CGFloat
    self.recognizerBeganY = recognizer.locationInView(myView).y as CGFloat

    case .Changed:
    self.recognizerChangedX = recognizer.locationInView(myView).x as CGFloat
    self.recognizerChangedY = recognizer.locationInView(myView).y as CGFloat

    imageView.frame.origin.x = self.imageViewOriginX + self.recognizerChangedX - self.recognizerBeganX
    imageView.frame.origin.y = self.imageViewOriginY + self.recognizerChangedY - self.recognizerBeganY

    case .Ended:
    self.imageViewOriginX = imageView.frame.origin.x
    default:
    break
    }
    }

    avec évidemment les variables imageViewOriginX, recognizerBeganX, etc, qui sont définies en début de fichier

  • En gros, si je garde cette fonction, cela ne fonctionne qu'après un zoom arrière, et si je la supprime, cela ne fonctionne pas du tout


  • AliGatorAliGator Membre, Modérateur
    Attends ton imageView est deja dans une scrollView (qui peut gérer le zoom pour toi si tu lui demandes) et en + tu rajoutes par dessus un GestureRecognizer a ton imageView ?


    Y'a des trucs qui se marchent sur les platebandes la non ?
  • Ben non, puisque j'ai supprimé la fonction construction et le pan associé. Il n'y a donc plus de GestureRecognizer.


     


    ​Et là , impossible de zoomer sur l'imageView au travers du masque, ou de déplacer l'imageView dans le masque, sans que le masque se déplace...


     


    Donc le soucis, est de pouvoir faire comme dans a.mov (l'image se déplace bien au travers du masque), mais avec la possibilité de zoomer, donc en supprimant la fonction construction et le pan associé, et en rajoutant les méthode delegate du UIScrollView. Mais cela ne fonctionne pas du tout. Le masque se déplace aussi...


  • AliGatorAliGator Membre, Modérateur
    Surcharge le layoutSubviews de ta ScrollView pour replacer ton calque au centre alors.
  • Merci AliGator pour ton concours.


    J'ai cherché à  faire pas mal de trucs avec layoutSubviews, sans réussir, même avec la doc.


     


    En analysant mon problème plus profondément, j'ai trouvé la solution.


    Cela, sans aucun code particulier.


    Il suffisait d'imbriquer mes views différemment, et surtout d'en rajouter une supplémentaire.


    En gros :


    Une UIScrollView qui contient une imageView avec la photo à  glisser et zoomer.


    Une imageView du masque qui doit rester en place.


    Une UIView qui contient ces deux éléments.


    Et le masque appliqué sur cette UIView.


     


    Est-ce que c'est correct, tout ça ?


    En tout cas, j'avais des doutes avant d'essayer cette technique, et je suis très content. Si ça peut servir à  quelqu'un...


     


    ça donne ça.


    http://www.magnitude-6.net/ge/c.mov


     


    Encore merci


  • busterTheobusterTheo Membre
    mars 2015 modifié #11

    Je met le code, si quelqu'un le désire.



    class ViewController: UIViewController, UIScrollViewDelegate {

    var myView: UIView = UIView()
    var myScrollView:UIScrollView = UIScrollView()

    var myImageView = UIImageView()
    var myMaskView = UIImageView()
    var myMaskContourView = UIImageView()

    override func viewDidLoad() {
    super.viewDidLoad()

    // LA VIEW ENGLOBANTE
    myView = UIView(frame: CGRectMake(-200 + UIScreen.mainScreen().bounds.width/2, -200 + UIScreen.mainScreen().bounds.height/2, 400, 400))
    myView.backgroundColor = UIColor.redColor()
    self.view.addSubview(myView)

    // LA SCROLLVIEW QUI CONTIENT LA IMAGEVIEW
    myScrollView.delegate = self
    myScrollView.frame = CGRectMake(10, 10, 380, 380)
    myScrollView.backgroundColor = UIColor.blueColor()
    myView.addSubview(myScrollView)

    // LA IMAGEVIEW DE LA PHOTO
    let myImage = UIImage(named: "moi.jpg")!
    myImageView.image = myImage
    myImageView.contentMode = UIViewContentMode.Center
    myImageView.frame = CGRectMake(0, 0, myImage.size.width, myImage.size.height)
    myScrollView.contentSize = myImage.size
    myImageView.userInteractionEnabled = true
    myScrollView.addSubview(myImageView)

    let scaleWidth = myScrollView.frame.size.width / 800
    let scaleHeight = myScrollView.frame.size.height / 800
    let minScale = min(scaleHeight, scaleWidth)

    myScrollView.minimumZoomScale = 1
    myScrollView.maximumZoomScale = 8
    myScrollView.zoomScale = 2

    // LA IMAGEVIEW DU MASQUE
    myMaskView = UIImageView(frame: CGRectMake(75, 75, 250, 250))
    myMaskView.image = UIImage(named: "twitterMask.png")
    myView.addSubview(myMaskView)

    myView.maskView = myMaskView

    // LA IMAGEVIEW DU CONTOUR MASQUE
    myMaskContourView = UIImageView(frame: CGRectMake(75, 75, 250, 250))
    myMaskContourView.image = UIImage(named: "twitterMaskContour.png")
    myView.addSubview(myMaskContourView)
    }

    func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return myImageView
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    }
    }

  • busterTheobusterTheo Membre
    mars 2015 modifié #12

    Salut Samir,


    je ne savais pas (je suis nouveau) que l'on pouvait dire "j'aime". Cool.


    Tu travailles aussi sur ce genre de trucs ?


  • Ah, AliGator, t'as aimé. ça me va droit au coe“ur  :p


  • samirsamir Membre
    mars 2015 modifié #14

    Salut,


     


    Mon "j'aime" est juste pour te remercie de ton retour sur le sujet :). C'est une bonne attitude de dire que tu as résolu ton problème et d'expliquer comment. 


     


    Après pour ton code je "l'aime pas" trop parce que :


     


    1. Y a trop de constantes magique. ( -200,....).


    2. Pourquoi tu préfixe par "my" les noms de tes variables ?


    3. Tu peux virer la méthode "didRecive..." puisque elle fait rien. 


     


    Sinon bon boulot :)


  • busterTheobusterTheo Membre
    mars 2015 modifié #15

    Ouaaaah,


    grand merci pour tes remarques, c'est exactement les critiques que je recherche.


    Je modifie tout ça tout de suite.


     


    Sans quoi, quelques questions et remarques, si je cela n'est pas trop abuser.


     


    1- Tu m'étonnes, c'est fait à  l'arrache, juste pour aboutir dans mes essais. T'as grave raison


    2- Surement parce que je me suis trop bouffé de tutos d;-) - Tu proposerais quoi, toi, stp ?


    3- Merci pour la méthode "didReeive..."


     


    Et merci pour la bonne attitude, justement, je me posais la question, si c'était pas trop relou pour les lecteurs, d'être envahi par du code. Tu me confortes dans mon action.


     


     


    Désolé, le post est parti deux fois. Oups


     


    Je cherche comment le supprimer.


  • AliGatorAliGator Membre, Modérateur
    mars 2015 modifié #16

    Désolé, le post est parti deux fois. Oups
     
    Je cherche comment le supprimer.

    Je me suis chargé de le supprimer du coup. Normalement il me semble que tu as un bouton/lien "Supprimer" en bas de ton post, au même titre que tu as le bouton "Modifier". Sauf que moi je suis admin et avec les droits que j'ai je vois ce bouton, mais j'ai un doute, je ne sais plus si l'auteur d'un message peut auto-supprimer son propre message peut-etre n'as-tu pas les droits.

    Sinon moi aussi mon "J'aime" c'était surtout pour dire "j'apprécie que tu sois revenu pour poster la solution pour aider d'autres qui pourraient avoir le mm souci que toi", c'est une bonne habitude et ça montre que tu ne viens pas sur le forum juste pour poser des questions, avoir la réponse toute crue et partir sans un mot (oui oui y'en a qui font ça), quand ça va pas on gueule mais quand ça va bien et qu'il y a des gens comme toi qui font de retours et reviennent poster leur solution faut aussi qu'on dise qu'on apprécie :D
  • DrakenDraken Membre
    mars 2015 modifié #17

    Sauf que moi je suis admin et avec les droits que j'ai je vois ce bouton, mais j'ai un doute, je ne sais plus si l'auteur d'un message peut auto-supprimer son propre message peut-etre n'as-tu pas les droits.

    Non, le commun des mortels n'a pas le droit d'effacer ses propres posts. Et c'est bien dommage quand la connexion ADSL se met à  bégayer ..
  • hummm, c'est trop bon de recevoir des compliments et encouragements. C'est mon copain, mon ego qui est content.


    Merci à  vous...


     


    Hey, Samir, une idée pour les noms variables différents de myVariable ?


     


    Merci


  • je confirme, les touristes ne peuvent pas supprimer leurs propres posts


  • Seuls les membres du club très sélect Contrôleurs d'arômes ont le droit de supprimer les posts. Et Dieu le père !

  • Et les Contrôleurs d'arômes le gagne, alors  o:)




  • Hey, Samir, une idée pour les noms variables différents de myVariable ?




     


    Salut,


     


    Les conventions de nomage en Objective C :


     


    On utilise les préfix pour les classes, protocoles, fonctions, constantes et les structures "typedef". 


     


    En Swift : 


    La plupart du code que je lis n'utilise pas de préfix même pour les classes puisqu'il y a la notion d'espace de noms. Donc chaque nom de classe est relié (appartient) au module dans lequel sa classe est définie.  


     


    Donc j'enlèverais les "my" et je garderais par exemple "contourView",....


     


    Pour les constantes magiques, j'utiliserais un xib ou storyboard. 

  •  

    Salut Samir,


    merci pour tes précisions.


     


    Par contre, je ne comprend pas ce que tu veux dire par



     


     


    Pour les constantes magiques, j'utiliserais un xib ou storyboard

    Tu veux dire que je ne dois pas créer de view en code mais dans le storyBoard ?

  • CéroceCéroce Membre, Modérateur

    Samir n'est pas très clair, mais je crois qu'il veut parler de ça:


    http://nshipster.com/ibinspectable-ibdesignable/


     


    (On peut aussi depuis iOS 5 fixer des propriétés dans un xib).


     


    Ceci dit, si tu as créé les vues par le code, c'est tout à  fait valide d'utiliser des constantes dans ton code.


  •  

    Ah merci Céroce,


    ouais, je connaissais IBInspectable et IBDesignable.


    C'est vrai, que dans la grosse appli que je dois faire, seuls les écrans principaux sont fait sous IB, tout le reste sera en code. Pour l'instant, j'expérimente toutes les techniques que je dois mettre en oe“uvre, donc avec un peu de laisser aller, mais au moment de rassembler tout ça, je définirais évidemment des constantes.


    Encore merci.

Connectez-vous ou Inscrivez-vous pour répondre.