HTML 캔버스에서 텍스트의 높이를 어떻게 찾을 수 있습니까?
규격에는 context.measure텍스트(text) 함수가 있어 해당 텍스트를 인쇄하는 데 필요한 너비를 알려주지만 높이를 알 수 있는 방법을 찾을 수 없습니다.글꼴 기준인 건 알지만, 글꼴 문자열을 텍스트 높이로 변환할 수는 없습니다.
브라우저는 고급 텍스트 메트릭을 지원하기 시작하고 있으며, 이 작업이 널리 지원될 때 이 작업은 사소한 것이 될 것입니다.
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- font bounding box accents 및 그 바로 아래 섹션
지원 현황(2017년 8월 20일):
- Chrome은 깃발 뒤에 그것을 가지고 있습니다 (https://bugs.chromium.org/p/chromium/issues/detail?id=277215) .
- 파이어폭스는 이를 개발 중입니다(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 module), 대부분 지원(https://github.com/Automattic/node-canvas/wiki/Compatibility-Status) .
업데이트 - 예를 들어 카로타 편집기에서 이 기법을 사용했습니다.
엘리스벤의 답변에 따라, 여기 기준선에서 상승 및 하강을 얻을 수 있는 향상된 버전이 있습니다. 즉 다음과 같습니다.tmAscent
그리고.tmDescent
Win32의 GetTextMetric API에 의해 반환되었습니다.글꼴/크기가 서로 다른 범위의 텍스트를 단어로 묶은 실행을 수행하려면 이 작업이 필요합니다.
위 이미지는 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;
};
텍스트 요소에 추가하여 다음과 같이 디바를 추가합니다.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);
베스핀의 경우 소문자 '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; }
}
};
편집: 캔버스 변환을 사용하고 있습니까?그렇다면 변환 행렬을 추적해야 합니다.다음 방법은 초기 변환으로 텍스트의 높이를 측정해야 합니다.
편집 #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.
*/
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에 나와 있는 것처럼.
컨텍스트를 사용하여 글꼴을 정의하면 픽셀 단위의 텍스트 높이가 글꼴 크기(단위)와 동일하지 않습니까?폰트?
픽셀 조작을 이용해서 이 문제를 간단히 해결했습니다.
다음은 그래픽 답변입니다.
코드는 다음과 같습니다.
function textHeight (text, font) {
var fontDraw = document.createElement("canvas");
var height = 100;
var width = 100;
// here we expect that font size will be less canvas geometry
fontDraw.setAttribute("height", height);
fontDraw.setAttribute("width", width);
var ctx = fontDraw.getContext('2d');
// black is default
ctx.fillRect(0, 0, width, height);
ctx.textBaseline = 'top';
ctx.fillStyle = 'white';
ctx.font = font;
ctx.fillText(text/*'Eg'*/, 0, 0);
var pixels = ctx.getImageData(0, 0, width, height).data;
// row numbers where we first find letter end where it ends
var start = -1;
var end = -1;
for (var row = 0; row < height; row++) {
for (var column = 0; column < width; column++) {
var index = (row * width + column) * 4;
// if pixel is not white (background color)
if (pixels[index] == 0) {
// we havent met white (font color) pixel
// on the row and the letters was detected
if (column == width - 1 && start != -1) {
end = row;
row = height;
break;
}
continue;
}
else {
// we find top of letter
if (start == -1) {
start = row;
}
// ..letters body
break;
}
}
}
/*
document.body.appendChild(fontDraw);
fontDraw.style.pixelLeft = 400;
fontDraw.style.pixelTop = 400;
fontDraw.style.position = "absolute";
*/
return end - start;
}
Daniel의 대답에 덧붙여보자면, (멋져요! 그리고 확실히 맞아요!) JQuery가 없는 버전:
function objOff(obj)
{
var currleft = currtop = 0;
if( obj.offsetParent )
{ do { currleft += obj.offsetLeft; currtop += obj.offsetTop; }
while( obj = obj.offsetParent ); }
else { currleft += obj.offsetLeft; currtop += obj.offsetTop; }
return [currleft,currtop];
}
function FontMetric(fontName,fontSize)
{
var text = document.createElement("span");
text.style.fontFamily = fontName;
text.style.fontSize = fontSize + "px";
text.innerHTML = "ABCjgq|";
// if you will use some weird fonts, like handwriting or symbols, then you need to edit this test string for chars that will have most extreme accend/descend values
var block = document.createElement("div");
block.style.display = "inline-block";
block.style.width = "1px";
block.style.height = "0px";
var div = document.createElement("div");
div.appendChild(text);
div.appendChild(block);
// this test div must be visible otherwise offsetLeft/offsetTop will return 0
// but still let's try to avoid any potential glitches in various browsers
// by making it's height 0px, and overflow hidden
div.style.height = "0px";
div.style.overflow = "hidden";
// I tried without adding it to body - won't work. So we gotta do this one.
document.body.appendChild(div);
block.style.verticalAlign = "baseline";
var bp = objOff(block);
var tp = objOff(text);
var taccent = bp[1] - tp[1];
block.style.verticalAlign = "bottom";
bp = objOff(block);
tp = objOff(text);
var theight = bp[1] - tp[1];
var tdescent = theight - taccent;
// now take it off :-)
document.body.removeChild(div);
// return text accent, descent and total height
return [taccent,theight,tdescent];
}
방금 위의 코드를 테스트해봤는데 맥의 최신 크롬, FF, 사파리에서 잘 작동합니다.
편집: 폰트 크기도 추가했고 시스템 폰트 대신 웹 폰트로 테스트했습니다. 잘 작동합니다.
여기에 정답이 없다는 것에 좀 충격을 받았습니다.견적이나 추측을 할 필요가 없습니다.또한 글꼴 크기는 글꼴의 경계 상자의 실제 크기가 아닙니다.글꼴 높이는 오름차순과 내림차순이 있는지 여부에 따라 달라집니다.
계산하려면 를 사용합니다.ctx.measureText()
를 더하면 다음과.actualBoundingBoxAscent
그리고.actualBoundingBoxDescent
. 그것은 실제 크기를 알려줄 것입니다.추가할 수도 있습니다.font*
요소 높이와 같은 것을 계산하는 데 사용되는 크기를 얻기 위한 버전이지만 실제로 사용된 글꼴 공간의 높이는 정확히 아닙니다.
const text = 'Hello World';
const canvas = document.querySelector('canvas');
canvas.width = 500;
canvas.height = 200;
const ctx = canvas.getContext('2d');
const fontSize = 100;
ctx.font = `${fontSize}px Arial, Helvetica, sans-serif`;
// top is critical to the fillText() calculation
// you can use other positions, but you need to adjust the calculation
ctx.textBaseline = 'top';
ctx.textAlign = 'center';
const metrics = ctx.measureText(text);
const width = metrics.width;
const actualHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
// fallback to using fontSize if fontBoundingBoxAscent isn't available, like in Firefox. Should be close enough that you aren't more than a pixel off in most cases.
const fontHeight = (metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent) ?? fontSize;
ctx.fillStyle = '#00F'; // blue
ctx.fillRect((canvas.width / 2) - (width / 2), (canvas.height / 2) - (fontHeight / 2), width, fontHeight);
ctx.fillStyle = '#0F0'; // green
ctx.fillRect((canvas.width / 2) - (width / 2), (canvas.height / 2) - (actualHeight / 2), width, actualHeight);
// canvas.height / 2 - actualHeight / 2 gets you to the top of
// the green box. You have to add actualBoundingBoxAscent to shift
// it just right
ctx.fillStyle = '#F00'; // red
ctx.fillText(text, canvas.width / 2, canvas.height / 2 - actualHeight / 2 + metrics.actualBoundingBoxAscent);
<canvas></canvas>
한 줄대답
var height = parseInt(ctx.font) * 1.2;
CSS "선 높이: 정상"은 1에서 1.2 사이입니다.
자세한 내용은 여기를 읽으십시오.
이것은 제가 여기에 있는 다른 답변들을 바탕으로 한 것입니다.
function measureText(text, font) {
const span = document.createElement('span');
span.appendChild(document.createTextNode(text));
Object.assign(span.style, {
font: font,
margin: '0',
padding: '0',
border: '0',
whiteSpace: 'nowrap'
});
document.body.appendChild(span);
const {width, height} = span.getBoundingClientRect();
span.remove();
return {width, height};
}
var font = "italic 100px Georgia";
var text = "abc this is a test";
console.log(measureText(text, font));
터미널 에뮬레이터를 쓰고 있어서 캐릭터 주변에 직사각형을 그려야 했어요.
var size = 10
var lineHeight = 1.2 // CSS "line-height: normal" is between 1 and 1.2
context.font = size+'px/'+lineHeight+'em monospace'
width = context.measureText('m').width
height = size * lineHeight
분명히 캐릭터가 차지하는 정확한 공간을 원한다면 도움이 되지 않을 것입니다.하지만 특정 용도에 대해서는 정확한 근사치를 제공할 것입니다.
여기 간단한 기능이 있습니다.라이브러리가 필요 없습니다.
이 함수는 기준선에 대한 상한과 하한을 얻기 위해 작성한 것입니다.textBaseline
로 설정됩니다.alphabetic
. 다른 캔버스를 만든 다음 그림을 그립니다. 그리고 나서 맨 위와 맨 아래의 빈 픽셀을 찾습니다.그리고 그것이 최고와 최저의 한계입니다.상대적인 값으로 반환되므로 높이가 20px이고 기준선 아래에 아무것도 없으면 상한은-20
.
문자를 입력해야 합니다.그렇지 않으면 당연히 높이와 너비가 0이 됩니다.
용도:
alert(measureHeight('40px serif', 40, 'rg').height)
기능은 다음과 같습니다.
function measureHeight(aFont, aSize, aChars, aOptions={}) {
// if you do pass aOptions.ctx, keep in mind that the ctx properties will be changed and not set back. so you should have a devoted canvas for this
// if you dont pass in a width to aOptions, it will return it to you in the return object
// the returned width is Math.ceil'ed
console.error('aChars: "' + aChars + '"');
var defaultOptions = {
width: undefined, // if you specify a width then i wont have to use measureText to get the width
canAndCtx: undefined, // set it to object {can:,ctx:} // if not provided, i will make one
range: 3
};
aOptions.range = aOptions.range || 3; // multiples the aSize by this much
if (aChars === '') {
// no characters, so obviously everything is 0
return {
relativeBot: 0,
relativeTop: 0,
height: 0,
width: 0
};
// otherwise i will get IndexSizeError: Index or size is negative or greater than the allowed amount error somewhere below
}
// validateOptionsObj(aOptions, defaultOptions); // not needed because all defaults are undefined
var can;
var ctx;
if (!aOptions.canAndCtx) {
can = document.createElement('canvas');;
can.mozOpaque = 'true'; // improved performanceo on firefox i guess
ctx = can.getContext('2d');
// can.style.position = 'absolute';
// can.style.zIndex = 10000;
// can.style.left = 0;
// can.style.top = 0;
// document.body.appendChild(can);
} else {
can = aOptions.canAndCtx.can;
ctx = aOptions.canAndCtx.ctx;
}
var w = aOptions.width;
if (!w) {
ctx.textBaseline = 'alphabetic';
ctx.textAlign = 'left';
ctx.font = aFont;
w = ctx.measureText(aChars).width;
}
w = Math.ceil(w); // needed as i use w in the calc for the loop, it needs to be a whole number
// must set width/height, as it wont paint outside of the bounds
can.width = w;
can.height = aSize * aOptions.range;
ctx.font = aFont; // need to set the .font again, because after changing width/height it makes it forget for some reason
ctx.textBaseline = 'alphabetic';
ctx.textAlign = 'left';
ctx.fillStyle = 'white';
console.log('w:', w);
var avgOfRange = (aOptions.range + 1) / 2;
var yBaseline = Math.ceil(aSize * avgOfRange);
console.log('yBaseline:', yBaseline);
ctx.fillText(aChars, 0, yBaseline);
var yEnd = aSize * aOptions.range;
var data = ctx.getImageData(0, 0, w, yEnd).data;
// console.log('data:', data)
var botBound = -1;
var topBound = -1;
// measureHeightY:
for (y=0; y<=yEnd; y++) {
for (var x = 0; x < w; x += 1) {
var n = 4 * (w * y + x);
var r = data[n];
var g = data[n + 1];
var b = data[n + 2];
// var a = data[n + 3];
if (r+g+b > 0) { // non black px found
if (topBound == -1) {
topBound = y;
}
botBound = y; // break measureHeightY; // dont break measureHeightY ever, keep going, we till yEnd. so we get proper height for strings like "`." or ":" or "!"
break;
}
}
}
return {
relativeBot: botBound - yBaseline, // relative to baseline of 0 // bottom most row having non-black
relativeTop: topBound - yBaseline, // relative to baseline of 0 // top most row having non-black
height: (botBound - topBound) + 1,
width: w// EDIT: comma has been added to fix old broken code.
};
}
relativeBot
,relativeTop
,그리고.height
반환 대상에 있는 유용한 것들입니다.
사용 예시는 다음과 같습니다.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script>
function measureHeight(aFont, aSize, aChars, aOptions={}) {
// if you do pass aOptions.ctx, keep in mind that the ctx properties will be changed and not set back. so you should have a devoted canvas for this
// if you dont pass in a width to aOptions, it will return it to you in the return object
// the returned width is Math.ceil'ed
console.error('aChars: "' + aChars + '"');
var defaultOptions = {
width: undefined, // if you specify a width then i wont have to use measureText to get the width
canAndCtx: undefined, // set it to object {can:,ctx:} // if not provided, i will make one
range: 3
};
aOptions.range = aOptions.range || 3; // multiples the aSize by this much
if (aChars === '') {
// no characters, so obviously everything is 0
return {
relativeBot: 0,
relativeTop: 0,
height: 0,
width: 0
};
// otherwise i will get IndexSizeError: Index or size is negative or greater than the allowed amount error somewhere below
}
// validateOptionsObj(aOptions, defaultOptions); // not needed because all defaults are undefined
var can;
var ctx;
if (!aOptions.canAndCtx) {
can = document.createElement('canvas');;
can.mozOpaque = 'true'; // improved performanceo on firefox i guess
ctx = can.getContext('2d');
// can.style.position = 'absolute';
// can.style.zIndex = 10000;
// can.style.left = 0;
// can.style.top = 0;
// document.body.appendChild(can);
} else {
can = aOptions.canAndCtx.can;
ctx = aOptions.canAndCtx.ctx;
}
var w = aOptions.width;
if (!w) {
ctx.textBaseline = 'alphabetic';
ctx.textAlign = 'left';
ctx.font = aFont;
w = ctx.measureText(aChars).width;
}
w = Math.ceil(w); // needed as i use w in the calc for the loop, it needs to be a whole number
// must set width/height, as it wont paint outside of the bounds
can.width = w;
can.height = aSize * aOptions.range;
ctx.font = aFont; // need to set the .font again, because after changing width/height it makes it forget for some reason
ctx.textBaseline = 'alphabetic';
ctx.textAlign = 'left';
ctx.fillStyle = 'white';
console.log('w:', w);
var avgOfRange = (aOptions.range + 1) / 2;
var yBaseline = Math.ceil(aSize * avgOfRange);
console.log('yBaseline:', yBaseline);
ctx.fillText(aChars, 0, yBaseline);
var yEnd = aSize * aOptions.range;
var data = ctx.getImageData(0, 0, w, yEnd).data;
// console.log('data:', data)
var botBound = -1;
var topBound = -1;
// measureHeightY:
for (y=0; y<=yEnd; y++) {
for (var x = 0; x < w; x += 1) {
var n = 4 * (w * y + x);
var r = data[n];
var g = data[n + 1];
var b = data[n + 2];
// var a = data[n + 3];
if (r+g+b > 0) { // non black px found
if (topBound == -1) {
topBound = y;
}
botBound = y; // break measureHeightY; // dont break measureHeightY ever, keep going, we till yEnd. so we get proper height for strings like "`." or ":" or "!"
break;
}
}
}
return {
relativeBot: botBound - yBaseline, // relative to baseline of 0 // bottom most row having non-black
relativeTop: topBound - yBaseline, // relative to baseline of 0 // top most row having non-black
height: (botBound - topBound) + 1,
width: w
};
}
</script>
</head>
<body style="background-color:steelblue;">
<input type="button" value="reuse can" onClick="alert(measureHeight('40px serif', 40, 'rg', {canAndCtx:{can:document.getElementById('can'), ctx:document.getElementById('can').getContext('2d')}}).height)">
<input type="button" value="dont reuse can" onClick="alert(measureHeight('40px serif', 40, 'rg').height)">
<canvas id="can"></canvas>
<h1>This is a Heading</h1>
<p>This is a paragraph.</p>
</body>
</html>
그relativeBot
그리고.relativeTop
이 이미지에서 볼 수 있는 것은 다음과 같습니다.
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text
HTML 캔버스를 이용하여 텍스트의 정확한 높이와 폭을 측정할 수 있는 멋진 라이브러리를 구현하였습니다.이렇게 하면 당신이 원하는 대로 될 겁니다.
https://github.com/ChrisBellew/text-measurer.js
TextMetrics의 너비만 있고 높이는 없다는 것이 재미있습니다.
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#textmetrics
이 예와 같이 Span을 사용할 수 있습니까?
http://mudcu.be/journal/2011/01/html5-typographic-metrics/ #alignFix
먼저 글꼴 크기의 높이를 설정한 다음 글꼴 높이의 값에 따라 현재 텍스트의 높이를 결정해야 합니다. 물론 텍스트가 최대 텍스트 상자를 초과하지 않을 경우 동일한 글꼴 높이를 누적해야 합니다.상자 텍스트 내의 텍스트만 표시합니다.값이 높으면 자신만의 정의가 필요합니다.미리 설정된 높이가 클수록 표시 및 가로채기가 필요한 텍스트의 높이가 증가합니다.
AutoWrappedText.auto_wrap = function(ctx, text, maxWidth, maxHeight) {
var words = text.split("");
var lines = [];
var currentLine = words[0];
var total_height = 0;
for (var i = 1; i < words.length; i++) {
var word = words[i];
var width = ctx.measureText(currentLine + word).width;
if (width < maxWidth) {
currentLine += word;
} else {
lines.push(currentLine);
currentLine = word;
// TODO dynamically get font size
total_height += 25;
if (total_height >= maxHeight) {
break
}
}
}
if (total_height + 25 < maxHeight) {
lines.push(currentLine);
} else {
lines[lines.length - 1] += "…";
}
return lines;};
저는 JUST FOR ARIAL이 경계 상자의 높이를 찾는 가장 간단하고 빠르고 정확한 방법은 특정 글자의 너비를 사용하는 것임을 발견했습니다.사용자가 다른 글꼴을 선택하지 않고 특정 글꼴을 사용할 계획이라면 해당 글꼴에 적합한 문자를 찾기 위해 약간의 조사를 수행할 수 있습니다.
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="700" height="200" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "100px Arial";
var txt = "Hello guys!"
var Hsup=ctx.measureText("H").width;
var Hbox=ctx.measureText("W").width;
var W=ctx.measureText(txt).width;
var W2=ctx.measureText(txt.substr(0, 9)).width;
ctx.fillText(txt, 10, 100);
ctx.rect(10,100, W, -Hsup);
ctx.rect(10,100+Hbox-Hsup, W2, -Hbox);
ctx.stroke();
</script>
<p><strong>Note:</strong> The canvas tag is not supported in Internet
Explorer 8 and earlier versions.</p>
</body>
</html>
글꼴 크기를 설정하는 것이 실용적이지 않을 수도 있습니다.
ctx.font = ''
는 CSS에 의해 정의된 것과 내장된 글꼴 태그를 사용할 것입니다.CSS 글꼴을 사용할 경우 측정을 사용하여 프로그래밍 방식으로 높이가 얼마인지 알 수 없습니다.문자 방식, 매우 근시안적입니다.그러나 다른 참고로 IE8은 너비와 높이를 반환하지 않습니다.
이것은 1) 멀티라인 텍스트에 대해서도 2) 그리고 IE9에서도 작동합니다!
<div class="measureText" id="measureText">
</div>
.measureText {
margin: 0;
padding: 0;
border: 0;
font-family: Arial;
position: fixed;
visibility: hidden;
height: auto;
width: auto;
white-space: pre-wrap;
line-height: 100%;
}
function getTextFieldMeasure(fontSize, value) {
const div = document.getElementById("measureText");
// returns wrong result for multiline text with last line empty
let arr = value.split('\n');
if (arr[arr.length-1].length == 0) {
value += '.';
}
div.innerText = value;
div.style['font-size']= fontSize + "px";
let rect = div.getBoundingClientRect();
return {width: rect.width, height: rect.height};
};
이것이 오래된 질문이라는 것을 알고 있지만, 나중에 참고할 수 있도록 JS 전용(jquery가 없는) 짧은 솔루션을 추가하고자 합니다.
var measureTextHeight = function(fontFamily, fontSize)
{
var text = document.createElement('span');
text.style.fontFamily = fontFamily;
text.style.fontSize = fontSize + "px";
text.textContent = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
document.body.appendChild(text);
var result = text.getBoundingClientRect().height;
document.body.removeChild(text);
return result;
};
프로젝트 중 하나에서 실제 텍스트 높이를 포함하도록 CanvasRenderingContext2D.measureText()를 몽키 패치했습니다.바닐라 JS로 쓰여 있고 의존성이 없습니다.
/*
* Monkeypatch CanvasRenderingContext2D.measureText() to include actual height of the text
*/
; (function (global) {
"use strict";
var _measureText = global.CanvasRenderingContext2D.prototype.measureText;
global.CanvasRenderingContext2D.prototype.measureText = function () {
var textMetrics = _measureText.apply(this, arguments);
var _getHeight = function (text) {
var $span = global.document.createElement("span");
var spanTextNode = global.document.createTextNode(text);
$span.appendChild(spanTextNode);
$span.setAttribute("style", `font: ${this.font}`);
var $div = global.document.createElement("div");
$div.setAttribute("style", "display: inline-block; width: 1px; height: 0; vertical-align: super;");
var $parentDiv = global.document.createElement("div");
$parentDiv.appendChild($span);
$parentDiv.appendChild($div);
var $body = global.document.getElementsByTagName("body")[0];
$body.appendChild($parentDiv);
var divRect = $div.getBoundingClientRect();
var spanRect = $span.getBoundingClientRect();
var result = {};
$div.style.verticalAlign = "baseline";
result.ascent = divRect.top - spanRect.top;
$div.style.verticalAlign = "bottom";
result.height = divRect.top - spanRect.top;
result.descent = result.height - result.ascent;
$body.removeChild($parentDiv);
return result.height - result.descent;
}.bind(this);
var height = _getHeight(arguments[0]);
global.Object.defineProperty(textMetrics, "height", { value: height });
return textMetrics;
};
})(window);
이렇게 쓰시면 됩니다.
ctx.font = "bold 64px Verdana, sans-serif"; // Automatically considers it as part of height calculation
var textMetrics = ctx.measureText("Foobar");
var textHeight = textMetrics.height;
parseInt(ctx.font, 10)
예.
let text_height = parseInt(ctx.font, 10)
예:반품35
정상적인 상황에서는 다음이 작동해야 합니다.
var can = CanvasElement.getContext('2d'); //get context
var lineHeight = /[0-9]+(?=pt|px)/.exec(can.font); //get height from font variable
이건 정말 화나는...텍스트의 높이는 글꼴 크기입니다.여러분 중 누구도 그 문서를 읽지 않으셨나요?
context.font = "22px arial";
이것은 높이를 22 px로 설정할 것입니다.
유일한 이유는..
context.measureText(string).width
문자열의 너비는 원하는 문자열을 알지 못하는 한 글꼴로 그려진 모든 문자열에 대해 결정할 수 없기 때문입니다.키는 22 px 입니다.
만약 당신이 px가 아닌 다른 측정을 사용한다면, 높이는 여전히 같겠지만, 그 측정을 사용하면 당신은 기껏해야 측정을 변환하기만 하면 될 것입니다.
근사 솔루션:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "100px Arial";
var txt = "Hello guys!"
var wt = ctx.measureText(txt).width;
var height = wt / txt.length;
이것은 단일 글꼴로 정확한 결과가 될 것입니다.
언급URL : https://stackoverflow.com/questions/1134586/how-can-you-find-the-height-of-text-on-an-html-canvas
'programing' 카테고리의 다른 글
필수 범주의 제품이 카트에 있는 경우에만 체크아웃 허용 (0) | 2023.10.30 |
---|---|
*ngIf에 대해 Angular 8 HTML 템플릿에서 Enum 사용 (0) | 2023.10.30 |
Postgre와 동등한 오라클SQL INSERT...돌아오는 *; (0) | 2023.10.30 |
서브쿼리의 출력을 조절할 수 있습니까? (0) | 2023.10.30 |
jQuery UI 슬라이더(프로그래밍 방식으로 설정) (0) | 2023.10.30 |