2013-05-29 3 views
0

저는 캔버스를 사용하고 있으며 어떤 해결책도 생각할 수 없거나 문제에 대한 답변을 찾을 수 없습니다.자바 스크립트에서 정확한 문자 문자열 높이를 계산하십시오.

필자는 from \ characters의 기호를 포함하는 글꼴의 높이와 너비가 다양합니다.

일부 문자 (기호)를 글꼴에서 그리고 일부는 기호의 맨 위에서 아래로 그립니다. 문제는 내가 그림을 그리는 문자의 픽셀 높이를 정확하게 표시하는 방법을 찾아 낼 수 없다는 것과 중심 기호와 가운데 기호 사이의 불필요한 공백이 상단 \ 아래에 있음을 알 수 없다는 것입니다 문자열에는 context.measureText (theText) 함수가 있습니다.

예 : 'X'가 내 중심 기호가되기를 원한다고 말할 수 있습니다. '-'를 맨 위에 놓습니다. 그것은이

처럼 보이는 -
X

하지만 지금은 'X'와 사이에 공간이 - 내가 원하는하지 않습니다 ''.

아무도 도와 줄 수 있습니까?

감사

답변

5

폭은 간단합니다 : 캔버스의 컨텍스트는 텍스트 폭을 측정하기위한 메트릭 내장되어 있습니다.

// this will measure text width 
context.font = '14pt Verdana'; 
var m=context.measureText(yourText); 
var theWidth=m.width; 

measureText에서 높이를 계산하지 않으므로 높이가 더 어려워집니다.

글꼴 크기를 높이와 비슷하게 사용할 수 있습니다. 그게 내가하는 일입니다. 당신이 정말로 더 필요하면

는하지만 정확도는 여기에 높이를 계산하기 위해 텍스트의 픽셀을 검사하는 기능입니다 :

function measureTextHeight(fontSizeFace) { 

    // create a temp canvas 
    var width=1000; 
    var height=60; 
    var canvas=document.createElement("canvas"); 
    canvas.width=width; 
    canvas.height=height; 
    var ctx=canvas.getContext("2d"); 

    // Draw the entire a-z/A-Z alphabet in the canvas 
    var text="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    ctx.save(); 
    ctx.font=fontSizeFace; 
    ctx.clearRect(0,0,width,height); 
    ctx.fillText(text, 0, 40); 
    ctx.restore(); 

    // Get the pixel data from the canvas 
    var data = ctx.getImageData(0,0,width,height).data, 
     first = false, 
     last = false, 
     r = height, 
     c = 0; 

    // Find the last line with a non-transparent pixel 
    while(!last && r) { 
     r--; 
     for(c = 0; c < width; c++) { 
      if(data[r * width * 4 + c * 4 + 3]) { 
       last = r; 
       break; 
      } 
     } 
    } 

    // Find the first line with a non-transparent pixel 
    while(r) { 
     r--; 
     for(c = 0; c < width; c++) { 
      if(data[r * width * 4 + c * 4 + 3]) { 
       first = r; 
       break; 
      } 
     } 

     // If we've got it then return the height 
     if(first != r) return last - first; 
    } 

    // error condition if we get here 
    return 0; 
} 
+0

먼저 답장을 보내 주셔서 감사합니다. 나는이 솔루션에 대해서도 생각했지만 이 솔루션은 덜 효율적이며 내 "효율적인"웹 사이트와 일치하지 않습니다. 더 좋은 방법은 없을까요? –

+3

이 코드는 효율적으로 사용하면 매우 효율적입니다! ** 다양한 글꼴에 대해이 코드를 한 번만 실행하면됩니다 **. 그럼 너는 영원히 너에게 높이가있다! 글꼴 크기를 픽셀 단위로 설정하면 웹 사이트를 공개하고 웹 사이트에서 사용할 수 있도록 JSON에 높이를 저장하기 전에 글꼴 크기를 설정할 수도 있습니다. 쉽고 효율적! BTW,이 코드는 초당 수백 번 실행되므로 실제로 동적으로 수행 할 수도 있습니다. ;) – markE

+0

물론 나는이 방법으로 시간을 절약 할 수 있습니다.하지만 저는 상징을 나타내는 캐릭터를 그리는 중입니다. 캐릭터마다 크기가 다릅니다. 그리고 그런. .. 그러나 나는 다른 길은 없다고 생각한다. 감사합니다. –

-1

좋아, 그럼이 코드를 시도하고 나는 그것을 작동하게 위해 조금 변경했다 .

이것은 투명하지 않은 픽셀이있는 마지막 행을 찾은 코드입니다.

그래서 누군가가 필요로하는 경우. 그냥 즐기십시오.

var blnFound = false; 
    var intCurrRow = 0; 

    // Find the first line with a non-transparent pixel 
    while(!blnFound && intCurrRow < last) 
    { 
     for(intCurrCol = 0; intCurrCol < width; intCurrCol++) 
     { 
     var intCurrDataIdx = intCurrRow * width * 4 + intCurrCol * 4 + 3; 
     if(data[intCurrDataIdx]) 
     { 
      first = intCurrRow; 
      blnFound = true; 
      break; 
     } 
    } 

    // If we've got it then return the height 
    if (blnFound) 
    { 
     return last - first; 
    } 

    intCurrRow++; 
    } 
1

이전의 좋은 답변을 바탕으로 구축하십시오. 이것은 높이와 너비 (일부 유니 코드 문자 및 measureText, 일부 문자에 대한 유일한 해결책이 몇 가지 문제가 있었다) 줄 것이다.

function measureTextHeight(fontSizeFace, text) { 
    var width = 1500; 
    var height = 500; 

    var canvas = document.createElement("canvas"); 
    canvas.width = width; 
    canvas.height = height; 
    var ctx=canvas.getContext("2d"); 
    ctx.save(); 
    ctx.font=fontSizeFace; 
    ctx.clearRect(0,0,width,height); 
    ctx.fillText(text, parseInt(width * 0.1, 10), parseInt(height/2, 10)); 
    ctx.restore(); 
    document.body.appendChild(canvas); 
    var data = ctx.getImageData(0,0,width,height).data; 


    var topMost = false; 
    var bottomMost = false; 
    var leftMost = false; 
    var rightMost = false; 
    for(var x=0; x<width; x++) { 
    for(var y=0; (y<height) && (!leftMost); y++) { 
     //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString()); 
     if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) { 
     leftMost = x; 
     } 
    } 
    } 
    for(var y=0; y<height; y++) { 
    for(var x=0; (x<width) && (!topMost); x++) { 
     //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString()); 
     if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) { 
     topMost = y; 
     } 
    } 
    } 
    for(var x=width-1; x>=0; x--) { 
    for(var y=height-1; (y>=0) && (!rightMost); y--) { 
     //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString()); 
     if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) { 
     rightMost = x; 
     } 
    } 
    } 
    for(var y=height-1; y>=0; y--) { 
    for(var x=width-1; (x>=0) && (!bottomMost); x--) { 
     //console.log("x: %s y: %s index: %s", x,y, getAlphaIndexForCoordinates(x,y,width,height).toString()); 
     if(data[getAlphaIndexForCoordinates(x,y,width,height)] != 0) { 
     bottomMost = y; 
     } 
    } 
    } 
    return ({ 
    width: (rightMost - leftMost) + 1 
    ,height: (bottomMost - topMost) + 1 
    }); 
} 
function getAlphaIndexForCoordinates(x,y,width,height) { 
    return (((width*4*y)+4*x)+3); 
} 
관련 문제