繁体   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