我目前正在使用canvasjavascript元素上绘制气泡。

说明:


var text包含将添加到语音气泡中的文本。
现在,getTextHeight函数将获取存储在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;
}

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

关于javascript - 使用javascript将自适应语音气泡添加到 Canvas ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46503374/

10-13 00:34