簡體   English   中英

使用javascript將自適應語音氣泡添加到畫布

[英]Add responsive speechbubble to canvas using javascript

我目前正在使用javascriptcanvas元素上繪制語音氣泡。

闡釋:

  • var text包含將添加到語音泡沫中的文本。
  • 現在,getTextHeight函數將獲取存儲在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM