Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

212
Visualizações
Anchura precisa de un carácter monoespaciado

Estoy trabajando en un editor de código con resaltado de sintaxis y necesito saber el ancho exacto de un carácter monoespaciado. Utilizo este valor para calcular la posición de un carácter en una línea, que necesito saber para poder colocar varios elementos de la GUI, como cursores de texto (puede haber varios), rectángulos de selección, información sobre herramientas de advertencia, etc. Hasta ahora He estado usando la siguiente función:

 function getCharacterWidth(char, fontFamily, fontSize) { let span = document.createElement("span"); span.style.fontFamily = fontFamily; span.style.fontSize = fontSize; span.style.position = "absolute"; span.style.visibility = "hidden"; span.style.width = "auto"; span.style.whiteSpace = "nowrap"; span.style.padding = "0"; span.style.margin = "0"; span.style.letterSpacing = "0px"; span.style.wordSpacing = "0px"; span.innerText = char; document.body.appendChild(span); let width = span.getBoundingClientRect().width; span.remove(); return width; }

Ha estado funcionando muy bien, pero luego noté un problema en Google Chrome. Cuando mi editor de texto representa una línea grande, con miles de caracteres, la posición del carácter no se calcula correctamente debido a problemas de redondeo. Parece que en Google Chrome, el width devuelto por getBoundingClientRect() tiene una precisión de 5 decimales como máximo, lo que no es ideal para mi caso de uso. En Firefox, la precisión parece ser mucho mayor, llegando a 15 decimales, por lo que nunca tuve este problema allí.

Después de investigar un poco, escuché sobre esta idea de calcular el ancho de un carácter en función del ancho de un lapso que contiene miles de ese carácter ( https://stackoverflow.com/a/56379770/2197150 ). Entonces, en mi función original, reemplacé span.innerText = char con span.innerText = char.repeat(10000) y devolví width / 10000 . Ayudó, pero el cálculo sigue siendo perceptiblemente incorrecto cuando trato con líneas grandes.

Así que aquí estoy. ¿Cómo puedo calcular el ancho de un carácter con alta precisión, como lo hace Firefox, en otros navegadores?

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

Esta no es una solución limpia, pero sospecho que no hay una solución realmente limpia.

Puede mantener un "mapa de columnas", basado en el formato de sintaxis <span> s que ya tiene volando. Digamos que tu resaltador te da:

 <div class="line"> var long_line_of_variables = <span class="number">123</span>; </div>

podría medir el desplazamiento izquierdo de este lapso + la columna en la que aparece (= longitud del contenido de texto de los hermanos anteriores = 29) y llegar a

 colums = { '29': 290.456 }

Ahora puede interpolar que la columna 14 tiene 290.456*14/29=140.22 píxeles.
Cuantos más intervalos agreguemos, mejor podremos adivinar:

 colums = { '29': 290.456, '2900': 28997.000 // whoops, not what we would have calculated! }

Este método es heurístico, por lo que deberá encontrar una estrategia que funcione en todos los navegadores, ajustes de zoom/escala de fuente, etc., incluidos

  • agregando más y más tramos a este "mapa"
  • pero tal vez "limpiándolo" de vez en cuando?
  • mantener un mapa global o uno por línea ?
  • sea inteligente con la interpolación: elija la entrada de mapa más cercana (en el mejor intervalo entre entradas)
  • agregar más "sondas de alcance"
    • dividir líneas largas sin ningún formato en fragmentos de N caracteres, envolviéndolos en intervalos o insertando intervalos vacíos en el medio
    • ¿tal vez solo un tramo de sonda justo al final de cada línea?

Habiendo trabajado en problemas y heurísticas similares, mi consejo sería: no lo hagas. :)
Implica muchos ajustes y pruebas, y probablemente sea una pesadilla multiplataforma (por ejemplo, compare la representación y el redondeo de fuentes en Firefox en Win vs Linux vs MacOS vs iOS). En su lugar, intente adjuntar cualquier cosa a un tramo localizado. Entiendo que esto probablemente sea mucho más difícil: muchos editores de texto luchan con líneas largas, especialmente. cuando se trata de JS compilado de tamaño MB ...

about 4 years ago · Juan Pablo Isaza Relatório

0

Se me ocurrió una solución que ha funcionado bien para mi caso de uso . La idea es calcular el ancho de un carácter en función de la línea más grande de mi editor. Mis elementos de línea se ven así:

 <div class="line"><span class="keyword">let</span><span class="space"> </span><span class="identifier">foo</span></div>

Si queremos calcular el ancho de un carácter basado en esa línea, esto es lo que hacemos:

 let lineElement = document.querySelector(".line"); let lineWidth = lineElement.getBoundingClientRect().width; let charWidth = lineWidth / lineElement.textContent.length;

Hago un seguimiento de la línea más grande que he renderizado en mi editor. Cada vez que represento una nueva línea más grande, actualizo charWidth en función de esa nueva línea.

Esto me permite calcular la posición de un carácter en cualquier columna dada dentro de una línea haciendo una simple column * charWidth . Ha estado funcionando bastante bien hasta ahora, incluso para líneas con más de 100000 caracteres.

Sin embargo, hay una última cosa que tuve que hacer para manejar líneas aún más grandes. Parece que hay un error en Google Chrome donde, cuando intenta representar una línea con un nodo de texto enorme, por ejemplo, <span>many many characters...</span> , no le dará el ancho correcto del elemento (ver Ancho inexacto de elemento grande en Chrome ). Para superar este problema, cada vez que tengo que representar un texto enorme, lo divido en varios tramos, por ejemplo, <span>many many </span><span>characters...</span> .

Ahora puedo renderizar líneas largas de 500000 caracteres con tamaño de fuente 48 sin problemas. Por encima de eso, las cosas vuelven a ponerse raras, con errores de cálculo y otros comportamientos extraños del navegador. Así que decidí establecer un límite estricto de 500000 caracteres representados en una línea. Todo más allá de los 500000n caracteres está oculto para el usuario.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda