XAML / WPF缩放到画布上的特定区域

时间:2013-06-17 10:37:39

标签: c# wpf xaml drawing 2d

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

在第二列中,我有一个位于Viewbox内的画布,同样的SVG也会渲染到此画布,并假设SVG图像大小大于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;
}

然后使用缩放变换,使用centreX和centreY作为变换的中心,并在变换上缩放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的中心?上述centreX和centreY计算似乎无法正常工作。

2 个答案:

答案 0 :(得分:0)

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

您可以使用画布的“margin”属性:

<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>

答案 1 :(得分:0)

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

<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的实际值(在代码后面或通过转换器)。