开发者

How to animate image zoom change in WPF?

开发者 https://www.devze.com 2023-04-04 23:45 出处:网络
I am building an image viewer. I have created a functionality that when the user moves the slider, it changes the ZoomLevel property value. This subsequently zooms the image based on the value provi

I am building an image viewer.

I have created a functionality that when the user moves the slider, it changes the ZoomLevel property value. This subsequently zooms the image based on the value provided by the ZoomLevel property.

<Image 
    Name="image"
    Source="Sample1.jpg"
    Opacity="1" 
    VerticalAlignment="Center"
    HorizontalAlignment="Center"
    Stretch="None"
    RenderTransformOrigin="0.5,0.5" 
    RenderOptions.BitmapScalingMode="HighQuality">
    <Image.RenderTransform>
        <TransformGroup>
            <ScaleTransform 
   开发者_高级运维             ScaleX="{Binding Path=ZoomLevel}" 
                ScaleY="{Binding Path=ZoomLevel}" />
            <TranslateTransform />
        </TransformGroup>
    </Image.RenderTransform>
</Image>

I wish to be able to animate the zooming with a DoubleAnimation. Animation is supposed to start from the current zoom level and then get to the zoom specified in the bound ZoomLevel property. It would be great if someone could provide some help in XAML. Thanks!

Mouse wheel code:

private void border_MouseWheel(object sender, MouseWheelEventArgs e)
{
    int delta;

    delta = e.Delta;
    zoom(delta);
}

private void zoom(int delta)
{
    double zoomIncrement;

    //Different zoom levels at different zoom stages
    if (ZoomLevel > 2)
    {
        zoomIncrement = Math.Sign(delta) * 0.2;
    }
    else if (ZoomLevel >= 1 && ZoomLevel <= 2)
    {
        zoomIncrement = Math.Sign(delta) * 0.1;
    }
    else
    {
        zoomIncrement = Math.Sign(delta) * 0.06;
    }

    //Rounding zoom level to boundary values
    //Zooming is allowed from 10% to 600%
    if (ZoomLevel + zoomIncrement > 6)
    {
        ZoomLevel = 6;
    }
    else if (ZoomLevel + zoomIncrement < 0.1)
    {
        ZoomLevel = 0.1;
    }
    else
    {
        ZoomLevel += zoomIncrement;
    }
}


It is a little messy but try this.

namespace Zoom
{

    public partial class Window1
    {   
        public double ZoomLevel { get; set; }
        public double SlideLevel { get; set; }

        public Window1()
        {
            InitializeComponent();

            ZoomLevel = 1.0;
            SlideLevel = 1.0;
            image.MouseWheel += image_MouseWheel;

        }

        private void image_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            double zoom = e.Delta > 0 ? .1 : -.1;
            slider.Value = (SlideLevel + zoom);
        }

        private void ZoomImage(double zoom)
        {
            Storyboard storyboardh = new Storyboard();
            Storyboard storyboardv = new Storyboard();

            ScaleTransform scale = new ScaleTransform(ZoomLevel, ZoomLevel);
            image.RenderTransformOrigin = new Point(0.5, 0.5);
            image.RenderTransform = scale;

            double startNum = ZoomLevel;
            double endNum = (ZoomLevel += zoom);

            if (endNum > 1.0)
            {
                endNum = 1.0;
                ZoomLevel = 1.0;
            }

            DoubleAnimation growAnimation = new DoubleAnimation();
            growAnimation.Duration = TimeSpan.FromMilliseconds(300);
            growAnimation.From = startNum;
            growAnimation.To = endNum;
            storyboardh.Children.Add(growAnimation);
            storyboardv.Children.Add(growAnimation);

            Storyboard.SetTargetProperty(growAnimation, new PropertyPath("RenderTransform.ScaleX"));
            Storyboard.SetTarget(growAnimation, image);
            storyboardh.Begin();

            Storyboard.SetTargetProperty(growAnimation, new PropertyPath("RenderTransform.ScaleY"));
            Storyboard.SetTarget(growAnimation, image);
            storyboardv.Begin();
        }

        private void slider_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
        {
            double zoomChange = (SlideLevel - slider.Value) * -1;
            SlideLevel = SlideLevel + zoomChange;

            ZoomImage(zoomChange);
        }
    }
}

I found this other stack question to be quite helpful

Here is the current setup of XAML that I have as well.

    <Border MaxWidth="500"
        MaxHeight="500"
        Height="500"
        Width="500"
        Name="border">
    <Image
        Name="image"
        Source="picture1.png"
        Opacity="1"
        VerticalAlignment="Center"
        HorizontalAlignment="Center"
        Stretch="Fill"
        RenderTransformOrigin="0.5,0.5"
        RenderOptions.BitmapScalingMode="HighQuality"
        ClipToBounds="True">
    </Image>
    </Border>
    <Slider
        HorizontalAlignment="Left"
        Margin="44,70,0,148"
        Name="slider"
        Width="24"
        Value="1.0"
        Minimum="0"
        Maximum="1.0"
        LargeChange="0.1"
        Orientation="Vertical"
        FlowDirection="LeftToRight"
        TickFrequency="0.1"
        IsSnapToTickEnabled="False"
        ValueChanged="slider_ValueChanged" />


Have you tried using a ViewBox? You can bind the final width to any value you need, here's a quick sample:

<Window.Resources>
    <Storyboard x:Key="ZoomIn">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="ImageContainer">
            <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="400"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>

<Grid x:Name="LayoutRoot">
    <Viewbox x:Name="ImageContainer" Width="200">
        <Image Source="http://images.wikia.com/lossimpson/es/images/a/a7/Homer_Simpson2.png"/>
    </Viewbox>
</Grid>
0

精彩评论

暂无评论...
验证码 换一张
取 消