2009-06-23 21 views
11

Necesito poder acercar y alejar un lienzo usando la rueda del mouse. He configurado con éxito los manejadores de rueda del mouse y actualmente estoy usando ScaleTransform para aplicar el zoom; sin embargo, la escala no se hace de una manera "intuitiva".Silverlight 3 - ScaleTransform u otro método para acercar un lienzo?

Estoy tratando de lograr el mismo estilo de "zoom" que se puede ver en MultiScaleImage, Google Maps/Earth o Adobe Acrobat Reader, pero NO con una imagen, con un control. La transición no necesita ser "suave" o animada (a menos que sea un enfoque más fácil), pero la funcionalidad debe ser la misma.

¡Cualquier idea o pensamiento sería muy apreciado y gracias de antemano!

Editar: he conseguido "suave" el zoom utilizando la animación:

<Canvas.Resources> 
      <Storyboard x:Name="ZoomStoryboard"> 
       <DoubleAnimation x:Name="ZoomAnimationX" 
           Storyboard.TargetName="Workspace" 
           Storyboard.TargetProperty="Canvas.RenderTransform.ScaleTransform.ScaleX" 
           Duration="0:0:0.2"/> 
       <DoubleAnimation x:Name="ZoomAnimationY" 
           Storyboard.TargetName="Workspace" 
           Storyboard.TargetProperty="Canvas.RenderTransform.ScaleTransform.ScaleY" 
           Duration="0:0:0.2"/> 
      </Storyboard> 
     </Canvas.Resources> 

con el siguiente código:

_Zoom += (args.Delta/7); 
if (_Zoom < 0.15) 
    _Zoom = 0.15; 
ZoomAnimationX.To = _Zoom; 
ZoomAnimationY.To = _Zoom; 
ZoomStoryboard.Begin(); 
ZoomScale.Text = _Zoom.ToString("0.00") + "x"; 
_PreviousMousePosition = _CurrentMousePosition 

Sin embargo, el problema sigue siendo que surge es el zoom de la esquina superior izquierda, a diferencia de sitios como Google Maps donde el zoom está "alrededor" del mouse.

Respuesta

10

Debe usar un promedio ponderado como el centro del zoom en función de la posición del mouse. En otras palabras, mantenga el último centro de zoom (o, si aún no lo tiene, configúrelo en la posición actual del mouse) y mantenga el número de veces que se calculó el centro de zoom (después del primer zoom, sería 1) . Cada vez que vuelva a calcular el centro del zoom, incremente esa var.

Ejemplo Código Sigue - deltaZoom es cuánto hacemos zoom, centerx y centery son el centro de zoom actual, ZoomSteps es el número de veces que hemos has, y mouseX y mouseY son la posición actual del ratón:

_Zoom += deltaZoom; 
     if (_Zoom <= 0) 
      _Zoom = 0.1; 

     if (deltaZoom >= 0) 
     { 
      if (_ZoomSteps == -1) 
      { 
       _CenterX = 0; 
       _CenterY = 0; 
       _ZoomSteps = 0; 
      } 
      else 
      { 
       _CenterX = (_CenterX * Math.Abs(_ZoomSteps) + mouseX)/(Math.Abs(_ZoomSteps + 1)); 
       _CenterY = (_CenterY * Math.Abs(_ZoomSteps) + mouseY)/(Math.Abs(_ZoomSteps + 1)); 
       _ZoomSteps++; 
      } 
     } 
     else 
     { 
      if (_ZoomSteps == 1) 
      { 
       _CenterX = 0; 
       _CenterY = 0; 
       _ZoomSteps = 0; 
      } 
      else 
      { 
       _CenterX = (_CenterX * Math.Abs(_ZoomSteps) - mouseX)/(Math.Abs(_ZoomSteps - 1)); 
       _CenterY = (_CenterY * Math.Abs(_ZoomSteps) - mouseY)/(Math.Abs(_ZoomSteps - 1)); 
       _ZoomSteps--; 
      } 
     } 

     ZoomAnimationX.To = _Zoom; 
     ZoomAnimationY.To = _Zoom; 
     CenterAnimationX.To = Math.Abs(_CenterX); 
     CenterAnimationY.To = Math.Abs(_CenterY); 
     ZoomStoryboard.Begin(); 

Editado para que pueda bajar el nivel de zoom de 1,0, pero todavía hay algunos problemas (ZoomStep = -1, 0 o 1 a veces causan batidos raros).

+0

Gracias por la fuente :) +1 –

+0

¿Qué es CenterAnimation? – Erix

Cuestiones relacionadas