Pregunta

Cualquier sugerencia es muy apreciada.

¿Fue útil?

Solución

La selección de texto tiene muchos componentes, algunos visuales y otros no visuales.

Primero, para hacer que el texto sea seleccionable, debe mantener una matriz que indique dónde está el texto, qué es el texto y qué fuente se utilizó.Utilizará esta información con la función Canvas MeasureText.

Al usar MeasureText, con su cadena de texto, puede identificar en qué letra debe aterrizar el cursor cuando hace clic en una imagen.

ctx.fillText("My String", 100, 100);
textWidth = ctx.measureText("My String").width;

Todavía tendrá que analizar la altura de la fuente de la propiedad "fuente", ya que actualmente no está incluida en las métricas de texto.El texto del lienzo está alineado con la línea de base de forma predeterminada.

Con esta información, ahora tiene un cuadro delimitador que puede comparar.Si el cursor está dentro del cuadro delimitador, ahora tiene la desafortunada tarea de deducir qué letra fue seleccionada intencionalmente;donde debe colocarse el inicio del cursor.Esto puede implicar llamar a MeasureText varias veces.

En ese momento sabes dónde debe ir el cursor;Deberá almacenar su cadena de texto como una cadena de texto, en una variable, por supuesto.

Una vez que haya definido los puntos de inicio y parada de su rango, debe dibujar un indicador de selección.Esto se puede hacer en una nueva capa (un segundo elemento de lienzo), o dibujando un rectángulo usando el modo de composición XOR.También se puede hacer simplemente limpiando y redibujando el texto sobre un rectángulo relleno.

En total, la selección y edición de texto en Canvas son bastante laboriosas de programar, y sería prudente reutilizar componentes ya escritos, siendo Bespin un excelente ejemplo.

Editaré mi publicación si encuentro otros ejemplos públicos.Creo que Bespin utiliza un método de selección basado en cuadrículas, que posiblemente requiera una fuente monoespaciada.Las ligaduras, el interletraje, la bidireccionalidad y otras funciones avanzadas de representación de fuentes requieren programación adicional;es un problema complejo.

Otros consejos

el texto dibujado en elementos de lona no se pueden seleccionar, a causa de la naturaleza de la etiqueta de la lona. Sin embargo, hay algunas soluciones, como el usado en typefaceJS .

Otra solución sería añadir texto con elementos div posicionado en lugar de useing strokeText o fillText.

Si es necesario tener texto seleccionable que sería mucho más fácil simplemente crear un div o lo que sea, y la posición en la parte superior de la tela en la que desea el texto para mostrar.

tela no tiene ningún mecanismo incorporado para la selección de texto, por lo que tendría que lanzar su propia representación de texto y el código de selección -. Que puede ser bastante difícil de conseguir la derecha

Es posible obtener algunas ideas de Bespin .

Se implementan un editor de texto en JavaScript utilizando lienzo con la selección de texto , barras de desplazamiento, cursor parpadeante, etc.

Código Fuente

Se recomienda usar la biblioteca EaselJS , puede agregar cada letra como un niño e incluso añadir eventos de ratón a ese objeto, su una biblioteca increíble, ir a verlo!

controles TextInput se complican

Permítanme comenzar diciendo que no soy un experto en controles de texto, pero por ahora estoy seguro de que esto no importa, porque yo puedo ayudarle a entrar en el bosque y en condiciones de seguridad. Estas cosas son complicadas en la naturaleza y requieren mucha intuición y el conocimiento de cómo funcionan las cosas. Sin embargo, puede inspeccionar el código que se ejecuta en el repositorio senpai-js/senpai-stage aquí .

Hay que definir algunas cosas por adelantado:

  • El texto puede ser cualquier carácter Unicode válida. Se puede analizar que el uso de este de expresiones regulares: /^.$/u
  • Es necesario hacer un seguimiento de tres diferentes tipos de modos de edición de texto: Insert, Selection, Basic (utilizo la enumeración SelectionState en mi biblioteca y examine la propiedad insertMode en el escenario)
  • Usted debe implementar comprobaciones de validez en todo momento, o que tendrá un comportamiento indefinido e inesperado
  • La mayoría de las personas esperan entradas de texto a ser considerable por el ancho, por lo que asegúrese de usar un patrón para las entrañas del cuadro de texto si usted planea usar una textura
  • / detección táctil punto de colisión ratón es complicada a menos que se garantiza que el control de entrada de texto no girará
  • El texto debe desplazarse cuando es más grande que el cuadro de texto en la dirección horizontal. Nos referiremos a esto como textScroll que siempre es un número negativo

Ahora voy a repasar cada función para describir su comportamiento para describir exactamente cómo un control de cuadro de texto debería funcionar.

Collision (broadPhase, y narrowPhase)

La detección de colisiones es un monstruo. movimiento del punto normalizador entre los eventos de ratón y el tacto es una bestia complicada no se tratan en este texto. Una vez que manejar eventos de punto, usted tiene que realizar algún tipo de detección de colisión en general para un rectángulo. Esto significa hacer AABB colisión. Si el propio sprite de cuadro de texto se gira, que tendrá que "des-rotación" el punto en sí. Sin embargo, nosotros por esta comprobación si el puntero del ratón / touch ya está abajo sobre el cuadro de texto. Esto se debe a que una vez que comience la selección de texto, desea esta función para volver siempre true. A continuación, pasamos a narrowPhase colisión, que en realidad se comprueba para ver si el punto de ratón / tacto "no-transformado" se encuentra dentro del relleno del cuadro de texto. Si lo es, o el cuadro de texto está activo, volvemos un valor Truthy aquí.

Una vez que sabemos que el punto de ratón / táctil está dentro de los límites de nuestra caja de texto, podemos cambiar el css de la lona para cursor: text; visualmente.

pointCollision

Al pulsar el botón del ratón sobre el cuadro de texto, tenemos que calcular dónde mover el cursor. El símbolo de intercalación puede existir en un intervalo de 0 a text.length inclusive. Tenga en cuenta que esto no es exactamente correcto ya que los caracteres Unicode puede tener una longitud de 2. Usted debe hacer un seguimiento de cada personaje añadido a su texto dentro de una matriz para afirmar que no se está midiendo caracteres Unicode defectuosos. Cálculo del índice de medios de blanco bucle sobre cada carácter del texto actual y añadiendo a una cadena temporal, midiendo cada vez hasta que la anchura medida es mayor que el textScroll actual + la textWidth medido.

Una vez que hemos garunteed que el punto se ha reducido en la parte superior del cuadro de texto y el punto de partida se fija, se puede iniciar el modo de "selección". Arrastrando el punto debe mover la selección del caretIndex de partida hasta el nuevo índice final calculado. Esto va en ambas direcciones.

se muestra un ejemplo de esta aquí .

pulsaciones de teclas

La solución de pulsaciones de teclas web es inspeccionar la propiedad key en el KeyEvent. A pesar de mucho de lo que dice todo el mundo, es posible para probar que la propiedad de texto para ello, contra la expresión regular Unicode antes mencionado. Si coincide, lo más probable es que la clave de hecho se ha pulsado en el teclado. Esto no tiene en cuenta las combinaciones de teclas como ctrl + c y ctrl + v para copiar y pegar. Estas características son triviales y se dejan al lector para decidir cómo poner en práctica estos.

Las pocas excepciones son las teclas de dirección: "arrowleft", "ArrowRight", etc. Estas teclas realidad modifican el estado de su control, y cambiar la forma en que funciona. Es importante recordar que los eventos clave deben ser manejados solamente por el control actualmente focused. Esto significa que debe comprobar y asegurarse de que el control se centra en la introducción de texto. Por supuesto, esto sucede en un nivel más alto que he codificado en mi biblioteca, así que esto es trivial.

El siguiente problema que necesita ser resuelto es cómo cada entrada de caracteres debe modificar el estado de su control. El método keyDown discierne la selectionState y llama a una función diferente en función de su estado. Esto no está optimizado pseudo-código, pero se utiliza para mayor claridad, y es perfecto para nuestros propósitos en la descripción del comportamiento.

keydown en una selección

  • pulsaciones de teclas normales reemplazan el contenido del texto seleccionado
  • Empalme hacia fuera de selectionStart, e insertar la nueva clave en la matriz de texto
  • Si se pulsa "eliminar" o "retroceso", empalmar a cabo la selección y volver al modo de selección de Normal o Caret
  • Si se pulsa la tecla "izquierda" o "derecha", mueva el cursor al principio o al final, respectivamente, y volver al modo de selección de normal a menos que se pulse la tecla de mayúsculas
  • Si se pulsa la tecla de mayúsculas, a continuación, que en realidad queremos extender más la selección
    • inicio de la selección será siempre en el caretIndex, y esencialmente mover el punto final de la selección hacia la izquierda o derecha con esta combinación de teclas
    • Si la selección final regresa de nuevo al índice de intercalación, volvemos a la selectionState Normal nuevo
  • las teclas de "extremo" "casa" y funcionan de la misma manera, sólo el cursor se mueve a 0 y los índices text.length respectivamente
    • también en cuenta que mantiene pulsada la tecla de mayúsculas se extiende desde la selección caretIndex una vez más

keydown en el modo (modo de intercalación) normales

  • en el modo de intercalación, no reemplazamos cualquier texto, basta con insertar nuevos caracteres en la posición actual
  • keydowns que coincidan con la expresión regular Unicode se insertan utilizando el método de empalme
  • mover el cursor hacia la derecha después de empalmar el texto (comprobar y asegurarse de que no pasen por encima longitud del texto)
  • Retroceso elimina un carácter antes del índice en caretIndex - 1
  • Eliminar elimina un carácter después de que el índice en caretIndex
  • selección de texto se aplica para las teclas izquierda y derecha mientras se pulsa la tecla de mayúsculas
  • al cambio no se presiona, la izquierda y la derecha se mueve el cursor hacia la izquierda y derecha, respectivamente
  • la tecla de inicio establece el caretIndex a 0
  • la tecla de finalización establece el caretIndex a text.length

keyDown en modo de inserción

  • en el modo de inserción, reemplazamos el carácter seleccionado en ese momento en caretIndex
  • keydowns que coincidan con la expresión regular Unicode se insertan utilizando el método de empalme
  • mover el cursor hacia la derecha después de empalmar el texto (comprobar y asegurarse de que no pasen por encima longitud del texto)
  • el retroceso eliminar el carácter anterior al actual selección
  • Eliminar quita el carácter seleccionado en ese momento
  • las teclas de flecha funcionar como se espera y se describe en el modo normal
  • teclas
  • el inicio y fin funcionan como se esperaba y se describe en el modo normal

actualizar el cuadro de texto cada cuadro

  • Si el cuadro de texto se centra, usted debe stel arte de parpadear el símbolo de intercalación para que el usuario sepa que está editando el texto en el cuadro de texto
  • cuando se mueve el cursor hacia la izquierda o la derecha en el modo Caret, debe reiniciar el mecanismo de flash para que muestre exactamente dónde están cada vez el cursor se mueve
  • Flash el cursor alrededor de una vez cada 30 tramas, o la mitad de un segundo
  • medir hasta qué punto el símbolo de intercalación es a lo largo del texto utilizando ctx.measureText al índice de símbolo de intercalación por corte el texto a la posición de intercalación menos que el modo es Selection
  • Es todavía útil para medir hasta qué punto a lo largo del texto se encuentra en Selection modo de selección, ya que la idea final de la selección de texto para que sea visible para el usuario
  • Asegúrese de que el cursor está siempre visible dentro de los límites visibles de la caja de texto, teniendo en cuenta la actual textScroll

haciendo que el cuadro de texto

  • guardar el contexto primera ctx.save() (tela básica)
  • Si no está dibujando el cuadro de texto con las rutas, dibujar la tapa izquierda del cuadro de texto, dibujar el patrón de media, y la tapa de la derecha, respectivamente, sobre la primera capa
  • utilizar una trayectoria definida por el relleno y el tamaño de la caja de texto para recortar un cuadrado para evitar que el texto de sangrado fuera
  • traducir al valor textScroll x que debe ser un número negativo
  • traducir al valor midline y que debe ser la mitad de la caja de texto verticalmente
  • establecer la propiedad de fuente
  • establecer la línea base del texto a middle y llenar el texto llamando text.join("") en la matriz de texto
  • Si hay una selección, o el modo de inserción, asegúrese de dibujar un cuadrado "azul" detrás del texto seleccionado e invertir el color de fuente del texto seleccionado (esto no es trivial y deja al lector como ejercicio)

Notas finales

Si la tarea es enorme, pero a veces sólo quiere dar al mundo un motor de novela visual, o una etapa del sprite con todo tipo de características. Por favor, visite el repositorio senpai-stage y presentar una solicitud de extracción si siente que quiere senpai de aviso usted. Buena suerte en sus esfuerzos!

~ diablo senpai

FabricJS ahora tiene la capacidad de interactuar con objetos fuera del elemento canvas - por ejemplo, esta demo muestra un botón que está vinculado a una imagen cargada en un elemento de la lona.

El mismo enfoque se puede utilizar en otros libs tales como Raphael enganchando cualquier caso movimiento, para obtener el cuadro delimitador del elemento y re-posicionar el elemento HTML.

tela es sólo una superficie de dibujo. Rindes y el resultado es píxeles. Por lo tanto, lo que se necesita para realizar un seguimiento de las posiciones de todos los textos que ha prestado a la lona en una cierta clase de estructura de datos que desea procesar durante los eventos del ratón.

Una respuesta simple sería: o bien el uso de HTML o SVG en lugar de lienzo. A menos que realmente necesita el grado de ofertas de lona de control de bajo nivel.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top