WPF滚动查看器滚动到鼠标位置

6
我正在开发一个图像查看器控件,其中包含一个位于滚动视图内的图像。 为了缩放,我在图像的布局变换中使用比例转换。 缩小是通过鼠标点击来实现的。如果用户点击图像,我希望鼠标位置处的像素位于滚动视图的可视区域中心。 为了实现这一点,我想要修改滚动视图偏移量,但我不确定如何计算正确的偏移量,以将像素放置在鼠标指针下方的中心位置。

这里有一个保持滚动条相对位置的描述。虽然可以正常工作,但并不是我想要的。

你如何正确计算偏移量呢?

以下是我的一些代码:

XAML 代码:

<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);
  }
}

我不知道为什么,但最后一个答案消失了。我在AdjustScroll(...)中使用了您的描述,但滚动条仍然停留在偏移量=0处。 - tabina
1个回答

4

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

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);
            }
        }
    }

我知道这段代码并不完美,但我认为它可以给你提供路径


我尝试了您的代码,但是(在禁用缩放的情况下)滚动仍不正确。 - tabina
@tabina 抱歉,我的第一反应是错误的。请看编辑后的内容。我升级了你的问题,或许其他人可以帮忙。 - Ramin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接