首页 > 解决方案 > 放大鼠标指向的图像部分

问题描述

我有一个带有图像标签的网格,如下所示:

<Grid Height="180" Width="180" Grid.Column="2">
        <Image Height="180" Width="180" Source="{Binding Result}">
            <Image.LayoutTransform>
                <ScaleTransform x:Name="st2" CenterX="90" CenterY="90" ScaleX="1" ScaleY="1" />
            </Image.LayoutTransform>
            <Image.Triggers>
                <EventTrigger RoutedEvent="Image.MouseEnter">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="st2"
                                         Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
                                         To="3.0" Duration="0:0:0" />
                                <DoubleAnimation Storyboard.TargetName="st2"
                                         Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
                                         To="3.0" Duration="0:0:0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="Image.MouseLeave">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="st2"
                                         Storyboard.TargetProperty="(ScaleTransform.ScaleX)"
                                         To="1.0" Duration="0:0:0" />
                                <DoubleAnimation Storyboard.TargetName="st2"
                                         Storyboard.TargetProperty="(ScaleTransform.ScaleY)"
                                         To="1.0" Duration="0:0:0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Image.Triggers>
        </Image>
    </Grid>

我介绍了它在这张图片上的工作原理:

在此处输入图像描述

我将鼠标指向KMM图像的任何地方,它都会放大图像的相同部分。例如,当我将鼠标指向图像底部时,它仍然会放大该图像的左上部分(如下所示):

在此处输入图像描述

如何编辑我的代码以在鼠标指向的任何地方放大我的图像?我可以在我的xaml文件 ( xaml.cs) 后面使用代码。我只希望它工作

标签: c#wpfxaml

解决方案


虽然使用内置的缩放变换使目标图像的缩放更容易,但鼠标位置跟踪并不那么容易。

我建议您使用一个视图框ImageBrush来显示您的缩放图像。您可以设置视图框ImageBrush以显示图像的所需部分。

要使代码可重用,请创建附加属性。例如,像这样一个:

public static class ViewBoxTracking
{
    // Source is an UIElement that will provide the mouse input
    // for calculating of the view box bounds.
    public static readonly DependencyProperty SourceProperty =
        DependencyProperty.RegisterAttached("Source", typeof(UIElement), typeof(ViewBoxTracking), new PropertyMetadata(null, SourceChanged));

    public static void SetSource(TileBrush brush, UIElement value) => brush.SetValue(SourceProperty, value);

    public static UIElement GetSource(TileBrush brush) => (UIElement)brush.GetValue(SourceProperty);

    private const int ZoomFactor = 3;

    private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs ea)
    {
        if (ea.NewValue is UIElement source && d is ImageBrush target)
        {
            // When the mouse cursor exits the source element,
            // reset the view box to the 100% zoom;
            // you can remove or change this logic.
            source.MouseLeave += (s, e) => target.Viewbox = new Rect(0, 0, 1, 1);

            // When the mouse hovers over the source object, update the view box.
            source.MouseMove += (s, e) => SourceMouseMove(target, e.GetPosition(source), source.RenderSize);
        }
    }

    private static void SourceMouseMove(ImageBrush target, Point currentPoint, Size sourceSize)
    {
        // The view box width is based on the zoom factor
        double viewBoxWidth = sourceSize.Width / ZoomFactor;
        double viewBoxHeight = sourceSize.Height / ZoomFactor;

        // Calculate the bounds for the view box - at first, in absolute coordinates.
        double x = Math.Max(0, currentPoint.X - viewBoxWidth / 2);
        double y = Math.Max(0, currentPoint.Y - viewBoxHeight / 2);
        if (x + viewBoxWidth > sourceSize.Width)
        {
            x = sourceSize.Width - viewBoxWidth;
        }

        if (y + viewBoxHeight > sourceSize.Height)
        {
            y = sourceSize.Height - viewBoxHeight;
        }

        // Now, make the coordinates relative.
        x /= sourceSize.Width;
        y /= sourceSize.Height;

        // Set the new view box to the target image brush.
        target.Viewbox = new Rect(x, y, 1d / ZoomFactor, 1d / ZoomFactor);
    }
}

下面是一个如何在 XAML 中使用新附加属性的示例:

<UniformGrid Columns="2">
    <Grid Height="180" Width="180">
        <Grid.Background>
            <ImageBrush ImageSource="{Binding YourImage}" ViewboxUnits="RelativeToBoundingBox" 
                        local:ViewBoxTracking.Source="{Binding ElementName=MainImage}" />
        </Grid.Background>
    </Grid>

    <Image x:Name="MainImage" Height="180" Width="180" Source="{Binding YourImage}" />

</UniformGrid>

local是 XAML 命名空间,表示放置附加属性的命名空间,例如xmlns:local="clr-namespace:YourNamespace".


推荐阅读