스펙에는 context.measureText (text) 함수가있어 텍스트를 인쇄하는 데 필요한 너비가 얼마나되는지 알려주지 만 키가 얼마나 큰지 알 수있는 방법을 찾을 수 없습니다. 글꼴을 기반으로한다는 것을 알고 있지만 글꼴 문자열을 텍스트 높이로 변환하는 것을 모르겠습니다.
답변
업데이트 -이 작업의 예를 들어 Carota 편집기 에서이 기술을 사용했습니다 .
ellisbben의 답변에 따라 다음은 기본에서 상승 및 하강을 얻는 향상된 버전입니다. 즉, Win32의 GetTextMetric API tmAscent
와 동일 하고 tmDescent
반환 됩니다 . 다른 글꼴 / 크기의 범위를 가진 단어로 줄 바꿈 된 텍스트를 실행하려는 경우에 필요합니다.
위의 이미지는 Safari의 캔버스에서 생성되었으며, 빨간색은 캔버스가 텍스트를 그리도록 지시 된 맨 위 선이며, 녹색은 기준선이고 파란색은 아래쪽입니다 (빨간색에서 파란색이 전체 높이 임).
간결성을 위해 jQuery 사용 :
var getTextHeight = function(font) {
var text = $('<span>Hg</span>').css({ fontFamily: font });
var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>');
var div = $('<div></div>');
div.append(text, block);
var body = $('body');
body.append(div);
try {
var result = {};
block.css({ verticalAlign: 'baseline' });
result.ascent = block.offset().top - text.offset().top;
block.css({ verticalAlign: 'bottom' });
result.height = block.offset().top - text.offset().top;
result.descent = result.height - result.ascent;
} finally {
div.remove();
}
return result;
};
텍스트 요소 외에도 div를 추가하여 스타일을 display: inline-block
설정 vertical-align
한 다음 브라우저가 배치 한 위치를 찾을 수 있습니다.
따라서 ascent
, descent
및 height
( 편의상 단지 ascent
+ descent
) 로 객체를 다시 얻습니다 . 그것을 테스트하려면 수평선을 그리는 함수를 가질 가치가 있습니다.
var testLine = function(ctx, x, y, len, style) {
ctx.strokeStyle = style;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + len, y);
ctx.closePath();
ctx.stroke();
};
그런 다음 상단, 기준선 및 하단을 기준으로 텍스트가 캔버스에서 어떻게 배치되는지 확인할 수 있습니다.
var font = '36pt Times';
var message = 'Big Text';
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top'; // important!
ctx.font = font;
ctx.fillText(message, x, y);
// Canvas can tell us the width
var w = ctx.measureText(message).width;
// New function gets the other info we need
var h = getTextHeight(font);
testLine(ctx, x, y, w, 'red');
testLine(ctx, x, y + h.ascent, w, 'green');
testLine(ctx, x, y + h.height, w, 'blue');
답변
대문자 M의 길이를 확인하면 세로 높이의 근사치를 얻을 수 있습니다.
ctx.font='bold 10px Arial';
lineHeight=ctx.measureText('M').width;
답변
캔버스 사양은 줄의 높이를 측정하는 방법을 제공하지 않습니다. 그러나 텍스트 크기를 픽셀 단위로 설정할 수 있으며 일반적으로 세로 경계가 비교적 쉬운 것을 알아낼 수 있습니다.
더 정확한 것이 필요하면 캔버스에 텍스트를 던지고 픽셀 데이터를 가져와 세로로 사용되는 픽셀 수를 알아낼 수 있습니다. 이것은 비교적 간단하지만 효율적이지 않습니다. 다음과 같은 작업을 수행 할 수 있습니다 (작동하지만 제거하려는 캔버스에 텍스트를 그립니다).
function measureTextHeight(ctx, left, top, width, height) {
// Draw the text in the specified area
ctx.save();
ctx.translate(left, top + Math.round(height * 0.8));
ctx.mozDrawText('gM'); // This seems like tall text... Doesn't it?
ctx.restore();
// Get the pixel data from the canvas
var data = ctx.getImageData(left, top, width, height).data,
first = false,
last = false,
r = height,
c = 0;
// Find the last line with a non-white 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-white 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;
}
// We screwed something up... What do you expect from free code?
return 0;
}
// Set the font
context.mozTextStyle = '32px Arial';
// Specify a context and a rect that is safe to draw in when calling measureTextHeight
var height = measureTextHeight(context, 0, 0, 50, 50);
console.log(height);
Bespin의 경우 소문자 ‘m’의 너비를 측정하여 높이를 가짜로 만듭니다 …이 방법을 모르며이 방법을 권장하지 않습니다. 관련 Bespin 방법은 다음과 같습니다.
var fixCanvas = function(ctx) {
// upgrade Firefox 3.0.x text rendering to HTML 5 standard
if (!ctx.fillText && ctx.mozDrawText) {
ctx.fillText = function(textToDraw, x, y, maxWidth) {
ctx.translate(x, y);
ctx.mozTextStyle = ctx.font;
ctx.mozDrawText(textToDraw);
ctx.translate(-x, -y);
}
}
if (!ctx.measureText && ctx.mozMeasureText) {
ctx.measureText = function(text) {
ctx.mozTextStyle = ctx.font;
var width = ctx.mozMeasureText(text);
return { width: width };
}
}
if (ctx.measureText && !ctx.html5MeasureText) {
ctx.html5MeasureText = ctx.measureText;
ctx.measureText = function(text) {
var textMetrics = ctx.html5MeasureText(text);
// fake it 'til you make it
textMetrics.ascent = ctx.html5MeasureText("m").width;
return textMetrics;
}
}
// for other browsers
if (!ctx.fillText) {
ctx.fillText = function() {}
}
if (!ctx.measureText) {
ctx.measureText = function() { return 10; }
}
};
답변
브라우저는 고급 텍스트 메트릭 을 지원하기 시작했습니다. 이 작업은 광범위하게 지원 될 때 사소한 것입니다.
let metrics = ctx.measureText(text);
let fontHeight = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
let actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
fontHeight
렌더링되는 문자열에 관계없이 일정한 경계 상자 높이를 가져옵니다. actualHeight
렌더링되는 문자열에 따라 다릅니다.
사양 : https://www.w3.org/TR/2012/CR-2dcontext-20121217/#dom-textmetrics-fontboundingboxascent 및 바로 아래 섹션.
지원 상태 (2017 년 8 월 20 일) :
- Chrome은 플래그 뒤에 있습니다 ( https://bugs.chromium.org/p/chromium/issues/detail?id=277215 ).
- Firefox는 개발 중입니다 ( https://bugzilla.mozilla.org/show_bug.cgi?id=1102584 ).
- Edge는 지원하지 않습니다 ( https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/30922861-advanced-canvas-textmetrics ).
- 주로 지원되는 node-canvas (node.js 모듈) ( https://github.com/Automattic/node-canvas/wiki/Compatibility-Status ).
답변
편집 : 캔버스 변환을 사용하고 있습니까? 그렇다면 변환 행렬을 추적해야합니다. 다음 방법은 초기 변환으로 텍스트 높이를 측정해야합니다.
편집 # 2 : 이상하게도 아래 코드는이 StackOverflow 페이지에서 실행할 때 정답을 생성하지 않습니다. 일부 스타일 규칙이 있으면이 기능이 중단 될 수 있습니다.
캔버스는 CSS에서 정의한대로 글꼴을 사용하므로 이론적으로 문서에 적절한 스타일의 텍스트 덩어리를 추가하고 높이를 측정 할 수 있습니다. 나는 이것이 텍스트를 렌더링 한 다음 픽셀 데이터를 확인하는 것보다 훨씬 쉽다고 생각하며 어 센더와 디 센더도 존중해야합니다. 다음을 확인하십시오.
var determineFontHeight = function(fontStyle) {
var body = document.getElementsByTagName("body")[0];
var dummy = document.createElement("div");
var dummyText = document.createTextNode("M");
dummy.appendChild(dummyText);
dummy.setAttribute("style", fontStyle);
body.appendChild(dummy);
var result = dummy.offsetHeight;
body.removeChild(dummy);
return result;
};
//A little test...
var exampleFamilies = ["Helvetica", "Verdana", "Times New Roman", "Courier New"];
var exampleSizes = [8, 10, 12, 16, 24, 36, 48, 96];
for(var i = 0; i < exampleFamilies.length; i++) {
var family = exampleFamilies[i];
for(var j = 0; j < exampleSizes.length; j++) {
var size = exampleSizes[j] + "pt";
var style = "font-family: " + family + "; font-size: " + size + ";";
var pixelHeight = determineFontHeight(style);
console.log(family + " " + size + " ==> " + pixelHeight + " pixels high.");
}
}
높이를 측정하는 DOM 요소에서 글꼴 스타일이 올바른지 확인해야하지만 매우 간단합니다. 정말 당신은 같은 것을 사용해야합니다
var canvas = /* ... */
var context = canvas.getContext("2d");
var canvasFont = " ... ";
var fontHeight = determineFontHeight("font: " + canvasFont + ";");
context.font = canvasFont;
/*
do your stuff with your font and its height here.
*/
답변
context.font 사용하여 글꼴을 정의하면 텍스트의 높이가 픽셀 단위의 글꼴 크기 (pts)와 같지 않습니까?
답변
JJ Stiff가 제안한 것처럼 텍스트를 범위에 추가 한 다음 범위의 오프셋 높이를 측정 할 수 있습니다.
var d = document.createElement("span");
d.font = "20px arial";
d.textContent = "Hello world!";
document.body.appendChild(d);
var emHeight = d.offsetHeight;
document.body.removeChild(d);
HTML5Rocks에 표시된대로