【问题标题】:Scaling image from center orgin using ScrollViewer is not working in UWP使用 ScrollViewer 从中心原点缩放图像在 UWP 中不起作用
【发布时间】:2020-08-26 21:13:58
【问题描述】:

我正在使用滚动查看器来缩放设置为 Grid.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);
    }

【问题讨论】:

    标签: c# xaml uwp scrollviewer


    【解决方案1】:

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

    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的解决方案

    由于滚动查看器的范围因应用缩放而发生变化,并且在应用滚动偏移后应用缩放,因此您必须通过使用 @ 推迟滚动到中心987654324@ 事件。这是因为可滚动区域受范围大小的影响(例如,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);
    

    替代方案1:使用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);
    }
    

    【讨论】:

    • 感谢您的回答。我已经尝试过这种方法,它正在部分工作。我期待一个准确的中心定位。你能帮我检查一下吗?
    • 对不起,我是 afk。我刚刚更新了解决方案以提供更流畅的体验。
    • 感谢 BionicCode,ZoomToFactor 已被弃用,能否提供基于 ChangeView 的解决方案?
    • 谢谢,我检查了您的解决方案 ZoomToFactor 是否按预期工作。但是,在使用 ChangeView 时,它最初并没有定位在中心。您能为此提供解决方案吗?
    • 我已更新我的答案以提供第三种解决方案。它实现了一个自定义的ZoomToFactor,这样你就可以摆脱对已弃用 API 的依赖。
    猜你喜欢
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-31
    相关资源
    最近更新 更多