Pregunta

Necesito poder acercar y alejar un lienzo con la rueda del mouse. He configurado correctamente los controladores de la rueda del mouse y actualmente estoy usando ScaleTransform para aplicar el zoom; sin embargo, el escalado no se realiza de forma intuitiva camino.

Estoy tratando de lograr el mismo estilo de "acercamiento" como 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 animado (a menos que sea un enfoque más fácil), pero la funcionalidad debe ser la misma.

Cualquier idea o idea sería muy apreciada y gracias de antemano

Editar: he logrado "suavizar" el zoom usando 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, sigue surgiendo el problema de que se está alejando de la esquina superior izquierda, en lugar de sitios como Google Maps donde el zoom está "alrededor". el ratón.

¿Fue útil?

Solución

Debe usar un promedio ponderado como 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 tiene uno, simplemente configúrelo en la posición actual del mouse) y mantenga la cantidad de veces que se calculó el centro de zoom (después del primer zoom, eso sería 1) . Cada vez que recalcule el centro del zoom, incremente esa var.

Sigue el código de ejemplo: deltaZoom es cuánto está haciendo zoom, centerX y centerY son el centro de zoom actual, ZoomSteps es la cantidad de veces que hemos hecho zoom, y mouseX y mouseY son la posición actual del mouse:

_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 caer por debajo del nivel de zoom 1.0 pero todavía hay algunos problemas (ZoomStep = -1, 0 o 1 a veces causan sacudidas extrañas).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top