使用 ScrollViewer 从中心原点缩放图像在 UWP 中不起作用

Scaling image from center orgin using ScrollViewer is not working in UWP

我正在使用滚动查看器缩放设置为 Grid.When 背景的图像,我正在使用 scrollViewer.ChangeView(horizo​​ntalOffset,verticalOffset, zoomFactor) 图像从左上角开始缩放,而不是从中心开始 position.When 每次单击按钮时将缩放级别增加为 0.1。

在此处查找示例:Sample

XAML:

        <UserControl  Grid.Row="2">
        <ScrollViewer x:Name="scrollViewer" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"  VerticalScrollMode="Enabled" HorizontalScrollMode="Enabled"  ZoomMode="Enabled"  >

            <Grid x:Name="ImageGrid" VerticalAlignment="Center" HorizontalAlignment="Center" Width="1260" Height="350" >
                <Image x:Name="MyImage" Width="1260" Height="210" Source="Assets\EditedImage.jpg" RenderTransformOrigin="0.5, 0.5" />
            </Grid>

        </ScrollViewer>
    </UserControl>

C#:

    float count = 1;
    private void Btn_Click(object sender, RoutedEventArgs e)
    {
        count += 0.1f;
        var width = this.scrollViewer.ExtentWidth / 2;
        var height = this.scrollViewer.ExtentHeight  / 2;

        scrollViewer.ChangeView(width, height, count);
    }

您必须计算相对于可滚动区域的偏移量。

XAML

<StackPanel>
  <Button Click="ZoomIn_OnButtonClick" Content="Increase Zoom"/>
  <ScrollViewer x:Name="ScrollViewer" 
                HorizontalScrollBarVisibility="Visible" 
                HorizontalContentAlignment="Center" 
                VerticalContentAlignment="Center">
    <Image Stretch="Uniform" Source="Assets\golden_eaglew.jpg" />
  </ScrollViewer>
</StackPanel>

解决方案使用ScrollViewer.ChangeView

由于应用缩放后滚动查看器的范围发生变化,并且应用缩放在应用滚动偏移后,您必须将滚动推迟到中心利用 ScrollViewer.ViewChanged 事件。这是因为可滚动区域受范围大小的影响(例如 ScrollableWidth = ExtentWidth - ViewportWidth)。

public MainPage()
{
  this.InitializeComponent(); 

  this.ScrollViewer.ViewChanged += ScrollToCenterOnScrollViewerChanged;
}

private void ScrollToCenterOnScrollViewerChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
  if (e.IsIntermediate)
  {
    return;
  }

  var scrollViewer = sender as ScrollViewer;
  scrollViewer.ChangeView(
    scrollViewer.ScrollableWidth / 2, 
    scrollViewer.ScrollableHeight / 2, 
    null);
}

private void ZoomIn_OnButtonClick(object sender, RoutedEventArgs e) 
  => this.ScrollViewer.ChangeView(null, null, this.ScrollViewer.ZoomFactor + 0.1f);

备选方案一:使用ScrollViewer.ZoomToFactor

请注意,此 API 是 marked as deprecated,不保证在未来的框架版本中可用。

private void ZoomIn_OnButtonClick(object sender, RoutedEventArgs e)
{   
  this.ScrollViewer.ZoomToFactor(this.ScrollViewer.ZoomFactor + 0.1f);
  this.ScrollViewer.ScrollToHorizontalOffset(this.ScrollViewer.ScrollableWidth / 2);
  this.ScrollViewer.ScrollToVerticalOffset(this.ScrollViewer.ScrollableHeight / 2);
}

替代解决方案 2:实施自定义 ZoomToFactor 方法

private void ZoomToFactor(double zoomFactor, ScrollViewer scrollViewer)
{
  if (!(scrollViewer?.Content is FrameworkElement zoomTarget))
  {
    return;
  }

  // Apply the zoom to the scroll content
  zoomTarget.Width = zoomTarget.ActualWidth * zoomFactor;
  zoomTarget.Height = zoomTarget.ActualHeight * zoomFactor;

  // Scroll the zoomed scroll content to center
  var scaledScrollableWidth = scrollViewer.ExtentWidth * zoomFactor - scrollViewer.ViewportWidth);
  var scaledScrollableHeight = scrollViewer.ExtentHeight * zoomFactor - scrollViewer.ViewportHeight;
  double horizontalScrollCenterOffset = scaledScrollableWidth / 2;
  double verticalScrollCenterOffset = scaledScrollableHeight / 2;

  scrollViewer.ScrollToHorizontalOffset(horizontalScrollCenterOffset);
  scrollViewer.ScrollToVerticalOffset(verticalScrollCenterOffset);
}

// Usage example
private void ZoomIn_OnButtonClick(object sender, RoutedEventArgs e)
{   
  ZoomToFactor(1.1, this.ScrollViewer);
}