2016-03-11 29 views
5

Ho bisogno di disegnare una stringa di testo in una posizione precisa su tela HTML5.La posizione del testo su tela è diversa in FireFox e Chrome

Here's my test code:

<!DOCTYPE html> 
<html> 
<body> 
<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;"> 
Your browser does not support the HTML5 canvas tag. 
</canvas> 
<script> 
    window.onload = function() { 
     var canvas = document.getElementById("mainCanvas"); 
     var ctx = canvas.getContext("2d");  
     ctx.textBaseline = "top"; 
     ctx.font = '100px Arial'; 
     ctx.textAlign = 'left'; 
     ctx.fillStyle = 'rgba(0, 0, 0, 255)'; 
     ctx.fillText('Test', 0, 0); 
    } 
</script> 
</body> 
</html> 

Il margine in alto è diverso in Chrome e Firefox: Text in Chrome vs Firefox

ho intenzione di disegnare altri elementi (ad esempio immagini, forme) sulla tela, e Devo assicurarmi che il testo appaia nella stessa posizione in tutti i browser. È possibile?

+1

probabilmente il problema è con la dimensione del testo, quando ho cambiato funzionerà bene anche se ho provato ad utilizzare sotto e funziona bene con me ctx.font = "50px Verdana"; ctx.fillStyle = 'rgba (0, 0, 0, 255)'; ctx.fillText ("Test", 10, 50); – cracker

+0

@cracker Ho provato a cambiare il font come suggerito e la posizione del testo rispetto alla parte superiore della tela è ancora diversa in Chrome e Firefox – Lev

+0

Ho provato a utilizzare ctx.textBaseline = "alfabetico"; ctx.fillText ('Test', 10, 100); dove è necessario impostare manualmente i parametri. potrebbe aiutarti! – cracker

risposta

2

Questo sembra essere un bug in Firefox risalente al 2012 e ancora non risolto!

Vedi https://bugzilla.mozilla.org/show_bug.cgi?id=737852

Edit: Impostazione della linea di base per "alfabetica" (impostazione predefinita) risultati sia Chrome e Firefox avendo la stessa posizione verticale per il testo.

Modifica: Sfortunatamente, la posizione verticale non è l'unica differenza tra Firefox e Chrome. Cambiare la stringa in "Test" mostra chiaramente che non solo la posizione verticale è diversa, ma anche lo spazio tra le lettere è leggermente diverso - risultando in una larghezza diversa del testo.

Se davvero necessario disporre di pixel posizione perfetta e le dimensioni del testo forse si dovrebbe usare Bitmap fonts

10

Causa

Come @iftah afferma: Il disallineamento è causata da un Firefox bug.

Si prega di aggiungere la vostra voce alla pagina di bug di Firefox in modo che risolverlo presto.

Soluzione

(purtroppo), la soluzione è per disegnare il testo su una seconda tela e la scansione che i dati di pixel per trovare il più in alto a sinistra & pixel del testo.

Quindi disegnare il testo sulla tela principale ma tirato verso l'alto e verso sinistra dagli offset di pixel calcolati.

Qui è annotato il codice e una demo:

// canvas vars 
 
var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 

 
// test vars 
 
var text='Test'; 
 
var fontsize=100; 
 
var fontface='arial'; 
 

 
drawTextAtXY(0,0,text,fontsize,fontface,'black'); 
 

 
function drawTextAtXY(x,y,text,fontsize,fontface,fill){ 
 
    // find the leftmost & topmost pixel of the text 
 
    var minXY=getTextTop(text,fontsize,fontface); 
 
    // set the font styles 
 
    ctx.textBaseline='top'; 
 
    ctx.font=fontsize+'px '+fontface; 
 
    ctx.fillStyle=fill; 
 
    // draw the text 
 
    // Pull the text leftward and topward by minX & minY 
 
    ctx.fillText(text,x-minXY.x,y-minXY.y); 
 
} 
 

 

 
function getTextTop(text,fontsize,fontface){ 
 
    // create temp working canvas 
 
    var c=document.createElement('canvas'); 
 
    var w=canvas.width; 
 
    var h=fontsize*2; 
 
    c.width=w; 
 
    c.height=h; 
 
    var cctx=c.getContext('2d'); 
 
    // set font styles 
 
    cctx.textBaseline='top'; 
 
    cctx.font=fontsize+'px '+fontface; 
 
    cctx.fillStyle='red'; 
 
    // draw the text 
 
    cctx.fillText(text,0,0); 
 
    // get pixel data 
 
    var imgdata=cctx.getImageData(0,0,w,h); 
 
    var d=imgdata.data; 
 
    // scan pixel data for minX,minY 
 
    var minX=10000000; 
 
    var minY=minX; 
 
    for(var y=0;y<h;y++){ 
 
    for(var x=0;x<w;x++){ 
 
     var n=(y*w+x)*4 
 
     if(d[n+3]>0){ 
 
      if(y<minY){minY=y;} 
 
      if(x<minX){minX=x;} 
 
     } 
 
    }} 
 
    // return the leftmost & topmost pixel of the text 
 
    return({x:minX,y:minY}); 
 
}
body{ background-color: ivory; } 
 
#canvas{border:1px solid red; margin:0 auto; }
<h4>Text drawn exactly at specified X,Y</h4> 
 
<canvas id="canvas" width=300 height=200></canvas>

+0

E anche se la creazione di una grande immagine della pagina di Chrome e il caricamento che con una mappa di immagine sarebbe un sacco di lavoro ... – ThrowingDwarf

+0

@ThrowingDwarf. Sì, compatibile con il browser === buono, (browser-incompatibile || browser-glitch) === PITA. :-) – markE

+1

Alcuni aggiornamenti su questo, (il bug report finalmente tornato alla vita :-)): Potrebbe effettivamente essere un bug in altri browser https://bugzilla.mozilla.org/show_bug.cgi?id=737852# c20 – Kaiido

3

È possibile risolvere facilmente.

è possibile utilizzare textBaseline = "middle"; e deve utilizzare trasformare a 50 px di all'inizio

significa:

<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;"> 
Your browser does not support the HTML5 canvas tag. 
    </canvas> 
    <script> 
    window.onload = function() { 
      var canvas = document.getElementById("mainCanvas"); 
      var ctx = canvas.getContext("2d");  
      ctx.textBaseline = "middle"; 
      ctx.font = '100px Arial'; 
      ctx.textAlign = 'left'; 
      ctx.fillStyle = 'rgba(0, 0, 0, 1)'; 
      ctx.save(); 
      ctx.transform(1, 0, 0, 1, 0, 50); 
      ctx.fillText('Test', 0, 0); 
      ctx.restore(); 
     } 
    </script> 

Un altro problema è nel codice: RGBA (0, 0, 0,) quarto numero in RGBA deve essere compresa tra 0-1 per esempio 0,75.

perché scrivo .save() e .restore()? per ripristinare la trasformazione e cancellare dopo l'uso.

Naturalmente è possibile utilizzare

ctx.fillText('Test', 0, 50); 

Invece

ctx.save(); 
ctx.transform(1, 0, 0, 1, 0, 50); 
ctx.fillText('Test', 0, 0); 
ctx.restore(); 
2

Come indicato in altra risposta è un po 're di bug (o forse solo una diversa implementazione). textBaseline bottom e Y position a 100 possono risolverlo.

<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;"> 
 
Your browser does not support the HTML5 canvas tag. 
 
</canvas> 
 
<script> 
 
    window.onload = function() { 
 
     var canvas = document.getElementById("mainCanvas"); 
 
     var ctx = canvas.getContext("2d");  
 
     ctx.textBaseline = "bottom"; 
 
     ctx.font = '100px Arial'; 
 
     ctx.textAlign = 'left'; 
 
     ctx.fillStyle = 'rgba(150, 50, 0, 1)'; 
 
     ctx.fillText('Test', 0, 100); 
 
    } 
 
</script>

In generale: Usa fondo della linea di base e aumentare posizione Y la quantità dimensione del carattere