2016-07-22 1 views
0

je suis en utilisant ce code à l'échelle ma toile autour d'un point de focalisationcomment l'échelle en utilisant la toile

private class MyScaleDetector 
      extends ScaleGestureDetector.SimpleOnScaleGestureListener { 


     @Override 
     public boolean onScaleBegin(ScaleGestureDetector detector) { 
      float focusx=detector.getFocusX(); 
      float focusy=detector.getFocusY(); 
      return super.onScaleBegin(detector); 

     } 

     @Override 
     public boolean onScale(ScaleGestureDetector detector) { 
      float factor=detector.getScaleFactor(); 

       scale *= factor; 


      scale = Math.max(0.4f, Math.min(scale, 20.0f)); 


      return true; 
     } 
    } 

ce qui est le code que je l'utilise à l'échelle dans la méthode OnDraw

@Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     canvas.scale(scale,scale,focusx,focusy); 
} 

mon problème C'est quand je commence à redimensionner autour du point de mise au point (200, 200) par exemple, au début, il commence à aller là, mais que, tout en augmentant l'échelle, il commence à s'éloigner du point. Mon problème est donc comment je redimensionne vers un point spécifique de sorte que ce point devient le centre de la fenêtre lors de la mise à l'échelle.

Je pense que je devrais utiliser canvas.translate() avec lui mais je ne sais pas combien je devrais déplacer la position x et y du canevas pendant la mise à l'échelle.

Edit: l'image ci-dessous résume ce que je suis en train de dire

image

Répondre

0

Il y a plusieurs choses à garder à l'esprit ici:

  1. Le ScaleDetector ne détecte que des événements d'échelle; cela sonne bien mais ne suffit pas à lui seul pour gérer le pincement/zoom en 2D (par exemple dans une image).
  2. Le 'foyer' retourné par le détecteur est le point médian entre les deux pointeurs (doigts); cela est moins utile puisque l'hypothèse naturelle lorsque vous commencez à mettre à l'échelle est que le pixel de l'image sous votre doigt restera sous votre doigt lorsque vous zoomez. Les gens bougent souvent les doigts à des vitesses différentes (ou délibérément garder un doigt immobile), ce qui invalide l'utilisation du point médian.
  3. Vous (probablement) souhaitez gérer la rotation aussi.

L'approche générale que je l'ai utilisé dans le passé est:

  • manuellement détecter premier et deuxième événements tactiles; enregistrer la coordonnée des deux pointeurs lorsque l'événement tactile du second pointeur se produit. Ces points doivent logiquement suivre les pointeurs à partir de maintenant.
  • lorsqu'un événement de mouvement se produit qui continue d'avoir deux pointeurs vers le bas, déterminer la traduction, l'échelle et la rotation comme suit (ie deux rotation doigts, zoom, ou faites glisser.):
    • l'échelle est basée sur la la distance entre les nouveaux points par rapport aux points d'origine (enregistré au début)
    • la rotation est basée sur la différence de l'angle entre les deux premiers points et l'angle entre les points les plus récents
    • la traduction est basée arbitrairement sur l'un des points (généralement le premier) - il suffit de traduire en fonction des pixels entre le point d'origine et le dernier point
    • ces valeurs peuvent être calculées et stockées lors de l'événement de mouvement, puis utilisé dans onDraw() Méthode

Notez que dans onDraw():

  • Il est important d'effectuer la traduction d'abord puisque vous travaillez sur des pixels d'écran pour les deux points de référence.
  • vous pouvez alors tourner & échelle dans l'ordre puisque l'échelle est toujours égale dans le X & Y direction

Modifier pour répondre à la demande plus spécifique:

Si tout ce que vous avez vraiment besoin de faire est tout simplement l'échelle autour d'un point spécifique redéfinie p (px, py) d'un montant s, et de garder p visible, vous pouvez effectuer les opérations suivantes:

canvas.translate(px, py); 
canvas.scale(s,s); 
canvas.translate(-px*s, py*s); 

Cela devrait conserver p dans la même position de pixel que celle dans laquelle il se trouvait avant la mise à l'échelle. Celui-ci souffrira de tous les problèmes évoqués ci-dessus ainsi que des risques de dérive dus à des événements d'échelle successifs autour d'un focus mobile (basé sur votre code original). Tu ferais mieux de faire ce que j'ai décrit plus haut.

+0

thx pour les détails mais vous n'avez pas mentionné comment mettre à l'échelle un point spécifique qui pose problème, je sais déjà combien d'échelle et cela fonctionne bien, je l'ai testé pour mettre à l'échelle le milieu de l'écran et ça marche très bien mais si je balance autour d'un autre point ça commence là au début de la mise à l'échelle mais ça commence à partir du point, comme tu peux le voir je dois trouver un moyen pour que je puisse faire ce point le centre de la fenêtre pendant la mise à l'échelle – hm9

+0

Vous mettez à l'échelle un point spécifique exactement comme vous l'avez fait. Pour s'assurer que ce point reste visible, c'est un peu plus de travail, voir ma réponse mise à jour – RabidMutant