![](/img/trans.png)
[英]Canvas speechbubble created in Javascript -> measureText height?
[英]Add responsive speechbubble to canvas using javascript
我目前正在使用javascript
在canvas
元素上繪制語音氣泡。
闡釋:
var text
包含將添加到語音泡沫中的文本。 var text
中的文本的高度。 component
函數將語音氣泡添加到canvas
元素。 component
函數內部調用wrapText
函數,以根據傳遞的maxwidth值向文本添加換行符。 例如,我現在傳遞值200,文本行將在200像素后斷開,並將其余文本添加到下一個文本行。 我的問題:
語音氣泡的寬度和高度不適合最終文本(斷行),因為我在交付了非文本行折斷文本的寬度和高度后就將其斷開。
我的問題:
我如何獲得斷行文本的寬度和高度以將其傳遞給component
函數,以便Speechbubble能夠適合斷行文本?
期望的結果:
語音氣泡應具有斷行文本的寬度和高度。
編碼:
var canvas = document.getElementById('canvas'); var ctx = canvas.getContext("2d"); ctx.font = "12px Helvetica"; var text = 'Speechbubble Speechbubble Speechbubble Speechbubble Speechbubble Speechbubble Speechbubble'; var fontHeight = getTextHeight(text, ctx.font); component(ctx, ctx.measureText(text).width, fontHeight, "#444", 10, 10, 5, text); function component(ctx, width, height, color, x, y, radius, text) { var r = radius; var w = width + 40; var h = height + 40; var pi2 = Math.PI * 2; var ap = w - 32; var aw = 20; var ah = 10; // Speechbubble create start ctx.beginPath(); ctx.arc(r, r, r, pi2 * 0.5, pi2 * 0.75); ctx.arc(w - r, r, r, pi2 * 0.75, pi2); ctx.arc(w - r, h - r, r, 0, pi2 * 0.25); ctx.lineTo(w - ap, h); ctx.lineTo(w - ap - (aw / 2), h + ah); ctx.lineTo(w - ap - aw, h); ctx.arc(r, h - r, r, pi2 * 0.25, pi2 * 0.5); ctx.fillStyle = color; ctx.fill(); // Speechbubble create end // Speechbubble text start ctx.fillStyle = "#fff"; wrapText(ctx, text, w - ctx.measureText(text).width - 25, h - fontHeight - 17, 300, 16); // Speechbubble text end } // Function to wrap the text depending on the maxWidth value // Function also adds the text to the following location: x, y function wrapText(context, text, x, y, maxWidth, lineHeight) { var words = text.split(' '); var line = ''; for(var n = 0; n < words.length; n++) { var testLine = line + words[n] + ' '; var metrics = context.measureText(testLine); var testWidth = metrics.width; if (testWidth > maxWidth && n > 0) { context.fillText(line, x, y); line = words[n] + ' '; y += lineHeight; } else { line = testLine; } } context.fillText(line, x, y); } // Function to get the height of the text function getTextHeight(txt, font) { var el = document.createElement('div'), height; el.style.cssText = "position:fixed; padding:0; left:-9999px; top:-9999px; font:" + font; el.textContent = txt; document.body.appendChild(el); height = parseInt(getComputedStyle(el).getPropertyValue('height'), 10); document.body.removeChild(el); return height; }
<canvas width="1200" height="1200" id="canvas"></canvas>
您將必須添加一些邏輯和數學...
var maxWidth = 500;
var w;
if (width > maxWidth) {
w = maxWidth;
} else {
w = width;
}
w += 40;
var h;
if (width > maxWidth) {
var numberOfRows = Math.ceil(width / maxWidth);
h = numberOfRows * height;
} else {
h = 16;
}
h += 40;
(下面的示例使用了上面的縮小版本,但功能完全相同)
之后,您必須重新調整文本的坐標。
從:
wrapText(ctx, text, w - ctx.measureText(text).width - 25, h - fontHeight - 17, 300, 16);
至:
wrapText(ctx, text, 25, 17, maxWidth, 16);
例:
var canvas = document.getElementById('canvas'); var ctx = canvas.getContext("2d"); ctx.font = "12px Helvetica"; var testCases = [ "Lorem ipsum dolor sit amet", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." ], testCaseIndex = 0; setInterval(function() { var text = testCases[testCaseIndex]; ctx.clearRect(0, 0, canvas.width, canvas.height); var fontHeight = getTextHeight(text, ctx.font); component(ctx, ctx.measureText(text).width, fontHeight, "#444", 10, 10, 5, text); testCaseIndex = (testCaseIndex + 1) % testCases.length; }, 2000) function component(ctx, width, height, color, x, y, radius, text) { var maxWidth = 300; var r = radius; var w = (width > maxWidth ? maxWidth : width) + 40; var h = ((width > maxWidth ? Math.ceil(width / maxWidth) : 1) * height) + 40; var pi2 = Math.PI * 2; var ap = w - 32; var aw = 20; var ah = 10; // Speechbubble create start ctx.beginPath(); ctx.arc(r, r, r, pi2 * 0.5, pi2 * 0.75); ctx.arc(w - r, r, r, pi2 * 0.75, pi2); ctx.arc(w - r, h - r, r, 0, pi2 * 0.25); ctx.lineTo(w - ap, h); ctx.lineTo(w - ap - (aw / 2), h + ah); ctx.lineTo(w - ap - aw, h); ctx.arc(r, h - r, r, pi2 * 0.25, pi2 * 0.5); ctx.fillStyle = color; ctx.fill(); // Speechbubble create end // Speechbubble text start ctx.fillStyle = "#fff"; wrapText(ctx, text, 25, 17, maxWidth, 16); // Speechbubble text end } // Function to wrap the text depending on the maxWidth value // Function also adds the text to the following location: x, y function wrapText(context, text, x, y, maxWidth, lineHeight) { var words = text.split(' '); var line = ''; for(var n = 0; n < words.length; n++) { var testLine = line + words[n] + ' '; var metrics = context.measureText(testLine); var testWidth = metrics.width; if (testWidth > maxWidth && n > 0) { context.fillText(line, x, y); line = words[n] + ' '; y += lineHeight; } else { line = testLine; } } context.fillText(line, x, y); } // Function to get the height of the text function getTextHeight(txt, font) { var el = document.createElement('div'), height; el.style.cssText = "position:fixed; padding:0; left:-9999px; top:-9999px; font:" + font; el.textContent = txt; document.body.appendChild(el); height = parseInt(getComputedStyle(el).getPropertyValue('height'), 10); document.body.removeChild(el); return height; }
<canvas width="1200" height="1200" id="canvas"></canvas>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.