Video Summary and Transcription
Las flechas etiquetadas se utilizan ampliamente en conversaciones, comunicación, diagramas y más. La charla discute la construcción de flechas etiquetadas, la representación de flechas en Canvas, la optimización de llamadas de API de trazo, el uso de RoughJS para dibujar y renderizar texto, la representación de texto multilinea en Canvas, la limpieza de áreas superpuestas y el recorte, la comparación del rendimiento del recorte y clear rect, el manejo del recorte y la vinculación de etiquetas a flechas, la vinculación de flechas etiquetadas a textos, texto rotado y exportación como SVG, enmascaramiento en SVG y etiquetado de flechas, enmascaramiento SVG y mejoras de rendimiento, y optimización de la representación y el dibujo en Canvas.
1. Introducción a las Flechas Etiquetadas
Las Flechas Etiquetadas son flechas con texto adjunto. Se utilizan ampliamente en conversaciones, comunicación, diagramas y más. En esta parte, exploraremos cómo se construyen las Flechas Etiquetadas y discutiremos los requisitos para construir un prototipo, incluyendo la renderización de flechas, la vinculación de etiquetas y flechas, el soporte de flechas multipunto, el manejo de la rotación de etiquetas y la exportación a SVG.
Antes de comenzar, permítanme dar una breve introducción. Soy Akansha, soy una mantenedora de código abierto, FOSS básicamente significa software libre y de código abierto. Soy una mantenedora principal de Excalidraw, ReactJS y algunas otras bibliotecas de código abierto. También organizo estos encuentros de FOSS en Bangalore, India para promover la comunidad FOSS en India. Y sí, estas son mis redes sociales. Me encantaría conectarme con todos ustedes y hablar sobre cualquier cosa relacionada con el frontend, React, código abierto, Canvas, cualquier cosa.
Entonces, ahora comencemos con la charla. ¿Qué quiero decir exactamente con Flechas Etiquetadas? Las Flechas Etiquetadas son básicamente cuando tienes una flecha y le adjuntas algún texto, eso es básicamente una Flecha Etiquetada. Seguramente lo habrás utilizado en alguna conversación, como puedes ver en la conversación entre dos amigos o alguna comunicación, algún flujo, algún diagrama arquitectónico para mostrar algunas direcciones, alguna información crucial. Puede ser cualquier cosa, pero es una de las características más utilizadas. Entonces, como vamos a implementarlo, veamos cómo se construye internamente esta Flecha Etiquetada. Veamos este ejemplo. Esta es una Flecha Etiquetada. Tiene una línea. Consiste en una línea. Consiste en una cabeza de flecha y un texto. Al menos al construir una Flecha Etiquetada, tienes al menos tres elementos diferentes separados. Y hagamos una nota de esto porque vamos a profundizar en esto.
Ahora, como hacemos los desarrolladores, antes de construir cualquier característica, vamos a establecer algunos requisitos mínimos para construir un prototipo. Veamos la lista de requisitos. Primero, queremos entender cómo podemos renderizar las flechas en Canvas, cómo podemos renderizar la etiqueta que es el texto encima de la flecha, cómo podemos vincular la etiqueta y la flecha. En el código, somos conscientes de que, hey, esta etiqueta en particular está adjunta a esta flecha en particular, y esta flecha tiene esta etiqueta. Así que solo necesitamos una relación entre estos dos elementos. ¿Cómo debemos renderizar la etiqueta para flechas multipunto? También hablaré de esto en un momento. ¿Y cómo debemos renderizar la etiqueta cuando rotamos una flecha? Y por último, queremos admitir la exportación a SVG también. También hablaremos un poco de SVG. Así que tengamos este conjunto de requisitos. Profundizaré en cada uno de ellos. Y los cumpliremos uno por uno y tendremos un prototipo mínimo al final.
2. Estructurando Elementos en Canvas
Para estructurar elementos en Canvas, utiliza un JSON mínimo con tipo, ID, coordenadas XY, ancho, alto, puntos, cabeza de flecha de inicio y cabeza de flecha de fin. Para comprender a la audiencia, realicé una encuesta y descubrí que el 63% son principiantes y el 37% son intermedios. Ahora, discutamos cómo renderizar flechas en Canvas utilizando la API de dibujo, que consta de rectángulos y rutas. Nos centraremos en las rutas y aprenderemos cómo crear un lienzo y interactuar con él.
Entonces, antes de eso, comprendamos cómo queremos estructurar los elementos en el Canvas. Este es el JSON mínimo, en el que puedes pensar. Tiene un tipo, que básicamente es el tipo de elemento. ¿Es una flecha o es un texto? El ID del elemento, que utilizarás para representar de manera única el elemento en el Canvas. Por lo tanto, cada elemento en el Canvas tendrá un ID único. Las coordenadas XY son básicamente las coordenadas para posicionarlos en el Canvas. El ancho y el alto son las dimensiones. Los puntos son un parámetro importante cuando se trata de flechas porque una flecha puede tener dos puntos, 100 puntos, 1,000 puntos, ¿quién sabe? Es básicamente la matriz de esos puntos. La cabeza de flecha de inicio y la cabeza de flecha de fin son básicamente los dos puntos extremos de la flecha y la forma de la cabeza de flecha, puedes decidirlo. Puedes tener una estrella. Puedes tener un círculo, cualquier forma que desees. Esto es como un JSON mínimo. Consideremos este JSON.
Así que acabo de compartir esto en las redes sociales para comprender a la audiencia y les pedí que completaran un formulario de Google solo para comprender el nivel de comprensión de la audiencia para esta charla. Y esto es lo que obtuve. Obtengo que el 63% de la audiencia serán principiantes y el 37% serán intermedios y lo mismo para SVG. ¿Puedo ver un rápido levantamiento de manos? ¿Quiénes son nuestros principiantes en Canvas aquí? ¡Genial! Gracias. Gracias por participar. Creo que algunos de ustedes participaron en esto, y muchas gracias.
Entonces, sí, vayamos ahora al primer requisito. ¿Cómo puedes renderizar las flechas en Canvas? Vamos a los conceptos básicos primero. La API de dibujo de Canvas se divide en dos categorías principales. Una es rectángulo y otra es rutas. El rectángulo se utiliza para dibujar rectángulos. Las rutas son básicamente una colección de muchos puntos con los que puedes dibujar cualquier forma compleja en Canvas. Y en esta charla, hablaremos mucho sobre rutas. Volviendo a los conceptos básicos, creas un lienzo. Obtienes el contexto para poder interactuar con el lienzo.
3. Dibujando Flechas en Canvas
Para dibujar una línea en Canvas, llama a la API de begin path, establece los estilos de trazo, muévete al punto de inicio y dibuja una línea hasta el punto final. Para dibujar una cabeza de flecha, dibuja la mitad de la forma de la cabeza de flecha desde el punto final de la línea. Luego, dibuja la otra mitad de la forma de la cabeza de flecha desde el punto final de la línea. Para flechas de múltiples puntos, dibuja múltiples líneas y llama a la API de trazo solo una vez para mejorar el rendimiento.
Antes de comenzar cualquier trazo, debes llamar a la API de begin path y luego establecer algunos estilos de trazo, que es el color de la flecha. Una vez que hagas esto, tenemos las APIs de move to y line to. Move to básicamente significa que mueves el lápiz a x, y, que se muestra en el diagrama. Luego, dibujo una línea hasta x más longitud, y, que aún no es visible. Para hacerlo visible, para pintarlo en el lienzo, debes llamar a la API de trazo. Esta es la forma mínima en la que puedes dibujar una línea.
Ahora dibujemos las cabezas de flecha. Estoy en este punto en particular, el extremo de la línea. Desde allí, dibujo la mitad de la cabeza de flecha. Puedes ver en la parte superior izquierda, he ampliado la cabeza de flecha, que tiene 20 píxeles de ancho y 10 píxeles de alto. Básicamente, dibujo una línea hasta A, B, que es la coordenada superior. Luego, vuelvo al mismo punto, x más longitud, y, y luego dibujo otra línea hasta A, C. Así es como dibujas una flecha. Puede parecer que son muchos pasos, pero es solo una combinación de las APIs line to y move to. Eso es todo.
Entonces, sí, esto es sobre la flecha. Ahora veamos las flechas de múltiples puntos. Una flecha de múltiples puntos puede tener más puntos, más de dos. Esta tiene cuatro puntos. Veamos rápidamente cómo se verá esto. Básicamente, dibujas una línea desde x hasta x más ancho, y luego llamas a la API de trazo para que sea visible. Luego, dibujas otra línea, llamas a la API de trazo, dibujas otra línea, llamas a la API de trazo y luego dibujas las cabezas de flecha. En esta, si te fijas, estamos llamando a la API de trazo varias veces. Esto puede ser costoso, especialmente si la flecha tiene 100 puntos o 1,000 puntos. Lo que debemos hacer es agrupar todas estas llamadas y llamar a la API de trazo solo una vez, ya que también obtendrás el mismo resultado. Tengo una demostración rápida para mostrarte cómo el rendimiento puede verse afectado en estos casos.
4. Optimizando Llamadas a la API de Trazo
Al dibujar flechas en Canvas, es importante evitar llamar a la API de trazo varias veces, ya que puede afectar significativamente el rendimiento. En su lugar, utiliza una única polilínea y llama a la API de trazo solo una vez al final. Este enfoque puede ser mucho más rápido, especialmente para un gran número de puntos, como se muestra en el ejemplo.
Entonces, sí. Este se encuentra básicamente en el lado izquierdo. Básicamente estoy dibujando una flecha a la que llamo a la API de trazo varias veces, como puedes ver aquí. Básicamente estoy llamando a este trazo dentro del bucle. Permíteme completar esta función donde solo llamo a la API de trazo una vez. Permíteme copiarlo aquí. Una única polilínea, con una única polilínea me refiero a que solo llamaré a la API de trazo una vez al final. Y dado que son múltiples puntos, es una polilínea.
Y ahora solo copio esto. Y ahora permíteme descomentar esto. Entonces... Sí. Ahora veamos cómo se comporta. Así que veamos. Permíteme hacerlo. Permíteme refrescarlo una vez. Sí. Veamos para 100 puntos. Si observas, la única polilínea toma 0.2 milisegundos frente a los múltiples que toman 0.3 milisegundos. Así que es 1.5 veces más rápido. Para 1,000, son 5.9 frente a 5.8. No es una diferencia muy grande. Pero si voy más allá de esto, no puedo mostrártelo en mi máquina en este momento, porque mi navegador puede colapsar debido a que es una API muy costosa. Así que solo tengo una grabación rápida para eso, solo para que entiendas lo costoso que puede llegar a ser. Así que vamos a ver eso.
Así que vamos a ver esta demostración rápida. Así que para 10,000, puedes ver que es 228 veces más rápido. Y luego mi navegador se bloquea. Esto es a lo que me refería, que si llamas a la API de trazo varias veces, esto es lo que sucederá. Si observas esto, son 0.7 milisegundos frente a 159 milisegundos cuando llamas varias veces.
5. Usando RoughJS para Dibujar y Renderizar Texto
Para evitar bloqueos del navegador, ten cuidado al llamar a la API de trazo para rutas complejas. En su lugar, utiliza RoughJS, una biblioteca que proporciona APIs simplificadas para dibujar formas en Excalidraw. Además, RoughJS agrega una sensación de dibujo a mano a tus dibujos. Ahora, pasemos al siguiente requisito: renderizar la etiqueta encima de la flecha. En canvas, renderizar texto requiere establecer la fuente, el estilo de relleno y utilizar la API de relleno de texto. Canvas no admite texto de varias líneas, por lo que cada línea debe renderizarse individualmente.
Y después de esto, mi navegador simplemente se bloqueará. Y depende de dónde lo estés testing. Lo estoy testing en Chrome y Mac. Puede ser diferente cuando lo pruebes en diferentes navegadores. Así que sí. Eso es algo a tener en cuenta, usar esto con precaución. No llames innecesariamente a la API de trazo para rutas complejas. Llámala solo una vez. O agrupa las llamadas. Así que sí. En Excalidraw, no tenemos que usar estas APIs de bajo nivel de canvas. Utilizamos RoughJS, que proporciona APIs simplificadas para dibujar las formas. Y además, si has utilizado Excalidraw, verás esa sensación de dibujo a mano, los trazos, la rugosidad. Todos ellos provienen de esta biblioteca RoughJS. Es una biblioteca fantástica creada por Preet. Échale un vistazo si quieres. Y sí, es una gran biblioteca. Así que sí, échale un vistazo.
Y ahora, se cumple el primer requisito de renderizar las flechas en canvas. Ahora, pasemos al siguiente requisito, que es renderizar la etiqueta encima de la flecha. Así que empecemos por lo básico. ¿Cómo se renderiza un texto en canvas? Tomas un texto, le das la fuente y el estilo de relleno. Y la API de relleno de texto es básicamente la que utilizarás para renderizar el texto en el canvas. Ahora, aquí he tomado un texto simple, hola react summit con una carita sonriente. Y se renderiza así con un color rosado. Permíteme tomar un texto de varias líneas. Y este, si lo ves, tengo slash n en mi texto. Pero al renderizarlo, se muestra como una sola línea. Esto se debe a que canvas no admite texto de varias líneas.
6. Renderización de Texto Multilínea en Canvas
Para renderizar texto multilínea en el canvas, divide las líneas individualmente y calcula sus dimensiones. Utiliza la API de clear rect para eliminar el área superpuesta entre el texto y la flecha. Finalmente, renderiza el texto encima del área borrada.
Si tienes varias líneas, debes dividirlas individualmente y renderizarlas individualmente en el canvas. Entonces lo que haces es simplemente dividir estas líneas por slash n y renderizarlas y renderizarlas con una diferencia de altura de línea vertical para que no estén una encima de la otra. La altura de línea es un concepto que proviene del navegador. Habrás visto como la altura de línea, cada navegador tiene una altura de línea diferente. Cuando se trata de una altura de línea sin unidades, 1.2, 1.25 son los valores más recomendados. También puedes utilizar otro valor, pero estos son los valores recomendados. Y como canvas trabaja con píxeles, simplemente lo multiplicamos por el tamaño de fuente y renderizamos estas líneas individualmente. Y así es como se verá. Entonces sí, así es como se renderizan las múltiples líneas. Ahora, si lo renderizo, se verá así encima de la flecha.
7. Eliminación de Área Superpuesta y Recorte
Para lograr el efecto deseado de que la flecha sea parte del texto, tenemos dos enfoques: utilizar la API clear rect y el recorte. La API clear rect nos permite calcular las dimensiones del texto y eliminar los píxeles superpuestos del canvas. El recorte implica definir una región y mostrar solo la parte recortada. Estos métodos proporcionan diferentes formas de lograr el resultado deseado.
Entonces, queremos eliminar esta área superpuesta que está con el texto. Eso es algo que quiero eliminar para que parezca que la flecha es realmente parte del texto y no un elemento superpuesto encima de él. ¿Cómo podemos hacer eso?
Para eso, queremos eliminar esta área en particular de la flecha. Y para eso, tenemos dos enfoques. Uno es utilizar la API clear rect y otro es el recorte. Veamos cómo se ve la API clear rect. Para eso, primero necesito calcular las dimensiones del texto. Y para calcular las dimensiones del texto, puedo utilizar la API measure text del canvas. La API measure text es proporcionada por el canvas y te brinda muchas otras métricas. La anchura es algo en lo que estoy interesado. Puedo usar esta API para calcular la anchura de un texto dado. Y la altura, como mencioné, es simplemente el tamaño de fuente multiplicado por la altura de línea. Esa es la altura del texto. ¿Pero qué pasa con el texto multilínea? Porque el canvas no admite texto multilínea. Por lo tanto, la API measure text tampoco funcionará con texto multilínea. Nuevamente, tenemos que dividirlo en líneas, calcular la anchura de cada línea y tomar la anchura de la línea más larga. En este caso, la página cuando se ve tiene la anchura más larga y esa es la anchura más segura para tomar. De manera similar para la altura, simplemente haz el tamaño de fuente multiplicado por la altura de línea y multiplícalo por el número de líneas que tengas. Eso te dará la altura del texto. Una vez que tenemos esto, simplemente llamamos a la API clear rect y con la ayuda de esta API, estos píxeles se eliminan del canvas y simplemente puedes renderizar el texto encima de él y así es como se ve. Esto es lo que queremos ver. Entonces, básicamente, esta es la implementación con clear rect. Es lo suficientemente simple para comenzar.
Ahora veamos también cómo funciona el recorte. Entendamos qué es exactamente el recorte. Consideremos este rectángulo en el lado derecho y quiero recortar esta región en particular que estoy mostrando con el rectángulo negro.
Entonces, básicamente lo que puedes hacer... Hay esta API rect que puedes llamar al tratar con el recorte. Lo que hacemos es simplemente dibujar este rectángulo y llamar a la API clip y solo esta porción del dibujo completo será visible, cualquier parte que hayas recortado. Ahora esto fue una región de recorte simple, solo un pequeño rectángulo.
8. Combinando Múltiples Partes de Recorte
Para lograr un recorte más complejo, podemos combinar múltiples partes y utilizar el parámetro 'even odd' de la API clip. Al crear un agujero en la región de intersección de las partes de recorte, podemos eliminar píxeles y hacer que toda la flecha sea visible. Esto proporciona una alternativa al uso de la API clear rect.
Puedo hacerlo más complejo combinando múltiples partes. Entonces, digamos que quiero recortar esta región donde tienes dos rectángulos. Y en este caso, nuevamente, si llamo a la API clip, solo esta región particular de todo el dibujo será visible porque esta es la región de recorte. Además de esto, la API clip toma otro parámetro que es... Lo cual básicamente te ayuda... Entonces, básicamente, otro parámetro es even odd, que básicamente crea un agujero en la región de intersección de las partes de recorte. Y esto es interesante porque esto es algo que realmente podemos utilizar cuando se trata de flechas etiquetadas. Entonces, lo que podemos hacer es, dado que sabemos que, bueno, tomamos múltiples partes de recorte y donde se están intersectando, simplemente se crea un agujero, lo que significa que se eliminan píxeles de allí. Entonces, lo que podemos hacer es tomar el rectángulo exterior porque queremos recortar esta área, queremos hacer que toda esta flecha sea visible. Tomemos otro rectángulo que sean las dimensiones del texto. Y en esta región particular donde ambos se superponen o se intersectan, se debe crear un agujero. Se deben eliminar los píxeles. Eso es lo que queremos. Una vez hecho esto, nuevamente tendrás el mismo resultado que con clear rect. Estos píxeles se eliminarán y puedes renderizar texto encima de ellos. Así que esto fue sobre el recorte.
9. Comparando el Rendimiento de Recorte y Clear Rect
En la demostración rápida, comparamos el rendimiento de recorte y clear rect. El recorte se implementa creando un agujero en la intersección de los rectángulos exterior e interior, eliminando píxeles. El rendimiento varía según el número de iteraciones, siendo el recorte inicialmente más rápido pero desacelerando con más iteraciones.
Ahora el rendimiento varía en ambos casos nuevamente. Así que vamos a la demostración rápida donde podemos comparar el recorte y el rendimiento de clear rect.
En este caso, actualmente el recorte aún no está implementado. Permítanme implementarlo rápidamente aquí. Solo... Con el propósito de mostrar cómo se verá, hagamos esto. Sí. Básicamente, este es el rectángulo exterior para mostrarles que esto es algo que voy a recortar. Luego, también dibujaré el rectángulo interior o las dimensiones del texto. Tal vez le dé un color amarillo. Y luego hago esto. Y tomo las dimensiones del texto y veo cómo se ve. Entonces, sí. Como pueden ver, esta es básicamente... La parte amarilla son las dimensiones del texto que voy a recortar. Y el negro es el rectángulo exterior. Y donde estas dos regiones se intersecten, se creará un agujero. Así que ahora voy a eliminar esta parte y usar el recorte que ya tengo aquí. Y una vez que hagamos esto, pueden ver que los píxeles se eliminan y es igual que clear rect.
Ahora voy a ejecutarlo y ver cómo se ve el rendimiento. Por primera vez, parece que el recorte es más rápido. Toma 0.1 milisegundos para una sola iteración frente a 0.4. Veamos para 10. Veamos para 100. Ahora se vuelve un poco más lento. 5 milisegundos frente a 2.4. Y hagamos 1000 iteraciones. A medida que aumento las iteraciones, cada vez que vuelvo a renderizar esto una y otra vez, el recorte se vuelve un poco más lento. 1.11 milisegundos frente a 15 milisegundos. No puedo ir más allá de esto.
10. Manejo de Recorte y Vinculación de Etiquetas a Flechas
El recorte es una operación intensiva que puede hacer que el navegador se bloquee con un gran número de iteraciones. Clear rect es más rápido y se utiliza en Excalibur. Los usuarios pueden interactuar con la función al renderizar un área de texto encima del lienzo, creando un elemento DOM. Las etiquetas pueden vincularse a las flechas en una relación uno a uno.
Mi navegador se bloqueará porque el recorte también es una operación intensiva. Así que permítanme mostrarles una demostración rápida de lo lento que puede ser en mi máquina. Así que veamos aquí. Si voy a 100, voy a 1000. Y veamos cómo se comporta para 10000. Sí. Si ven aquí, 12,551 milisegundos frente a 120 milisegundos. Pueden imaginar lo lento que se vuelve el recorte cuando tienes 10000 elementos o 10000 iteraciones, como 10000 elementos pueden imaginar porque estoy repitiendo esta operación 10000 veces y luego mi navegador se bloquea. Así que sí. Así que sí. Ahora déjenme solo. Un segundo. Sí. Sí, eso fue sobre recorte versus clear rect. Ahora una vez que hayas renderizado el texto, clear rect parece más rápido. Eso es lo que también usamos en Excalibur. Ahora lo que tenemos que hacer es que los usuarios puedan interactuar realmente con esta función, necesitamos algún DOM encima del lienzo. Así que simplemente rendericemos un área de texto encima del lienzo, con una posición absoluta para que se coloque encima de él. Eliminemos todo el estilo. Como pueden ver, margen 0, relleno 0, borde 0, contorno 0, para que los usuarios sientan que están escribiendo en el lienzo, pero en realidad es un elemento DOM. Básicamente, es para que los usuarios sientan que están escribiendo en la aplicación, escribiendo directamente en el lienzo. Así que sí, aquí es donde está la interacción del usuario y sí, con esto cumplimos también el segundo requisito.
11. Vinculación de Etiquetas a Flechas
La vinculación de etiquetas a flechas requiere una relación uno a uno entre ellas. Agregar un ID de etiqueta al JSON ayuda a identificar las flechas etiquetadas. El texto puede ser identificado como parte de una flecha etiquetada por su ID de contenedor.
Entonces, vamos al tercer requisito. Ahora quiero vincular la etiqueta y la flecha para que como desarrolladores sepamos qué etiqueta está adjunta a qué flecha y qué flecha tiene qué etiqueta viceversa. Así que tengamos algunas suposiciones para mantenerlo simple. Una flecha puede tener solo una etiqueta. Bastante justo. No creo que queramos adjuntar varias flechas o varias etiquetas a una sola flecha o tal vez podamos discutirlo, pero sí. Una etiqueta solo puede estar adjunta a una flecha. Es básicamente una relación uno a uno entre la flecha y la etiqueta. Y esto simplifica muchas cosas. Entonces, lo que podemos hacer es en este JSON, lo que quiero es que al mirar este JSON, debería poder identificar si es una flecha regular o una flecha etiquetada. Dado que cada elemento tiene un ID único, simplemente agreguemos un ID de etiqueta, lo cual ayudará a identificar si una flecha tiene un ID de etiqueta, significa que es una flecha etiquetada. De lo contrario, es una flecha regular. Entonces, una revisión parece estar bien. Ahora lo mismo para el texto. Si un texto, agreguemos también un atributo al texto. Digamos ID de contenedor.
12. Vinculación de Flechas Etiquetadas a Textos
Vincular flechas etiquetadas a sus textos es bastante simple. Al verificar el ID de la etiqueta, las acciones aplicadas a la flecha se replican en el texto. Para flechas de múltiples puntos, adjuntar el texto al punto medio lo hace intuitivo. Para un número par de puntos, el texto se posiciona en el punto medio del segmento medio. Se discutirá la representación de la etiqueta cuando la flecha está rotada.
Si un texto tiene un ID de contenedor, significa que es parte de una flecha etiquetada y no un texto regular. De lo contrario, es un texto regular. Sí, esto parece simple. Vincular ambos es bastante simple.
Ahora, una vez que hayamos hecho esto, lo que podemos hacer es, mientras muevo la flecha etiquetada, puedo verificar si esta flecha tiene un ID de etiqueta. Permíteme mover también el texto. Cuando estoy redimensionando la flecha etiquetada, puedo verificar si esta flecha tiene un ID de etiqueta. Permíteme redimensionar también el texto. Entonces, cualquier acción que apliques a la flecha etiquetada se replicará en el elemento de texto también porque puedes vincular ambos. Sí, una vez que esto se haya hecho, también se cumplirá este requisito.
Ahora pasemos al siguiente, que es cómo se debe representar la etiqueta para flechas de múltiples puntos. Entonces, en este caso, si ves, estas son flechas de múltiples puntos. Por flecha de múltiples puntos, me refiero a cualquier flecha compleja con más de dos puntos. Entonces, en este caso, si ves, siguiendo la lógica anterior, donde tomé dos puntos extremos y representé el texto en la línea, el punto medio de la línea, se vería así porque esta es la línea que une los dos puntos extremos de la flecha y este es el punto medio. Pero esto parece un poco desconectado de las formas, ¿verdad? No está realmente conectado a las formas. Entonces ahora necesitamos algo de intuición, algo de lógica aquí, cómo podemos mejorarlo.
Entonces, lo que podemos hacer es una flecha puede tener un número impar o un número par de puntos. Lo que podemos hacer es que esta es una flecha con un número impar de puntos. Entonces, cuando tienes un número impar de puntos, siempre tienes un punto medio. Así que simplemente adjuntemos el texto al punto medio. Donde sea que esté este punto medio, simplemente adjuntemos el texto al punto medio. De esa manera será intuitivo para una parte de las flechas donde tienes un número impar de puntos. Ahora, ¿qué haces? Así es como se verá. Entonces, ¿qué haces cuando tienes un número par de puntos, no tienes ningún punto medio aquí, pero cuando tienes un número par de puntos, tienes un número impar de segmentos. Entonces, si ves, hay uno, dos, tres, cuatro, cinco segmentos aquí, tomemos el segmento medio y el punto medio del segmento medio. Entonces, en este caso, simplemente podemos representar el texto en esta posición particular donde tienes un número par de puntos. Entonces, en resumen, así es como se verá. Ahora el texto está realmente adjunto a estas flechas y te dará la sensación de que, okay, estas flechas de múltiples puntos están realmente conectadas con él. Esta es una forma de hacerlo. Así es como se hace en Excalibur también. Y el siguiente es cómo queremos representar la etiqueta cuando la flecha está rotada a un cierto ángulo. Consideremos estos ejemplos.
13. Texto Rotado y Exportación de Flechas Etiquetadas como SVG
Cuando se compara la legibilidad del texto rotado y no rotado, el texto no rotado es más legible. El texto de la flecha en Excalidraw siempre se representa de izquierda a derecha para priorizar la legibilidad. La exportación de flechas etiquetadas como SVG implica el uso de elementos de ruta para representar la flecha y convertir las API de movimiento y línea en API de SVG. El desafío es ocultar el área donde el texto y la línea se superponen en el SVG.
El lado izquierdo, el texto no está rotado o el texto está rotado. El lado derecho, el texto no está rotado. ¿Cuál crees que es más legible, L o R? Sí, R es más legible. Genial. ¿Cuál crees que es más legible, L o R? ¿Puedo escuchar más ruido? De acuerdo. Entonces, en ambos casos, cuando el texto no está rotado, es más legible, ¿verdad? Así es como se ve si comparas el texto rotado y el texto no rotado. Y esto es así, si usas Excalidraw, verás que cuando rotas la flecha a cierto ángulo, el texto nunca se rotará. Siempre lo representaremos de izquierda a derecha. Y esta es la razón porque queremos dar importancia a la legibilidad. Pero, sí, si recibimos solicitudes futuras para rotar también el texto de la flecha, entonces podemos considerarlo dependiendo de la cantidad de solicitudes. Pero, sí.
Ahora la última parte. ¿Cómo exportas las flechas etiquetadas como SVG? Esto también es algo que queremos en nuestro, estaba en la lista de requisitos. Así que vamos a ello. Vamos a lo básico primero. Así es como se ve el SVG. SVG es básicamente basado en vectores. Está en el DOM a diferencia de Canvas. Utilizas elementos de ruta para representar la flecha. Si te fijas aquí, M básicamente significa mover el lápiz a, similar al API move to. L básicamente significa dibujar una línea hasta 200, 10. Básicamente similar al API line to de Canvas. Así que básicamente es la misma API, solo que escrita de manera diferente. Así que relacionemos esto entre sí. Ahora, si puedes visualizar, todos los API move to y line to se convierten en API de SVG. Y eso es, esa es la conversión. Pero te ayuda a visualizarlo, cómo básicamente ambos son lo mismo. Es solo una forma diferente de escribirlo. Así que ahora, nuevamente, estamos ante el mismo problema. ¿Cómo ocultamos esta parte de la flecha en el SVG? Queremos ocultar nuevamente esta área en el SVG donde el texto y la línea están Queremos enmascarar esta área en particular.
14. Enmascarado en SVG y Etiquetado de Flechas
Cuando se aplica enmascarado en SVG, el color blanco significa revelar el área y el color negro significa ocultarla. Agregar enmascarado implica aplicar atributos e IDs a los elementos. Diferentes colores de relleno determinan la visibilidad, siendo el negro completamente invisible y el blanco completamente visible. Aplicar esta lógica a las flechas etiquetadas implica rellenar el rectángulo exterior con blanco y rellenar las dimensiones del texto con negro para ocultar la región. Agregar el rectángulo de fondo blanco a la máscara hace que la flecha sea visible.
Ahora, cuando se trata de enmascarado, el color blanco significa revelar el área, el color negro significa ocultarla. El blanco significa transparente, el negro significa opaco. Esta es una regla para recordar. Así que recordemos esta regla. Y veamos cómo se ve el enmascarado en SVG.
Nuevamente, es el mismo rectángulo rojo que les mostré hace un par de minutos. Y así es como se puede agregar enmascarado. Básicamente, se agregan los atributos de enmascarado, se le asigna un ID. Y luego, como pueden ver, en el rectángulo, estoy aplicando esa máscara con la ayuda del ID de la máscara.
Entonces agreguemos algunas regiones de enmascarado aquí. Ahora, si observan, he agregado cuatro regiones de enmascarado aquí. Y cada una tiene un color de fondo diferente. Cada una tiene un color de relleno diferente. Así que si se fijan, el segundo rectángulo, la segunda región de enmascarado, es completamente invisible porque está relleno de negro. Negro significa opaco. Y el cuarto es completamente visible. Y el último, es completamente visible porque está relleno de blanco. Blanco significa transparente. Entonces, cuando lo rellenas de negro, básicamente oculta esos píxeles. Y cuando lo rellenas de blanco, básicamente lo hace transparente.
Así que usemos la misma lógica cuando se trata de flechas etiquetadas. Permítanme dibujar un rectángulo exterior porque quiero que esta región completa sea visible. Así que lo hago transparente, lo relleno de blanco. Y las dimensiones del texto, quiero ocultar esta región en particular de la flecha. Así que la rellenaré de negro. Esto solo ocurre en el SVG de la flecha, el texto está fuera del enmascarado. Entonces, si hacemos esto, básicamente el área negra debería estar oculta o eliminada del SVG. Así que veamos, así es como se ve. Ahora, permítanme agregar el rectángulo de fondo blanco a la máscara. Y cuando lo hago, ven que la flecha es visible porque está rellena de blanco.
15. Enmascarado en SVG y Mejoras de Rendimiento
Para ocultar áreas superpuestas en flechas etiquetadas utilizando enmascarado en SVG, el blanco significa visible o transparente, mientras que el negro elimina el área. Las mejoras de rendimiento incluyen dibujar una sola polilínea en lugar de múltiples líneas y utilizar un lienzo fuera de pantalla para renderizar. Tomar capturas de pantalla con la API Draw Image mejora significativamente la velocidad de renderizado. Se recomienda redondear los valores de carga de trabajo y mover tareas repetitivas a lienzos temporales para optimizar.
El blanco significa visible o transparente. Y si agrego el negro a la región de enmascarado, esa área se elimina. Así es como puedes usar el enmascarado en SVG para ocultar esta área superpuesta cuando se trata de flechas etiquetadas. Y sí, así es como funciona en SVG.
Ahora que hemos cumplido con todos los requisitos, discutamos algunas mejoras de rendimiento que nos gustaría implementar para mejorar esta función y hacerla más rápida. Como ya mencioné, siempre es recomendable dibujar una sola polilínea en lugar de múltiples líneas, especialmente al dibujar flechas multipunto. Deberíamos utilizar un lienzo fuera de pantalla. Lo que quiero decir con lienzo fuera de pantalla es el lienzo que no se renderiza en el DOM. Básicamente, lo utilizas para crear las formas, pero no lo renderizas en el DOM. Es básicamente un lienzo temporal. En lugar de renderizar las formas cada vez, puedes renderizarlas en un lienzo temporal y luego tomar una captura de ese lienzo para el lienzo principal utilizando la API Draw Image.
16. Optimización de Renderizado y Dibujo en Canvas
Al renderizar texto múltiples veces en el lienzo, el uso de la API Draw Image para tomar una captura y copiarla al lienzo principal mejora significativamente el rendimiento. Mover tareas repetitivas a lienzos fuera de pantalla o temporales, redondear los valores de carga de trabajo y renderizar flechas en partes en lugar de usar clear rect también puede mejorar el rendimiento.
Permítanme mostrarles una demostración rápida para esto también. En el lado izquierdo, estoy renderizando el texto múltiples veces. Estoy llamando a la API fill text una y otra vez. Si ven aquí, estoy llamando a draw text, que en realidad llama a la API fill text una y otra vez. En el lado derecho, en realidad estoy usando la API Draw Image. Así que estoy tomando una captura de eso y copiándola al lienzo principal. Por lo tanto, cuando renderizo este texto 100 veces, pueden ver que está dibujando imágenes en 1.3 milisegundos, mientras que cuando se renderiza múltiples veces, tarda 2.3 milisegundos. Hagámoslo 1,000 veces. Es 15.2 veces más rápido, la API Draw Image. Hagámoslo 10,000 veces. Ahora esta diferencia se ve bien. 8.2 milisegundos versus 177 milisegundos, lo cual es enorme. Así que sí, no solo para texto o flechas. Cualquier tarea repetitiva, cuando se trata de lienzo, intenta moverla a un lienzo fuera de pantalla o temporal. Valores de carga de trabajo, porque conduce a un renderizado de píxeles. Esto siempre, como también se menciona en la documentación. Así que siempre intenta redondearlo.
Esto es interesante. Renderizar flechas en partes puede ayudar a mejorar el performance. Lo que quiero decir con renderizar en partes. Dibujo la parte de la flecha antes del texto, luego dibujo el texto y luego dibujo el resto de la flecha. Así que estás dividiendo la tarea en tres pasos en lugar de usar clear rect u otras cosas. Y esto realmente puede mejorar el performance. Permítanme mostrarles rápidamente. El lado izquierdo es con clear rect. Y en el lado derecho, en realidad lo estoy dibujando en partes. Y si ven aquí, en realidad estoy dibujando la primera parte de la flecha, luego el segundo parte de la flecha, la primera parte de la flecha, luego el texto y luego la segunda parte de la flecha. Así que la primera vez, es súper rápido. Hagámoslo durante 100 iteraciones. Son 1.9 milisegundos versus 8.5 milisegundos.
17. Conclusiones y Puntos Clave
Dibujar en partes es más rápido en comparación con clear rect. Clear rect es mucho más rápido que el recorte. Utilice un lienzo fuera de pantalla para dibujar el texto y la flecha. Dibujar una sola polilínea siempre es más eficiente que dibujar múltiples líneas. Evite los valores de punto flotante y redóndelos a enteros. Renderizar flechas etiquetadas en SVG y usar máscaras para eliminar áreas superpuestas. Implementar el dibujo en partes puede ser complejo para diferentes tipos de flechas. Pruébelo y comparta sus comentarios. Apoye al desarrollador independiente de código abierto.
Dibujar en partes es más rápido en comparación con clear rect. 7.7 milisegundos versus 89.2 milisegundos. Nuevamente, esta es una gran mejora. Entonces, sí, esto es algo que realmente puedes probar. Pero al mismo tiempo, esto puede ser complejo de implementar, dependiendo del tipo de flecha, porque tienes que determinar los puntos hasta los cuales debes renderizar y luego renderizar el texto y luego renderizar el resto de la flecha.
Entonces sí, para concluir la charla, veamos las conclusiones, lo que has aprendido hasta ahora. Aprendimos sobre cómo renderizar flechas etiquetadas en Canvas. Canvas no admite varias líneas, por lo que es necesario manejarlo al renderizar texto. Clear rect versus recorte. Clear rect es mucho más rápido que el recorte. Utilice un lienzo fuera de pantalla para dibujar el texto y la flecha, o cualquier tarea repetitiva, y copie al lienzo principal. Dibujar una sola polilínea siempre es más eficiente que dibujar múltiples líneas. Evite los valores de punto flotante y redóndelos a enteros para evitar algunos problemas de renderizado de píxeles. También aprendimos sobre flechas etiquetadas, cómo renderizarlas en SVG y usar máscaras para eliminar el área superpuesta. Y sí, dibujar flechas en partes es rápido en comparación con clear rect, pero puede resultar mucho más complejo cuando se trata de la implementación. No hacemos esto en Excalator, pero podríamos hacer parte de esto para flechas de dos puntas.
Entonces sí, con esto, estas son todas las demostraciones. Si quieres probarlo en tu máquina y compartir cómo funciona para ti, porque cada navegador de dispositivo tendrá diferentes requisitos, por lo que podría cambiar. Pero si quieres probarlo, puedes escanear este código QR code y probarlo. Y sí, estas son mis redes sociales nuevamente. Y sí, por último, soy un desarrollador independiente de código abierto, así que por favor apóyame para que pueda seguir contribuyendo al código abierto. Eso es todo de mi parte. Nuevamente, terminando con el tema del ciclo. Entonces sí, muchas gracias. Gracias a los organizadores por tenerme aquí, y sí, si tienen alguna pregunta o algún comentario, háganmelo saber. No creo que tenga tiempo para preguntas, pero podemos hablar fuera de aquí. ¿Sí? De acuerdo, gracias.
Comments