我目前正在使用canvas
在javascript
元素上绘制一个语音小泡。
阐释:
var text
包含将添加到speechbubble的文本。var text
中存储的文本的高度。component
函数将语音气泡添加到canvas
元素,具体取决于文本的高度和宽度。wrapText
函数将在component
函数内调用,以根据传递的maxwidth值为文本添加换行符。例如,我现在传递值200,文本行将在200像素后被破坏,并将剩余的文本添加到下一个文本行。我的问题:
由于我在传递非文本行损坏文本的宽度和高度后打破文本,因此语音气泡的宽度和高度不符合最终文本(换行符号)
我的问题:
我怎样才能获得断行文本的宽度和高度以将其传递给component
函数,因此speechbubble将符合换行文本?
期望的结果:
语音气泡应该具有断线文本的宽度和高度。
Image to show the desired outcome
代码:
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;
}
&#13;
<canvas width="1200" height="1200" id="canvas"></canvas>
&#13;
答案 0 :(得分:3)
你必须添加一些逻辑和数学......
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>