Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

289
Vistas
Cómo usar en un lienzo un elemento de texto con una fuente descrita en CSS

Esto está dentro del proyecto Bismon (un software GPLv3+ financiado por proyectos europeos H2020), git commit 0e9a8eccc2976f . Este borrador de informe describe el software. Esta pregunta da más contexto y motivaciones. Se trata del archivo (escrito a mano) webroot/jscript/bismon-hwroot.js , utilizado en alguna página HTML cuyo código es generado por Bismon (un servidor web especializado por encima de libonion ).

Agregué alguna clase de CSS para span, por ejemplo, span.bmcl_evalprompt (por ejemplo, en mi archivo first-theme.css ).

¿Cómo codifico JavaScript para agregar una pieza de texto en un lienzo (preferiblemente usando jcanvas con jquery) que tenga el mismo estilo (misma fuente, color, etc.) que span.bmcl_evalprompt ? ¿Necesito crear un elemento de intervalo de este tipo en mi DOM? ¿Es eso simplemente posible?

Solo me importa un Firefox reciente (68 al menos) en Linux. JQuery es 3.4. También estoy usando Jquery UI 1.12.1

La idea que tenía en mente era crear un solo elemento <span class='bmcl_evalprompt'> con coordenadas lejos de la ventana del navegador (o ventana X11), por ejemplo, en x= -10000 e y= -10000 (en píxeles) , luego agregue ese único elemento mal posicionado en el DOM del documento, luego use las técnicas tradicionales de Jquery para obtener la familia de fuentes, el tamaño de fuente y el tamaño del elemento. Pero, ¿hay alguna manera mejor? ¿O alguna biblioteca compatible con Jquery haciendo eso?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Si simplemente desea representar el texto de su intervalo en un lienzo, puede acceder a los atributos de estilo mediante la función window.getComputedStyle . Para hacer que el intervalo original sea invisible, configure su estilo para que se display: none .

 // get the span element const span = document.getElementsByClassName('bmcl_evalprompt')[0]; // get the relevant style properties const font = window.getComputedStyle(span).font; const color = window.getComputedStyle(span).color; // get the element's text (if necessary) const text = span.innerHTML; // get the canvas element const canvas = document.getElementById('canvas'); // set the canvas styling const ctx = canvas.getContext('2d'); ctx.font = font; ctx.fillStyle = color; // print the span's content with correct styling ctx.fillText(text, 35, 110);
 #canvas { width: 300px; height: 200px; background: lightgrey; } span.bmcl_evalprompt { display: none; // makes the span invisible font-family: monospace; // change this value to see the difference font-size: 32px; // change this value to see the difference color: rebeccapurple; // change this value to see the difference }
 <span class="bmcl_evalprompt">Hello World!</span> <canvas id="canvas" width="300" height="200"></canvas>

over 4 years ago · Santiago Trujillo Denunciar

0

¿Coincide la fuente DOM en el lienzo?

La respuesta simple es: "¡¡Muy difícil!!" y "Nunca será perfecto".

Lo mejor que puede hacer es una aproximación que se encuentra en el ejemplo en la parte inferior de la respuesta, que también mostrará que la coincidencia del estilo visible no está relacionada con la calidad visible.

Extendiendo desde solo reglas CSS.

Si desea que la fuente coincida lo más posible con el elemento, existen algunas preocupaciones adicionales además de obtener el CSS como se indica en la respuesta de Spark Fountain .

Tamaño de fuente y tamaño de píxeles CSS

  • El tamaño de fuente está relacionado con el tamaño de píxel de CSS. El HTMLCanvasElement

  • El tamaño de píxel de CSS no siempre coincide con los píxeles de visualización del dispositivo. Por ejemplo, pantallas HiDPI/Retina. Puede acceder a la proporción de píxeles CSS del dispositivo a travésdevicePixelRatio

  • El tamaño de píxel de CSS no es una constante y puede cambiar por muchas razones. Los cambios se pueden monitorear a través de MediaQueryListEvent y escuchar el evento de change

  • Los elementos se pueden transformar. CanvasRenderingContext2D no puede hacer transformaciones 3D, por lo tanto, si el elemento o el lienzo tiene una transformación 3D, no podrá hacer coincidir la fuente renderizada del lienzo con la fuente renderizada de los elementos.

  • La resolución del lienzo y el tamaño de la pantalla son independientes.

    • Puede obtener la resolución del lienzo a través de las propiedades HTMLCanvasElement.width y HTMLCanvasElement.height
    • Puede obtener el tamaño de visualización del lienzo a través de las propiedades de estilo ancho y alto, o mediante una variedad de otros métodos, consulte el ejemplo.
    • El aspecto de píxel del lienzo puede no coincidir con el aspecto de píxel de CSS y debe calcularse al representar la fuente en el lienzo.
    • La representación de fuentes de lienzo en tamaños de fuente pequeños es terrible. Por ejemplo, una fuente de 4 píxeles representada en un tamaño de 16 píxeles es ilegible. ctx.font = "4px arial"; ctx.scale(4,4); ctx.fillText("Hello pixels"); Debe usar un tamaño de fuente fijo que tenga resultados de renderizado de lienzo de buena calidad y escalar el renderizado hacia abajo cuando use fuentes pequeñas.

Color de fuente

El estilo de color de los elementos solo representa el color renderizado. No representa el color real visto por el usuario.

Como esto se aplica tanto al lienzo como al elemento del que obtiene el color y a cualquier elemento que se coloque por encima o por debajo, la cantidad de trabajo necesaria para hacer coincidir visualmente el color es enorme y va mucho más allá del alcance de una respuesta de desbordamiento de pila (las respuestas tienen un longitud máxima de 30K)

Representación de fuentes

El motor de representación de fuentes del lienzo es diferente al del DOM. El DOM puede usar una variedad de técnicas de representación para mejorar la calidad aparente de las fuentes aprovechando la forma en que se organizan los subpíxeles RGB físicos de los dispositivos. Por ejemplo, las fuentes TrueType y las sugerencias relacionadas utilizadas por el renderizador, y el subpíxel ClearType derivado con representación de sugerencias.

Estos métodos de representación de fuentes PUEDEN coincidir en el lienzo , aunque para la coincidencia en tiempo real tendrá que usar WebGL.

El problema es que la representación de fuentes DOM está determinada por muchos factores, incluida la configuración de los navegadores. JavaScript no puede acceder a la información necesaria para determinar cómo se representa la fuente. En el mejor de los casos, puede hacer una conjetura informada.

Otras complicaciones

También hay otros factores que afectan la fuente y cómo las reglas de estilo de fuente CSS se relacionan con el resultado visual de la fuente mostrada. Por ejemplo, unidades CSS, animación, alineación, dirección, transformaciones de fuentes y modo peculiar.

Personalmente para renderizado y color no me molesto. Eventualmente, si escribí un motor de fuente completo usando WebGL para que coincida con cada variante de fuente, filtrado, composición y representación, no son parte del estándar y, por lo tanto, están sujetos a cambios sin previo aviso. Por lo tanto, el proyecto siempre estaría abierto y podría fallar en cualquier momento al nivel de resultados ilegibles. Simplemente no vale la pena el esfuerzo.


Ejemplo

El ejemplo tiene un lienzo de representación a la izquierda. La parte superior central del texto y la fuente. Una vista ampliada a la derecha, que muestra una vista ampliada del lienzo izquierdo

El primer estilo utilizado es el predeterminado de las páginas. La resolución del lienzo es de 300 por 150, pero está escalada para ajustarse a 500 por 500 píxeles CSS. Esto da como resultado un texto de lienzo de MUY mala calidad. El ciclo de la resolución del lienzo mostrará cómo el lienzo afecta la calidad.

Las funciones

  • drawText(text, x, y, fontCSS, sizeCSSpx, colorStyleCSS) dibuja el texto usando valores de propiedad CSS. Escalar la fuente para que coincida con el tamaño visual DOM y la relación de aspecto lo más cerca posible.

  • getFontStyle(element) devuelve los estilos de fuente necesarios como un objeto del element

Uso de la interfaz de usuario

  • HAGA CLIC en el centro de la fuente para cambiar los estilos de fuente.

  • HAGA CLIC en el lienzo izquierdo para alternar las resoluciones del lienzo.

  • En la parte inferior está la configuración utilizada para representar el texto en el lienzo.

Verá que la calidad del texto depende de la resolución del lienzo.

Para ver cómo el zoom DOM afecta la representación, debe acercar o alejar la página. Las pantallas HiDPI y retina tendrán un texto de lienzo de calidad mucho menor debido al hecho de que el lienzo tiene la mitad de la resolución de los píxeles CSS.

 const ZOOM_SIZE = 16; canvas1.width = ZOOM_SIZE; canvas1.height = ZOOM_SIZE; const ctx = canvas.getContext("2d"); const ctx1 = canvas1.getContext("2d"); const mouse = {x:0, y:0}; const CANVAS_FONT_BASE_SIZE = 32; // the size used to render the canvas font. const TEXT_ROWS = 12; var currentFontClass = 0; const fontClasses = "fontA,fontB,fontC,fontD".split(","); const canvasResolutions = [[canvas.scrollWidth, canvas.scrollHeight],[300,150],[200,600],[600,600],[1200,1200],[canvas.scrollWidth * devicePixelRatio, canvas.scrollHeight * devicePixelRatio]]; var currentCanvasRes = canvasResolutions.length - 1; var updateText = true; var updating = false; setTimeout(updateDisplay, 0, true); function drawText(text, x, y, fontCSS, sizeCSSpx, colorStyleCSS) { // Using px as the CSS size unit ctx.save(); // Set canvas state to default ctx.globalAlpha = 1; ctx.filter = "none"; ctx.globalCompositeOperation = "source-over"; const pxSize = Number(sizeCSSpx.toString().trim().replace(/[az]/gi,"")) * devicePixelRatio; const canvasDisplayWidthCSSpx = ctx.canvas.scrollWidth; // these are integers const canvasDisplayHeightCSSpx = ctx.canvas.scrollHeight; const canvasResWidth = ctx.canvas.width; const canvasResHeight = ctx.canvas.height; const scaleX = canvasResWidth / (canvasDisplayWidthCSSpx * devicePixelRatio); const scaleY = canvasResHeight / (canvasDisplayHeightCSSpx * devicePixelRatio); const fontScale = pxSize / CANVAS_FONT_BASE_SIZE ctx.setTransform(scaleX * fontScale, 0, 0, scaleY * fontScale, x, y); // scale and position rendering ctx.font = CANVAS_FONT_BASE_SIZE + "px " + fontCSS; ctx.textBaseline = "hanging"; ctx.fillStyle = colorStyleCSS; ctx.fillText(text, 0, 0); ctx.restore(); } function getFontStyle(element) { const style = getComputedStyle(element); const color = style.color; const family = style.fontFamily; const size = style.fontSize; styleView.textContent = `Family: ${family} Size: ${size} Color: ${color} Canvas Resolution: ${canvas.width}px by ${canvas.height}px Canvas CSS size 500px by 500px CSS pixel: ${devicePixelRatio} to 1 device pixels` return {color, family, size}; } function drawZoomView(x, y) { ctx1.clearRect(0, 0, ctx1.canvas.width, ctx1.canvas.height); //x -= ZOOM_SIZE / 2; //y -= ZOOM_SIZE / 2; const canvasDisplayWidthCSSpx = ctx.canvas.scrollWidth; // these are integers const canvasDisplayHeightCSSpx = ctx.canvas.scrollHeight; const canvasResWidth = ctx.canvas.width; const canvasResHeight = ctx.canvas.height; const scaleX = canvasResWidth / (canvasDisplayWidthCSSpx * devicePixelRatio); const scaleY = canvasResHeight / (canvasDisplayHeightCSSpx * devicePixelRatio); x *= scaleX; y *= scaleY; x -= ZOOM_SIZE / 2; y -= ZOOM_SIZE / 2; ctx1.drawImage(ctx.canvas, -x, -y); } displayFont.addEventListener("click", changeFontClass); function changeFontClass() { currentFontClass ++; myFontText.className = fontClasses[currentFontClass % fontClasses.length]; updateDisplay(true); } canvas.addEventListener("click", changeCanvasRes); function changeCanvasRes() { currentCanvasRes ++; if (devicePixelRatio === 1 && currentCanvasRes === canvasResolutions.length - 1) { currentCanvasRes ++; } updateDisplay(true); } addEventListener("mousemove", mouseEvent); function mouseEvent(event) { const bounds = canvas.getBoundingClientRect(); mouse.x = event.pageX - scrollX - bounds.left; mouse.y = event.pageY - scrollY - bounds.top; updateDisplay(); } function updateDisplay(andRender = false) { if(updating === false) { updating = true; requestAnimationFrame(render); } updateText = andRender; } function drawTextExamples(text, textStyle) { var i = TEXT_ROWS; const yStep = ctx.canvas.height / (i + 2); while (i--) { drawText(text, 20, 4 + i * yStep, textStyle.family, textStyle.size, textStyle.color); } } function render() { updating = false; const res = canvasResolutions[currentCanvasRes % canvasResolutions.length]; if (res[0] !== canvas.width || res[1] !== canvas.height) { canvas.width = res[0]; canvas.height = res[1]; updateText = true; } if (updateText) { ctx.setTransform(1,0,0,1,0,0); ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); updateText = false; const textStyle = getFontStyle(myFontText); const text = myFontText.textContent; drawTextExamples(text, textStyle); } drawZoomView(mouse.x, mouse.y) }
 .fontContainer { position: absolute; top: 8px; left: 35%; background: white; border: 1px solid black; width: 30%; cursor: pointer; text-align: center; } #styleView { } .fontA {} .fontB { font-family: arial; font-size: 12px; color: #F008; } .fontC { font-family: cursive; font-size: 32px; color: #0808; } .fontD { font-family: monospace; font-size: 26px; color: #000; } .layout { display: flex; width: 100%; height: 128px; } #container { border: 1px solid black; width: 49%; height: 100%; overflow-y: scroll; } #container canvas { width: 500px; height: 500px; } #magViewContainer { border: 1px solid black; display: flex; width: 49%; height: 100%; } #magViewContainer canvas { width: 100%; height: 100%; image-rendering: pixelated; }
 <div class="fontContainer" id="displayFont"> <span class="fontA" id="myFontText" title="Click to cycle font styles">Hello Pixels</span> </div> <div class="layout"> <div id="container"> <canvas id="canvas" title="Click to cycle canvas resolution"></canvas> </div> <div id="magViewContainer"> <canvas id="canvas1"></canvas> </div> </div> <code id="styleView"></code>

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda