c# - UWP: Calcular la Transformación basada en ScrollViewer
xaml windows-10 (1)
Tengo una aplicación universal de Windows donde renderizo una escena con DirectX. Quiero hacer uso del Scrollviewer y, por lo tanto, mostrar mi escena detrás del Scrollviewer y quiero calcular la transformación de escena basada en el Scrollviewer. Hasta ahora funciona bien, especialmente la traducción y el desplazamiento. Pero cuando hago un acercamiento, la escena salta en dos situaciones especiales:
- La escena tenía suficiente espacio y estaba centrada y ahora se requiere desplazamiento.
- La dirección opuesta.
Más o menos uso el siguiente código:
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);
Puede obtener un ejemplo aquí: https://github.com/SebastianStehle/Win2DZoomTest
Para estar seguro de que mis ojos no están rotos, estaba haciendo un acercamiento y escribí los valores de traducción y zoom en un archivo. Puedes verlo aqui:
https://www.dropbox.com/s/9ak6ohg4zb1mnxa/Test.png?dl=0
El significado de las columnas es el siguiente:
Columna 1: El valor de zoom calculado de la matriz de transformación (M11) = ScrollViewer.ZoomFactor Columna 2: El desplazamiento x calculado de la matriz (Ver arriba) Columna 3: El valor x del resultado de la matriz * vector (500, 500) , aquí: Colum1 * 500 + Columna2
Ya ves, los valores de la matriz se ven bien, pero al aplicar la transformación, obtienes este pequeño salto hacia la derecha durante algunos milisegundos. Una teoría era que la ventana gráfica podría cambiar porque la barra de desplazamiento se hace visible. Pero este no es el caso. También probé valores fijos aquí, hice visibles las barras de desplazamiento e incluso creé una plantilla personalizada para el scrollviewer sin barras de desplazamiento.
Por cierto: esta es una publicación cruzada, también hice la pregunta aquí: https://github.com/Microsoft/Win2D/issues/125
Verá este comportamiento porque cuando hace un zoom mayor que el tamaño del Visor de desplazamiento, se mueve el punto central del zoom. Para solucionarlo, solo tiene que suscribirse al evento LayoutUpdated
ScrollViewer
y, dentro del controlador, mantener su contenido en el centro de forma manual.
private void ScrollViewer_LayoutUpdated(object sender, object e)
{
this.ScrollViewer.ChangeView(this.ScrollViewer.ScrollableWidth / 2, this.ScrollViewer.ScrollableHeight / 2, this.ScrollViewer.ZoomFactor, true);
}
Esto debería arreglar el movimiento nervioso en los dos Rectangle
dibujados de Win2D .
Actualizar
Solo para demostrar mi punto, es probable que el comportamiento nervioso se deba a un cambio inusual en el valor de x y / o de traducción cuando el tamaño del contenido supera el tamaño del ScrollViewer
. Así que escribí un código para registrar estos valores en la pantalla como se muestra a continuación:
...
this.Test1.Text += ((float)translateX).ToString() + " ";
this.Test2.Text += ((float)translateY).ToString() + " ";
session.Transform =
Matrix3x2.CreateTranslation(
(float)translateX,
(float)translateY) *
Matrix3x2.CreateScale((float)zoom);
Ahora mira los números en la imagen de arriba. Lo que hice fue intentar acercarme hasta que ocurrió la escena. Ver el valor de traducir traducido y ? Es ligeramente mayor que su valor anterior, lo que está en contra de la tendencia decreciente.
Por lo tanto, para solucionar esto, deberá poder omitir estos valores inusuales causados por ScrollViewer
.