24

DirectX でシーンをレンダリングしている Windows ユニバーサル アプリがあります。Scrollviewer を利用したいので、Scrollviewer の背後にあるシーンをレンダリングし、Scrollviewer に基づいてシーンの変換を計算したいと考えています。これまでのところ、特に翻訳とスクロールはうまく機能しています。しかし、ズームインすると、2 つの特別な状況でシーンがジャンプします。

  1. シーンには十分なスペースがあり、中央に配置されていたため、スクロールが必要になりました。
  2. 反対方向。

多かれ少なかれ、次のコードを使用します。

float zoom = scrollViewer.ZoomFactor;

float inverseZoom = 1f / scrollViewer.ZoomFactor;

float scaledContentW = Document.Size.X * scrollViewer.ZoomFactor;
float scaledContentH = Document.Size.Y * scrollViewer.ZoomFactor;

float translateX;
float translateY;

if (scaledContentW < scrollViewer.ViewportWidth)
{
    translateX = ((float)scrollViewer.ViewportWidth * inverseZoom - Document.Size.X) * 0.5f;
}
else
{
    translateX = -inverseZoom * (float)scrollViewer.HorizontalOffset;
}

if (scaledContentH < scrollViewer.ViewportHeight)
{
    translateY = ((float)scrollViewer.ViewportHeight * inverseZoom - Document.Size.Y) * 0.5f;
}
else
{
    translateY = -inverseZoom * (float)scrollViewer.VerticalOffset;
}

float visibleX = inverseZoom * (float)scrollViewer.HorizontalOffset;
float visibleY = inverseZoom * (float)scrollViewer.VerticalOffset; ;

float visibleW = Math.Min(Document.Size.X, inverseZoom * (float)scrollViewer.ViewportWidth);
float visibleH = Math.Min(Document.Size.Y, inverseZoom * (float)scrollViewer.ViewportHeight);

Rect2 visibleRect = new Rect2(visibleX, visibleY, visibleW, visibleH);

transform =
    Matrix3x2.CreateTranslation(
        translateX,
        translateY) *
    Matrix3x2.CreateScale(zoom);

ここで例を取得できます: https://github.com/SebastianStehle/Win2DZoomTest

私の目が壊れていないことを確認するために、ズームして、翻訳とズームの値をファイルに書き込んでいます。ここで見ることができます:

https://www.dropbox.com/s/9ak6ohg4zb1mnxa/Test.png?dl=0

列の意味は次のとおりです。

列 1: 変換マトリックス (M11) の計算されたズーム値 = ScrollViewer.ZoomFactor 列 2: マトリックスの計算された x オフセット (上記を参照) 列 3: マトリックス * ベクトル (500, 500) の結果の x 値、ここでは:Colum1 * 500 + Column2

ご覧のとおり、行列の値は適切に見えますが、変換を適用すると、数ミリ秒間右に小さなジャンプが発生します。1 つの理論は、スクロールバーが表示されるため、ビューポートが変更される可能性があるというものでした。しかし、そうではありません。ここでも固定値を試し、スクロールバーを表示し、スクロールバーのないスクロールビューアー用のカスタム テンプレートを作成しました。

ところで:これはクロスポストです。私もここで質問しました:https ://github.com/Microsoft/Win2D/issues/125

4

1 に答える 1

6

ScrollViewerのサイズよりも大きくズームすると、ズームの中心点が移動するため、この動作が見られます。ScrollViewerこれを修正するには、のイベントをサブスクライブしLayoutUpdated、ハンドラー内でそのコンテンツを手動で中央に保持するだけです。

    private void ScrollViewer_LayoutUpdated(object sender, object e)
    {
        this.ScrollViewer.ChangeView(this.ScrollViewer.ScrollableWidth / 2, this.ScrollViewer.ScrollableHeight / 2, this.ScrollViewer.ZoomFactor, true);
    }

これにより、 Win2DRectangleから描画された 2 つの のびくびくした動きが修正されます。


アップデート

私の主張を証明するために、コンテンツのサイズがScrollViewer. そこで、以下に示すように、これらの値を画面に記録するコードをいくつか書きました-

...
this.Test1.Text += ((float)translateX).ToString() + " ";
this.Test2.Text += ((float)translateY).ToString() + " ";

session.Transform =
    Matrix3x2.CreateTranslation(
        (float)translateX,
        (float)translateY) *
    Matrix3x2.CreateScale((float)zoom);

ここに画像の説明を入力

次に、上の画像の数字を見てください。私がやったことは、ビクビクするシーンが発生するまでズームインしてみました. 強調表示された平行移動 y値を確認しますか? 減少傾向に反して、前回の値よりもわずかに大きくなっています。

したがって、これを修正するには、 によって引き起こされるこれらの異常値をスキップできる必要がありますScrollViewer

于 2015-08-20T03:59:19.640 に答える