6

スクロールビューア内の画​​像で構成される画像ビューアコントロールに取り組んでいます。ズームするには、画像のレイアウト変換内でスケール変換を使用します。Zoomin はマウス クリックで発生します。ユーザーが画像をクリックした場合、マウス位置のピクセルをスクロールビューアの視覚領域の中心に配置したいと思います。これを実現するには、スクロールビューアーのオフセットを変更したいのですが、マウスポインターの下のピクセルを中央に配置する正しいオフセットを計算する方法がわかりません。

以下は、スクロールバーを相対的な位置に保つ方法の説明です。それはうまくいきますが、私が探しているものではありません。

オフセットを正しく計算するにはどうすればよいですか?

これが私のコードの一部です:

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);
  }
}
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 に答える