具有比例变换的 Grid 的 ScrollViewer

Posted

技术标签:

【中文标题】具有比例变换的 Grid 的 ScrollViewer【英文标题】:ScrollViewer with Grid which has scale transform 【发布时间】:2014-10-03 19:09:09 【问题描述】:

所以我有一个 Grid>Canvas>Image 放在滚动查看器中。

我已将 RenderTransform> ScaleTransform 放入 Grid 并在其上使用鼠标滚轮事件对其进行缩放。

当我使用它时,它会放大和缩小,但滚动查看器保持它的初始设置,在我看来,当我缩放时实际宽度和高度没有改变(我不想改变)。

我想要的想法是缩放滚动查看器范围,以及将缩放宽度和缩放高度绑定到的网格相同的百分比。

我在 MSDN 中查看 ScrollViewer 类,但找不到保存滚动查看器范围的位置。我正在查看 ExtentHeight 和 ExtentWidth、ScrollableHeight 和 ScrollableWidth,但我有点在黑暗中摸索。

如何以编程方式获取 scrollViewer 水平和垂直条的像素/数值范围?我怎样才能改变它们?我想在网格的鼠标滚轮事件上这样做。

ViewportWidth、ExtentWidth、ScrollableWidth、Width 之间的实际区别是什么?

XAML:

<ScrollViewer Grid.Row="0" Grid.Column="1" Name="sourcePicScroll" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" Height="Auto" Width="Auto">
        <Grid Name="sourceGrid" Background="Gray" MouseWheel="sourceGrid_MouseWheel">
            <Grid.RenderTransform>
                <ScaleTransform x:Name="sourceGridScaleTransform"/>
            </Grid.RenderTransform>
           <Canvas Name="sourceCanvas" Width="0" Height="0" Background="White" MouseMove="sourceCanvas_MouseMove" PreviewMouseLeftButtonDown="sourceCanvas_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="sourceCanvas_PreviewMouseLeftButtonUp" HorizontalAlignment="Left" VerticalAlignment="Top" MouseWheel="sourceCanvas_MouseWheel">
                <Canvas.RenderTransform>
                    <ScaleTransform x:Name="sourceScaleTransform"/>
                </Canvas.RenderTransform>
                <Image Name="sourcePic" HorizontalAlignment="Left" VerticalAlignment="Top" Panel.ZIndex="1" Stretch="None"></Image>
                <Rectangle Name="sourceSelectionBox" Visibility="Collapsed" Stroke="Black" StrokeThickness="1" Panel.ZIndex="50"/>
                <Ellipse Name="sourceSelectionEllipse" Visibility="Collapsed" Stroke="Black" StrokeThickness="1" Panel.ZIndex="51"/>
            </Canvas>
        </Grid>
    </ScrollViewer>

C#代码:

double ScaleRate = 1.1;
        if (e.Delta > 0)
        
            sourceGridScaleTransform.ScaleX *= ScaleRate;
            sourceGridScaleTransform.ScaleY *= ScaleRate;
        
        else
        
            sourceGridScaleTransform.ScaleX /= ScaleRate;
            sourceGridScaleTransform.ScaleY /= ScaleRate;
        

【问题讨论】:

【参考方案1】:

两个问题

    渲染转换仅适用于不影响布局的渲染,因此滚动查看器不会反映相同 画布没有大小,默认为 0,因此应用变换不会影响画布大小,除非在画布上指定了大小。

由于您没有在子级上使用任何画布属性,除非需要,否则您可以安全地删除它们。

所以你可以试试这个示例

<ScrollViewer Grid.Row="0"
              Grid.Column="1"
              Name="sourcePicScroll"
              VerticalScrollBarVisibility="Visible"
              HorizontalScrollBarVisibility="Visible"
              Height="Auto"
              Width="Auto">
    <Grid Name="sourceGrid"
          HorizontalAlignment="Left"
          VerticalAlignment="Top"
          Background="Gray"
          MouseWheel="sourceGrid_MouseWheel">
        <Grid.LayoutTransform>
            <ScaleTransform x:Name="sourceGridScaleTransform" />
        </Grid.LayoutTransform>
        <Image Name="sourcePic"
               HorizontalAlignment="Left"
               VerticalAlignment="Top"
               Panel.ZIndex="1"
               Source="pr.png"
               Stretch="None"></Image>
        <Rectangle Name="sourceSelectionBox"
                   Visibility="Collapsed"
                   Stroke="Black"
                   StrokeThickness="1"
                   Panel.ZIndex="50" />
        <Ellipse Name="sourceSelectionEllipse"
                 Visibility="Collapsed"
                 Stroke="Black"
                 StrokeThickness="1"
                 Panel.ZIndex="51" />
    </Grid>
</ScrollViewer>

变化是

RenderTransform 到 LayoutTransform

将 Horizo​​ntalAlignment="Left" & VerticalAlignment="Top" 添加到网格

移除了内部画布

试试看这是不是你要找的,注意鼠标滚轮只在内部网格上起作用。

如果您需要滚动在全滚动查看器上工作,这里是一个修改后的示例

<Grid>
    <ScrollViewer Grid.Row="0"
                  Grid.Column="1"
                  Name="sourcePicScroll"
                  VerticalScrollBarVisibility="Visible"
                  HorizontalScrollBarVisibility="Visible"
                  Height="Auto"
                  Width="Auto">
        <Grid Name="sourceGrid"
              HorizontalAlignment="Left"
              VerticalAlignment="Top"
              Background="Gray">
            <Grid.LayoutTransform>
                <ScaleTransform x:Name="sourceGridScaleTransform" />
            </Grid.LayoutTransform>
            <Image Name="sourcePic"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   Panel.ZIndex="1"
                   Source="pr.png"
                   Stretch="None"></Image>
            <Rectangle Name="sourceSelectionBox"
                       Visibility="Collapsed"
                       Stroke="Black"
                       StrokeThickness="1"
                       Panel.ZIndex="50" />
            <Ellipse Name="sourceSelectionEllipse"
                     Visibility="Collapsed"
                     Stroke="Black"
                     StrokeThickness="1"
                     Panel.ZIndex="51" />

        </Grid>
    </ScrollViewer>
    <Grid MouseWheel="sourceGrid_MouseWheel"
          Background="Transparent"></Grid>
</Grid>

【讨论】:

使用 LayoutTransform 而不是 ScaleTransform。之后一切都很顺利。谢谢你的详细回答。 添加到您提到的内容的一个很好的参考是 MSDN 转换页面:msdn.microsoft.com/en-us/library/ms750596%28v=vs.110%29.aspx

以上是关于具有比例变换的 Grid 的 ScrollViewer的主要内容,如果未能解决你的问题,请参考以下文章

如何计算偏移量以绘制到画布中应用了比例变换的最近像素?

ScrollView:如何处理大量内容?

2D射影几何和变换

如何在 React Native 中使 ScrollView 组件大小与屏幕大小成比例?

变换比例:缩小比例的问题

计算机图像处理之形状变换