WPF Scrollviewer 滚动到鼠标位置

标签 wpf image offset scrollviewer

我正在研究一个图像查看器控件,该控件由滚动查看器内的图像组成。
为了缩放,我在图像的 layouttransform 中使用了 scaletransform。
Zoomin 在鼠标点击时发生。如果用户单击图像,我希望鼠标位置的像素位于滚动查看器可视区域的中心。
为了实现这一点,我想修改滚动查看器的偏移量,但我不确定如何计算将像素置于鼠标指针下方的正确偏移量。

Here是关于如何将滚动条保持在其相对位置的描述。这工作正常,但不是我正在寻找的。

你如何正确计算偏移量?

这是我的一些代码:

xml:

<ScrollViewer Margin="5" Name="scrvImagePanel" VerticalAlignment="Stretch" 
                  CanContentScroll="True"
                  DockPanel.Dock="Left" 
                  HorizontalAlignment="Stretch" 
                  HorizontalContentAlignment="Stretch"
                  HorizontalScrollBarVisibility="Auto" 
                  VerticalContentAlignment="Stretch" 
                  VerticalScrollBarVisibility="Auto"
                  Background="{StaticResource {x:Static SystemColors.ControlDarkBrushKey}}"
                  ScrollChanged="OnScrollChanged">
        <Image Name="imgPicture"
               MouseUp="imgMouseUp" 
               Stretch="None"
               HorizontalAlignment="Left" 
               VerticalAlignment="Top" 
               >
            <Image.LayoutTransform>
                <TransformGroup>
                <ScaleTransform x:Name="imgZoomTransform" ScaleX="1" ScaleY="1"></ScaleTransform>
                </TransformGroup>
            </Image.LayoutTransform>                
        </Image>
    </ScrollViewer>

和代码:
private void imgMouseUp(object sender, MouseButtonEventArgs e)
{
   Point absScreenPos = e.GetPosition(imgPicture);

    //calculate the new zoom factor
    this.ZoomFactor = imgZoomTransform.ScaleX;
    if (e.ChangedButton == MouseButton.Right)
    {
      this.ZoomFactor /= 2.0;
    }
    else if (e.ChangedButton == MouseButton.Left)
    {
      this.ZoomFactor *= 2.0;
    }

    //perform the zooming
    this.DoZoom(this.ZoomFactor, absScreenPos.X, absScreenPos.Y);

}

private void DoZoom(double zoom, double posX, double posY)
{
  // update the scale transform
  imgZoomTransform.ScaleX = zoom;
  imgZoomTransform.ScaleY = zoom;

  this.AdjustScroll(new Point(posX, posY));
}


private void AdjustScroll(Point? centerPoint)
{
  if(centerPoint != null)
  {
    var sv = this.scrvImagePanel;

    double offsetX = (centerPoint.Value.X / this.imgPicture.ActualWidth) * sv.ActualWidth;
    double offsetY = (centerPoint.Value.Y / this.imgPicture.ActualHeight) * sv.ActualHeight;

    sv.ScrollToHorizontalOffset(offsetX);
    sv.ScrollToVerticalOffset(offsetY);
  }
}

最佳答案

这个想法很简单,当鼠标按下时,您应该计算它与中心的距离,并将其添加或减去当前偏移量。
考虑这个代码:

bool left = false;
    double scale = 2;
    double ZoomFactor;
    private void imgMouseUp(object sender, MouseButtonEventArgs e)
    {
        Point absScreenPos = e.GetPosition(imgPicture);

        //calculate the new zoom factor
        this.ZoomFactor = imgZoomTransform.ScaleX;
        if (e.ChangedButton == MouseButton.Right)
        {
            left = false;
            this.ZoomFactor /= scale;
        }
        else if (e.ChangedButton == MouseButton.Left)
        {
            left = true;
            this.ZoomFactor *= scale;
        }
        //perform the zooming
        this.DoZoom(this.ZoomFactor, absScreenPos.X, absScreenPos.Y);
    }
    private void AdjustScroll(Point? centerPoint)
    {
        if (centerPoint != null)
        {
            Point poi = Mouse.GetPosition(scrvImagePanel);

            double Xmove = ( scrvImagePanel.ActualHeight) / 2 - poi.X;
            double Ymove = (scrvImagePanel.ActualWidth) / 2 - poi.Y;

            if (left)
            {
                scrvImagePanel.ScrollToHorizontalOffset((scrvImagePanel.HorizontalOffset - Xmove) * scale);
                scrvImagePanel.ScrollToVerticalOffset((scrvImagePanel.VerticalOffset - Ymove) * scale);
            }
            else
            {
                scrvImagePanel.ScrollToHorizontalOffset((scrvImagePanel.HorizontalOffset - Xmove) / scale);
                scrvImagePanel.ScrollToVerticalOffset((scrvImagePanel.VerticalOffset - Ymove) / scale);
            }
        }
    }

我知道这段代码不能完美运行,但我认为这必须为您提供路径

关于WPF Scrollviewer 滚动到鼠标位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13968723/

相关文章:

javascript - 滚动时检测第一个顶部元素

c# - WPF 中的线程问题

image - 同一图像中的多重裁剪

python - 通过python在图像上编写复杂的自定义元数据

Laravel Eloquent 限制和偏移

Azure Cosmos DB - Azure DocumentDB 数据迁移工具 - 无法将大型数据库 (4GB) 导出到 json 文件

wpf - 如何让 StackPanel 的子级向下填充最大空间?

c# - WPF WebView 不显示

c# - 当文本框的背景在 wpf 中为灰色时插入符消失

html - 无法使用 CSS 调整图像大小