UWP:根据ScrollViewer计算转换

时间:2015-08-07 15:26:25

标签: c# xaml windows-10 uwp win2d

我有一个Windows通用应用程序,我正在使用DirectX渲染场景。我想使用Scrollviewer,因此我在Scrollviewer后面渲染我的场景,并希望根据Scrollviewer计算场景变换。它到目前为止工作正常,特别是翻译和滚动。但是当我放大时,场景会在两种特殊情况下跳跃:

  1. 场景有足够的空间并且居中,现在需要滚动。
  2. 相反的方向。
  3. 或多或少我使用以下代码:

    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

    你看,矩阵值看起来不错,但是在应用转换时,你可以向右跳几毫秒。一种理论认为,视口可能会发生变化,因为滚动条变得可见。但这种情况并非如此。我还尝试了固定值,使滚动条可见,甚至为滚动查看器创建了一个自定义模板,根本没有滚动条。

    顺便说一句:这是一篇交叉帖子,我在这里也问过这个问题:https://github.com/Microsoft/Win2D/issues/125

1 个答案:

答案 0 :(得分:6)

您会看到此行为,因为当您缩放大于product的大小时,会移动缩放中心点。要解决此问题,您只需订阅public class FrameArray { private String frameInventory; private int[] units; private double[] price; private double product; public FrameArray( String frame, int[] unitsArray, double[] priceArray, double product ) { frameInventory = frame; units = unitsArray; price = priceArray; product = weightedProduct(unitsArray, priceArray); } public void setFrameInventory( String frame ) { frameInventory = frame; } public String getFrameInventory() { return frameInventory; } public double weightedProduct(int[] unitsArray, double[] priceArray){ double value = 0; double product = 0; for(int i = 0; i < unitsArray.length; i++){ value = (double) (unitsArray[i] * priceArray[i]); product = product + value;} return product; } public void displayMessage() { System.out.printf( "Current frame inventory\n\n"); } public void processInventory() { outputInventory(); } public void outputInventory() { System.out.println( "Inventory levels:\n"); System.out.printf( "Style Qty Price Value\n\n"); for (int frame = 0; frame < price.length; frame++) System.out.printf( "Frame %2d: %3d %5.2f %5.2f\n", frame + 1, units[ frame ], price[ frame], product ); } } 的{​​{1}}事件,并在处理程序内部手动将其内容保留在中心。

ScrollViewer

这应修复来自 Win2D 的两个绘制ScrollViewer的跳跃运动。

更新

为了证明我的观点,当内容大小超过大小时,跳跃行为很可能是由于不正常的翻译x 和/或 y 值的变化。 LayoutUpdated。所以我写了一些代码来在屏幕上记录这些值,如下所示 -

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

enter image description here

现在查看上图中的数字。我做的是我尝试放大直到发生跳跃的场景。查看突出显示的翻译y 值?它略大于之前的价值,这与下降趋势相反。

因此,要解决此问题,您需要能够跳过由Rectangle引起的这些异常值。