javascript - mdn - Espaciado entre letras en el elemento canvas
dibujar lineas en canvas javascript (9)
Aquí hay un coffeescript que le permite establecer kerning a su contexto como tal
tctx = tcanv.getContext(''2d'')
tctx.kerning = 10
tctx.fillStyle = ''black''
tctx.fillText ''Hello World!'', 10, 10
el código de soporte es:
_fillText = CanvasRenderingContext2D::fillText
CanvasRenderingContext2D::fillText = (str, x, y, args...) ->
# no kerning? default behavior
return _fillText.apply this, arguments unless @kerning?
# we need to remember some stuff as we loop
offset = 0
_.each str, (letter) =>
_fillText.apply this, [
letter
x + offset + @kerning
y
].concat args # in case any additional args get sent to fillText at any time
offset += @measureText(letter).width + @kerning
El javascript sería
var _fillText,
__slice = [].slice;
_fillText = CanvasRenderingContext2D.prototype.fillText;
CanvasRenderingContext2D.prototype.fillText = function() {
var args, offset, str, x, y,
_this = this;
str = arguments[0], x = arguments[1], y = arguments[2], args = 4 <= arguments.length ? __slice.call(arguments, 3) : [];
if (this.kerning == null) {
return _fillText.apply(this, arguments);
}
offset = 0;
return _.each(str, function(letter) {
_fillText.apply(_this, [letter, x + offset + _this.kerning, y].concat(args));
offset += _this.measureText(letter).width + _this.kerning;
});
};
La pregunta lo dice todo. He estado buscando y comenzando a preocuparme de que sea imposible.
Tengo este elemento canvas al que estoy dibujando texto. Quiero establecer el espaciado entre letras similar al atributo de letter-spacing
CSS. Con eso me refiero a aumentar la cantidad de píxeles entre letras cuando se dibuja una cuerda.
Mi código para dibujar el texto es así, ctx es la variable de contexto canvas.
ctx.font = "3em sheepsans";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillStyle = "rgb(255, 255, 255)";
ctx.fillText("Blah blah text", 1024 / 2, 768 / 2);
He intentado agregar ctx.letterSpacing = "2px";
antes del sorteo, pero sin resultado. ¿Hay alguna manera de hacer esto solo con una configuración simple, o tendré que hacer una función para dibujar individualmente cada personaje con el espaciado en mente?
El espaciado de letras en el lienzo ES APOYADO, utilicé esto
canvas = document.getElementById(''canvas'');
canvas.style.letterSpacing = ''2px'';
En realidad, el lienzo del concepto de espaciado entre letras no es compatible.
Entonces usé javascript para hacer esto.
var value = $(''#sourceText1'').val().split("").join(" ");
O
var sample_text = "Praveen Chelumalla"; var text = sample_text.split("").join(" ");
No es verdad. Puede agregar propiedad de espaciado de letras al elemento canvas en css y funciona perfectamente. No hay necesidad de soluciones complicadas. Me acabo de dar cuenta en este momento en mi proyecto de lienzo. es decir: lienzo {ancho: 480px; altura: 350px; margen: 30px auto 0; relleno: 15px 0 0 0; fondo: rosa; bloqueo de pantalla; borde: 2px discontinuo marrón; espaciado entre letras: 0.1em; }
No estoy seguro de si debería funcionar (según las especificaciones), pero en algunos navegadores (Chrome) puede establecer la propiedad CSS letter-spacing
en el elemento <canvas>
sí, y se aplicará a todo el texto dibujado en el contexto . (Funciona en Chrome v56, no funciona en Firefox v51 o IE v11).
Tenga en cuenta que en Chrome v56 debe volver a obtener el contexto canvas 2d (y volver a establecer los valores que le interesan) después de cada cambio en el estilo de letter-spacing
; el espaciado parece hornearse en el contexto 2d que obtienes.
Ejemplo: https://jsfiddle.net/hg4pbsne/1/
var inp = document.querySelectorAll(''input''),
can = document.querySelector(''canvas''),
ctx = can.getContext(''2d'');
can.width = can.offsetWidth;
[].forEach.call(inp,function(inp){ inp.addEventListener(''input'', redraw, false) });
redraw();
function redraw(){
ctx.clearRect(0,0,can.width,can.height);
can.style.letterSpacing = inp[0].value + ''px'';
ctx = can.getContext(''2d'');
ctx.textAlign = ''center'';
ctx.textBaseline = ''middle'';
ctx.font = ''4em sans-serif'';
ctx.fillText(''Hello'', can.width/2, can.height*1/4);
can.style.letterSpacing = inp[1].value + ''px'';
ctx = can.getContext(''2d'');
ctx.textAlign = ''center'';
ctx.textBaseline = ''middle'';
ctx.font = ''4em sans-serif'';
ctx.fillText(''World'', can.width/2, can.height*3/4);
};
canvas { background:white }
canvas, label { display:block; width:400px; margin:0.5em auto }
<canvas></canvas>
<label>hello spacing: <input type="range" min="-20" max="40" value="1" step="0.1"></label>
<label>world spacing: <input type="range" min="-20" max="40" value="1" step="0.1"></label>
Respuesta original, entre navegadores:
Esto no es posible; HTML5 Canvas no tiene todo el poder de transformación de texto de CSS en HTML. Sugeriría que combine las tecnologías apropiadas para cada uso. Use HTML en capas con Canvas e incluso SVG, cada uno haciendo lo que mejor hace.
Tenga en cuenta también que "enrollar el suyo", dibujando cada carácter con un desplazamiento personalizado, producirá malos resultados para la mayoría de las fuentes, dado que hay pares de interletraje de letras y sugerencias de fuentes alineadas en píxeles.
No puede establecer la propiedad del espaciado entre letras, pero puede lograr un espacio entre letras más ancho en el lienzo insertando uno de los espacios en blanco entre cada letra de la cadena. Por ejemplo
ctx.font = "3em sheepsans";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillStyle = "rgb(255, 255, 255)";
var ctext = "Blah blah text".split("").join(String.fromCharCode(8202))
ctx.fillText(ctext, 1024 / 2, 768 / 2);
Esto insertará un espacio entre cada letra.
Al usar 8201 (en lugar de 8202) se insertará el espacio delgado ligeramente más ancho
Para obtener más opciones de espacios en blanco, consulte esta lista de espacios Unicode
Este método le ayudará a conservar el kerning de la fuente mucho más fácilmente que al posicionamiento manual de cada letra, sin embargo, no podrá ajustar el espacio entre letras de esta manera.
Para permitir ''pares de interletraje de letras'' y similares, he escrito lo siguiente. Debe tener esto en cuenta, y las pruebas preliminares sugieren que sí. Si tiene algún comentario al respecto, le indicaré mi pregunta sobre el tema (Cómo agregar espacio entre letras en el lienzo HTML )
Básicamente usa measureText () para obtener el ancho de toda la cadena, y luego elimina el primer carácter de la cadena y mide el ancho de la cadena restante, y usa la diferencia para calcular la posición correcta, teniendo en cuenta los pares de kerning y similares. Vea el enlace dado para más pseudocódigo.
Aquí está el HTML:
<canvas id="Test1" width="800px" height="200px"><p>Your browser does not support canvas.</p></canvas>
Aquí está el código:
this.fillTextWithSpacing = function(context, text, x, y, spacing)
{
//Start at position (X, Y).
//Measure wAll, the width of the entire string using measureText()
wAll = context.measureText(text).width;
do
{
//Remove the first character from the string
char = text.substr(0, 1);
text = text.substr(1);
//Print the first character at position (X, Y) using fillText()
context.fillText(char, x, y);
//Measure wShorter, the width of the resulting shorter string using measureText().
if (text == "")
wShorter = 0;
else
wShorter = context.measureText(text).width;
//Subtract the width of the shorter string from the width of the entire string, giving the kerned width of the character, wChar = wAll - wShorter
wChar = wAll - wShorter;
//Increment X by wChar + spacing
x += wChar + spacing;
//wAll = wShorter
wAll = wShorter;
//Repeat from step 3
} while (text != "");
}
Código para prueba demo / eyeball:
element1 = document.getElementById("Test1");
textContext1 = element1.getContext(''2d'');
textContext1.font = "72px Verdana, sans-serif";
textContext1.textAlign = "left";
textContext1.textBaseline = "top";
textContext1.fillStyle = "#000000";
text = "Welcome to go WAVE";
this.fillTextWithSpacing(textContext1, text, 0, 0, 0);
textContext1.fillText(text, 0, 100);
Idealmente, lanzaría múltiples cadenas aleatorias y haría una comparación de píxel por píxel. Tampoco estoy seguro de cuán bueno es el interletraje predeterminado de Verdana, aunque entiendo que es mejor que Arial: sugerencias sobre otras fuentes para intentar aceptar con gratitud.
Entonces ... hasta ahora se ve bien. De hecho, se ve perfecto. Aún espero que alguien señale cualquier falla en el proceso.
Mientras tanto, pondré esto aquí para que otros vean si están buscando una solución al respecto.
Yo suelo:
ctx.font = "32px Tahoma";//set font
ctx.scale(0.75,1);//important! the scale
ctx.fillText("LaFeteParFete test text", 2, 274);//draw
ctx.setTransform(1,0,0,1,0,0);//reset transform
No puede establecer el espaciado entre letras como una propiedad del contexto Canvas. Solo puede lograr el efecto haciendo un espaciado manual, lo siento. (Como en, dibujando cada letra de forma manual aumentando la x en una cantidad de píxel en cada una)
Para el registro, puede establecer algunas propiedades de texto usando ctx.font
pero el espaciado entre letras no es uno de ellos. Los que puede configurar son: "font-style font-variant font-weight font-size / line-height font-family"
Por ejemplo, técnicamente puede escribir ctx.font = "bold normal normal 12px/normal Verdana"
(o cualquier omisión de cualquiera de ellos) y se analizará correctamente.