【问题标题】:XAML/WPF zoom to a specific area on a canvasXAML/WPF 缩放到画布上的特定区域
【发布时间】:2013-06-17 10:37:38
【问题描述】:

所以我有一个带有 2 列网格的 WPF 窗口。在第一列中,我有一个要渲染 SVG 图像的画布。此画布被重新调整为与图像相同的大小(因此没有进行转换),并且假设图像比屏幕小很多,因此不需要滚动查看器 - 我会将其称为左侧画布。

在第二列中,我有另一个位于 Viewbox 内的画布,同样的 SVG 也被渲染到这个画布上,并且假定 SVG 图像大小大于 Viewbox 的固定大小。 Viewbox 会重新调整画布的大小以适合其中的大小 - 尽管似乎没有对画布应用任何变换,也没有改变其宽度或高度,但这里还有一些其他的魔法 - 但很好,它可以工作。

这个想法是用户可以在左侧画布上绘制一个矩形,这将代表一个缩放区域,然后右侧画布将放大,以便该矩形适合包含画布的 Viewbox - 我的意思是不适合裁剪或拉伸/挤压任何缩放区域,因此如果它是纵向 Viewbox 中的横向缩放区域,则缩放区域的侧面将与 Viewbox 的侧面相交,在顶部和底部留出空间,这很好。

尽管这将是直截了当的,因为没有对任何一个画布应用任何变换,并且它们都具有相同的宽度和高度(尽管 Viewbox 中的一些魔法正在使右边的画布变小)。这就是我目前的做法:

找到中心点:

centreX = Canvas.GetLeft(zoomAreaRect) + (zoomAreaRect.Width / 2);
centreY = Canvas.GetTop(zoomAreaRect) + (zoomAreaRect.Height / 2);

查找秤量:

double scale;

if(zoomAreaRect.Width > zoomAreaRect.Height)
{
    scale = RightCanvas.Width / zoomAreaRect.Width;
}
else
{
    scale = RightCanvas.Height / zoomAreaRect.Height;
}

然后使用 centerX 和 centerY 作为变换中心的缩放变换,并在变换上同时缩放 scaleX 和 scaleY。

现在这显然行不通,因为我需要在计算比例量时以某种方式考虑 Viewbox 的大小,我只是不知道该怎么做。有人可以帮忙吗?

更新:

我已经废弃了 Viewbox,因为这会使事情变得复杂。所以右画布也只是正常大小,但包含在具有固定宽度和高度的边框内。目的是放大缩放区域,直到它适合边框。

这是右侧的 XAML:

<Border Name="ContainingBorder" 
              Grid.Column="1"
              MaxWidth="295"
              MaxHeight="487"
              Height="487">
    <Border.Clip>
        <RectangleGeometry Rect="0.5, 0.5, 295, 487"/>
    </Border.Clip>

    <Canvas Name="RightCanvas"/>
</Border>

我设法放大了正确的数量,只是没有放大到正确的中心。我只是使用纵横比作为似乎有效的比例量:

double ratioX = ContainingBorder.AcctualWidth / zoomAreaRect.Width;
double ratioY = ContainingBorder.AcctualHeight / zoomAreaRect.Height;

double scale = ratioX < ratioY ? ratioX : ratioY;

有什么方法可以计算出中心 x 和 y 吗?上述 centerX 和 centerY 计算似乎无法正常工作。

【问题讨论】:

    标签: c# wpf xaml drawing 2d


    【解决方案1】:

    我不确定我是否完全理解您的问题。也许粘贴 xaml 代码会有所帮助。

    您可能可以使用画布的“边距”属性:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <!--clip to bounds for hide parts of the canvas-->
        <Viewbox ClipToBounds="True">
            <!--set margin negatively to zoom out of the viewbox size-->
            <Canvas Margin="0,0,-100,-100" Width="200" Background="Red" Height="200">
                <Rectangle Width="100" Height="100" Fill="Gray"/>
            </Canvas>
        </Viewbox>
    </Grid>
    

    【讨论】:

    • Viewbox 可以是 300wx700h,Canvas 可以是 600x600(但适合 Viewbox),用户可以在 200,300 处绘制一个 100wx150h 的矩形。然后我想缩放画布,使其放大矩形,直到矩形适合 Viewbox,同时保持 100x150 矩形的纵横比。
    【解决方案2】:

    也许你可以用视觉画笔解决你的问题:

    <Window x:Class="ZoomViewBoxTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="700">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>       
        <Viewbox Width="700" Height="300">
            <Canvas x:Name="LeftCanvas" Width="600" Background="Red" Height="600">
                <!--drawing Rectangle simulates your zoom area-->
                <Rectangle x:Name="DrawingRectange" Width="100" Height="150" Fill="Green" Canvas.Left="200" Canvas.Top="300"></Rectangle>
                <Rectangle Width="200" Height="200" Fill="Gray" Canvas.Left="250" Canvas.Top="350"/>
            </Canvas>
        </Viewbox>
        <Viewbox Grid.Column="1">
            <Rectangle Width="{Binding ElementName=DrawingRectange,Path=Width}" Height="{Binding ElementName=DrawingRectange,Path=Height}">
                <Rectangle.Fill>
                    <VisualBrush Visual="{Binding ElementName=LeftCanvas}" Stretch="None" >
                        <VisualBrush.Viewbox>
                            <!-- X = DrawingRectangle.X / LeftCanvas.Width 
                                 Y = DrawingRectangle.X / LeftCanvas.Height
                                 Width = DrawingRectangle.Width / LeftCanvas.Width
                                 Height = DrawingRectangle.Height / LeftCanvas.Height-->
                            <Rect X="0.333" Y="0.5" Width="0.1666" Height="0.25"></Rect>
                        </VisualBrush.Viewbox>
                    </VisualBrush> 
                    </Rectangle.Fill>
            </Rectangle>
        </Viewbox>
    </Grid>
    

    VisualBrush 的 Viewbox 必须绑定到 DrawingRectangle 的实际值(在代码后面或通过转换器)。

    【讨论】:

    • 感谢您的帮助,但我真的希望能够使用变换来实现,以便为放大设置动画。
    猜你喜欢
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    • 1970-01-01
    • 2021-03-09
    • 2013-01-23
    相关资源
    最近更新 更多