javascript - w3schools - js canvas draw
Optimizaciones de rendimiento del ciclo de dibujo de Canvas de HTML5 (2)
Estamos construyendo una aplicación CAD que se ejecuta en un navegador.
- CAD significa Computer Aided Design .
- Illustrator, CorelDraw, AutoCAD, etc. son algunos ejemplos de aplicaciones CAD.
Se basa en Paper.js , una biblioteca de lienzo muy ordenada que te permite manipular vectores mediante programación.
El problema
El principal problema que estoy teniendo en este momento es el rendimiento del ciclo de dibujo.
El algoritmo de redibujo es ''tonto'' (en términos de hacks inteligentes para mejorar el rendimiento) y, por lo tanto, ineficiente y lento: la representación de los elementos del gráfico de escena depende de un ciclo de redibujo progresivamente más lento.
A medida que se acumulan los puntos para dibujar, cada ciclo de redibujo se vuelve más lento y más lento.
El esquema de redibujado es tan simple como se obtiene:
- despejar toda el área
- tomar todos los elementos de la gráfica de escena
- volver a dibujar todos los elementos.
La pregunta
¿Hay ejemplos de aula de optimizaciones de representación en estos casos? Suponiendo que me gustaría detenerme antes de implementar un algoritmo de rectángulos sucios (dibujando solo áreas que han cambiado)
Edición: He experimentado con la rasterización manual en el lugar que funciona bastante bien, he publicado una respuesta a continuación.
Herramienta útil
Mi rama de paper.js podría ayudar, pero quizás no sea la mejor opción para ti.
Le permite evitar que paper.js vuelva a dibujar todos los marcos (use paper.view.persistence = 1;
).
De esta manera, tendrá un mejor control sobre lo que debe borrar y debe volver a dibujarlo: por ejemplo, cuando mueve una forma, puede despejar el área donde estaba (usando el dibujo de lona nativo por ejemplo) y actualizarla una vez que se mueve (use la path.needsUpdate();
).
Retirarse
Los problemas vienen cuando las formas se cruzan. Si desea modificar una forma que se interseca con otra, deberá actualizar ambas. Lo mismo si la segunda forma se cruza con una tercera, y así una y así sucesivamente.
Por lo tanto, necesita una función recursiva, no difícil de codificar, pero puede ser costoso si hay muchas formas complejas que se intersecan, por lo que es posible que en este caso no obtenga el rendimiento.
(Actualización) caché de mapa de bits
Como lo sugirió Nicholas Kyriakides en la siguiente respuesta , el almacenamiento en caché de mapas de bits es una muy buena solución.
Un lienzo por forma
Una alternativa sería dibujar cada forma en un lienzo separado (trabajando como capas). De esta manera puedes despejar libremente y volver a dibujar cada forma independientemente. Puede separar el evento onFrame de las vistas que no están cambiando (todos los lienzos excepto el que está trabajando el usuario). Esto debería ser más fácil, pero conduce a otros pequeños problemas, como compartir los mismos parámetros de vista del proyecto (en el caso del zoom), y puede ser costoso con muchas formas (lo que significa muchos lienzos).
Lienzo estático y dinámico.
Un (probablemente) mejor enfoque sería tener solo dos lienzos, uno para las formas estáticas y otro para la forma activa. El lienzo de formas estáticas contendría todas las formas (excepto la que se está editando) y se volvería a dibujar justo cuando el usuario inicia y detiene la edición de la forma activa. Cuando el usuario comienza a editar una forma, se transfiere del lienzo estático al dinámico, y al revés cuando el usuario se detiene.
Esto se puede hacer con la rasterización en un proceso / técnica similar al almacenamiento en caché de mapas de bits .
El problema con los Gráficos de Escena con un alto número de nodos es que al renderizarlos, el motor de renderizado gime. El navegador debe atravesar sus nodos y representar sus píxeles en el lienzo.
Así que aquí hay una buena solución:
1. Renderice un mapa de bits, pero mantenga la forma original debajo, oculta
La solución es reemplazar los vectores con imágenes, rasterizarlos, solo cuando se renderizan, pero manteniendo la forma original debajo de su copia de la imagen, en un estado oculto solo cuando está inactivo ( no se está manipulando actualmente ).
Al hacer clic en las imágenes, las eliminamos y alternamos la visibilidad de la forma original. De esta manera, las formas inactivas se representan como imágenes y las formas activas se liberan de su representación de mapa de bits y actúan como vectores, que se pueden manipular libremente. Cuando no están activos, simplemente se sientan allí, invinsibles con su copia de Raster encima de ellos.
Esto permite que el motor mantenga la representación vectorial de las formas, pero evita representarlas como vectores, en lugar de eso, las imágenes que se parecen a ellas se colocan sobre ellas.
Los miles de comandos de ruta son esencialmente reemplazados por una sola imagen, pero solo cuando se procesa, la ruta original existe realmente como un objeto en el gráfico de escena, o cualquier tipo de DOM que esté usando
2. Rasterizar en grupos.
El truco es realizar la rasterización en grupos : agrupe de 10 a 15 formas y rasterícelos como una sola imagen. Esto mantiene el número de trama bajo. Al hacer clic en una imagen, podemos liberar todo el grupo o solo el elemento en el que se hizo clic.
3. Adjunte los controladores de clic en el grupo para restablecer la copia vectorial cuando se reactive.
Al rasterizar un grupo, simplemente podemos adjuntar un controlador de click
en él, de modo que al hacer clic en nosotros, alternamos mapa de bits con vector. Las imágenes no se comportan igual que los vectores cuando se realizan pruebas de impacto: las imágenes son squares
por naturaleza y no se pueden probar de forma asimétrica. Mientras que un vector considera que sus bordes están en los límites de su trayectoria, una imagen considera que sus límites son todo el cuadro delimitador. La solución es al hacer clic en la imagen para realmente probar el punto de clic con la ruta del vector debajo de la imagen; si se vuelve verdadera, realice una liberación.