Pregunta

Esto es un tiro largo, pero ¿alguien sabe de un algoritmo para estimar y categorizar el ancho del texto (para una fuente de ancho variable) basado en su contenido?

Por ejemplo, me gustaría saber que iiiiiiii no es tan ancho como abcdefgh , que a su vez no es tan ancho como WWWWWWWWW , aunque las tres cadenas tienen ocho caracteres de longitud.

En realidad, se trata de un intento de incorporar algunas inteligencias en un método de truncamiento de cadena, que en este momento está truncando correctamente una cadena visualmente ancha, pero también está truncando innecesariamente una cadena visualmente estrecha, porque ambas cadenas contienen el mismo número de caracteres. Probablemente sea suficiente para que el algoritmo clasifique la cadena de entrada como estrecho , normal o ancho y luego trunque según corresponda.

Esta pregunta no es realmente específica del idioma, pero si hay un algoritmo, lo implementaré en Java. Esto es para una aplicación web. Soy consciente de que hay respuestas en SO que tratan este problema utilizando JavaScript para obtener el ancho de un elemento div que contiene, pero me pregunté si es posible una solución del lado del servidor.

¿Fue útil?

Solución

La mayoría de los marcos de GUI proporcionan alguna forma de calcular las métricas de texto para las fuentes en dispositivos de salida dados.

Usando java.awt.FontMetrics , por ejemplo, creo que puedes hacer esto:

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics; 

public int measureText(Graphics g, String text) {
   g.setFont(new Font("TimesRoman", Font.PLAIN, 12));
   FontMetrics metrics = g.getFontMetrics();

   return metrics.stringWidth(text);
}

No probado, pero entiendes la idea.


Debajo de .Net puede usar Graphics .MeasureString método. En C #:

private void MeasureStringMin(PaintEventArgs e)
{

    // Set up string.
    string measureString = "Measure String";
    Font stringFont = new Font("Arial", 16);

    // Measure string.
    SizeF stringSize = new SizeF();
    stringSize = e.Graphics.MeasureString(measureString, stringFont);

    // Draw rectangle representing size of string.
    e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);

    // Draw string to screen.
    e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0));
}

Otros consejos

Esto me funcionó:

AffineTransform af = new AffineTransform();     
FontRenderContext fr = new FontRenderContext(af,true,true);     
Font f = new Font("Arial", 0, 10); // use exact font
double width= f.getStringBounds("my string", fr).getWidth();      

Para una aplicación web, no puede (realmente) obtener una estimación adecuada. Las diferentes fuentes tienen diferentes anchos, de modo que esto no solo depende del cliente (navegador) y su configuración de zoom y DPI, sino también de las fuentes presentes en esa máquina (y sistema operativo) o sus sustituciones.

Si necesita una medición exacta, cree un gráfico (mapa de bits, SVG o incluso algún PDF o lo que sea) que se diseñará y representará en el servidor y no en el cliente.

No existe una solución confiable del lado del servidor para calcular el ancho del texto. (aparte de crear una imagen del texto y probablemente SVG)

Si prueba una herramienta como tomas de navegador y la ejecuta en páginas relativamente básicas, inmediatamente ver por qué. Es difícil predecir qué tan amplios resultarán incluso los ejemplos más mundanos, y mucho menos si un usuario decide ampliar el navegador, etc ...

No se indica con precisión, es posible que desee truncar la cadena (podría ser útil para ofrecer posibles soluciones), pero una común es porque desea cortar el texto en algún momento y proporcionar una elipse.

Esto se puede hacer de manera confiable en muchas plataformas de navegador usando una propiedad css, y NO javascript:

http://www.jide.fr/emulate -text-overflowellipsis-in-firefox-with-css

Realmente no tiene forma de saber qué navegador, configuración de fuente, tamaño de pantalla, etc. está usando el cliente. (De acuerdo, a veces los encabezados de solicitud proporcionan una indicación, pero en realidad no son consistentes ni confiables).

Por lo tanto, yo:

  • muestra un texto de muestra en Internet Explorer con la configuración predeterminada en un tamaño de pantalla / ventana de 1024x768 (generalmente es el tamaño más común)
  • tome una línea / caracteres promedio con esta configuración y úselo para su estimación.

Por lo general, he encontrado esto " lo suficientemente bueno " ;, por ejemplo, para estimar el número de líneas que un texto tomará en un navegador, para estimar cuántos anuncios se mostrarán al lado del texto.

Si realmente fue crucial para ti, entonces puedo imaginar un esquema complejo en el que inicialmente envías algo de Javascript al cliente, que luego toma una medida y la envía de vuelta a tu servidor, y luego utilizas esta información para el futuro. Páginas para ese cliente. Sin embargo, no puedo imaginar que valga la pena el esfuerzo.

Creo que deberías elegir una de estas soluciones:

  • Solución exacta: sume el ancho de cada carácter de la cadena (la mayoría de las API le proporcionarán esta información)
  • Estimación rápida: tome el ancho máximo o el mínimo y multiplíquelo por la cantidad de caracteres.

Por supuesto, es posible realizar una estimación mixta, pero creo que esto es demasiado esfuerzo en la dirección equivocada.

Para una buena solución del lado del cliente *, puede probar un enfoque híbrido de CSS y Javascript como lo sugiere La respuesta de RichieHindle a mi pregunta .

Dado que no sabe en qué fuente verá la página el usuario (siempre pueden anular su selección, Ctrl- + la página, etc.), " derecha " el lugar para hacer esto está en el navegador ... ¡aunque los navegadores no lo hacen fácil!

* cuando digo " nice " ;, me refiero a " probablemente nice pero no lo he probado todavía " ;.

  

En realidad, se trata de un intento de incorporar algunas inteligencias en un método de truncamiento de cadenas [...]

¿Realmente vale la pena el esfuerzo? Tuvimos este problema exacto Y esto fue en todos los idiomas. La solución fue dejarlo como está. La complejidad de mantener esta inteligencia aumenta rápidamente (y probablemente de manera exponencial) con cada idioma para el que agrega soporte. De ahí nuestra decisión.

  ¿

[...] un algoritmo para estimar y categorizar el ancho del texto (para una fuente de ancho variable) basado en su contenido?

La mayoría de las bibliotecas de fuentes te darán esta información. Pero esto es algo bastante bajo nivel. La idea básica es pasar una cadena y recuperar el ancho en puntos.

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