6

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

以下是如何将滚动条保持在其相对位置的描述。这很好用,但不是我想要的。

如何正确计算偏移量?

这是我的一些代码:

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

1 回答 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);
            }
        }
    }

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

于 2012-12-20T09:31:43.173 回答