根据鼠标在wpf中的位置缩放图像

Zoom on image according to mouse position in wpf

我在放大 canvas 中的图像时遇到了一些问题。我正在考虑使用 matrixtransform 但它不起作用。它returns我是一个我不明白的例外!这是 XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Button Click="Button_Click"/>

    <ScrollViewer Grid.Row="2"
                  Name="scroll"
                  HorizontalScrollBarVisibility="Auto" 
                  VerticalScrollBarVisibility="Auto">

        <Canvas Name="Container"
                ClipToBounds="True"
                MouseWheel="Container_MouseWheel"
               >

            <Image  Name="ImageSource"
                >
                <Image.LayoutTransform>
                    <MatrixTransform/>
                </Image.LayoutTransform>
            </Image>
        </Canvas>
    </ScrollViewer>
</Grid>

背后的代码:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Bitmap Bmp = new Bitmap(@"C:\Desktop\image1.bmp");
    ImageSource.Source = CreateBitmapSourceFromGdiBitmap(Bmp);
    Container.Width = Bmp.Width;
    Container.Height = Bmp.Height;
}

private void Container_MouseWheel(object sender, MouseWheelEventArgs e)
{
    var element = sender as UIElement;
    var position = e.GetPosition(element);
    var transform = element.RenderTransform as MatrixTransform;
    var matrix = transform.Matrix;
    var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); // choose appropriate scaling factor

    matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);
    transform.Matrix = matrix;
}

如果有人能给我提示就好了,谢谢!

替换

transform.Matrix = matrix;

element.RenderTransform = new MatrixTransform( matrix );

并且有效 ;)

不知道你解决了没有。但是这里的 Xaml 代码可以让你很好地缩放。它可以工作,您可以使用 ScrollVider 的滚动条来平移图像。

<ScrollViewer x:Name="vbxImageViewBox" 
              CanContentScroll="False" 
              HorizontalScrollBarVisibility="Auto"
              VerticalScrollBarVisibility="Auto">

    <Grid x:Name="grdItcMain" Margin="5">
         <Grid.LayoutTransform>
            <TransformGroup>
                <ScaleTransform 
                    ScaleX="{Binding Path=ScaleFactor, 
                             ElementName=this, 
                             Mode=OneWay}" 
                    ScaleY="{Binding Path=ScaleFactor, 
                             ElementName=this, 
                             Mode=OneWay}" />
            </TransformGroup>
        </Grid.LayoutTransform>
        <Rectangle Fill="DeepSkyBlue" Stretch="Fill" />
        <Image MouseWheel="Image_MouseWheel"
            Source="{Binding PreviewSource,
                     ElementName=this,
                     Mode=OneWay}"
            Stretch="Fill" />
    </Grid>
</ScrollViewer>

private const double _smallChange = 0.1;
private double _scaleFactor;
public double ScaleFactor 
{ 
    get 
    { 
        return _scaleFactor; 
    } 
    set 
    { 
        _scaleFactor = value; 
        OnPropertyChanged("ScaleFactor"); 
    } 
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
     double scaleX = (grdItcMain.ActualWidth - 20) / 1920;
     double scaleY = (grdItcMain.ActualHeight - 20) / 1080;
     double dScale = Math.Min(scaleX, scaleY);
     ScaleFactor = dScale; //size to fit initially
}

private void Image_MouseWheel(object sender, MouseWheelEventArgs e)
{
    if (e.Delta > 0)
    {
        if ((ScaleFactor + _smallChange) > 25.0)
        {
            return;
        }

        ScaleFactor += _smallChange;

        vbxImageViewBox.LineRight();
        vbxImageViewBox.LineRight();
        vbxImageViewBox.LineRight();
        vbxImageViewBox.LineRight();
        vbxImageViewBox.LineRight();

        vbxImageViewBox.LineDown();
        vbxImageViewBox.LineDown();
        vbxImageViewBox.LineDown();
        vbxImageViewBox.LineDown();
        vbxImageViewBox.LineDown();
        vbxImageViewBox.LineDown();
    }
    else
    {
        if ((ScaleFactor - _smallChange) < 0.001)
        {
            return;
        }
        ScaleFactor -= _smallChange;

        vbxImageViewBox.LineLeft();
        vbxImageViewBox.LineLeft();
        vbxImageViewBox.LineLeft();
        vbxImageViewBox.LineLeft();
        vbxImageViewBox.LineLeft();

        vbxImageViewBox.LineUp();
        vbxImageViewBox.LineUp();
        vbxImageViewBox.LineUp();
        vbxImageViewBox.LineUp();
        vbxImageViewBox.LineUp();
        vbxImageViewBox.LineUp();
        }
    }

这不是一个完美的解决方案,但它有效且易于实施。

道格

任何其他寻找解决方案的人都应该尝试 Wiesław Šoltés 创建的优秀解决方案 here。只需粘贴答案中显示的代码即可。