Zanam
Zanam

Reputation: 4807

Multi-line split of very long text on canvas (adding line breaks)

I have a working example here at sandbox

Because top text is very long it extends across both ends. I am trying to split the text dynamically into multi lines so that they get accommodated based on the size of image and length of input text.

How do I split the text into multilines when it much longer than the image width?

function drawTextBG(ctx, txt, font, x, y, txtWidth, imgWidth) {
  ctx.save();
  ctx.font = font;
  ctx.textAlign = "center";
  ctx.textBaseline = 'middle';
  ctx.fillStyle = '#FFFFFF';
  var dimen = measureText(txt, font)
  var height = dimen['height']
  var width = dimen['width']
  var fontsize = height/5
  ctx.fillRect(x - width/2, y-height/2 + fontsize/2, width, parseInt(font));
  ctx.fillStyle = '#000000';
  ctx.fillText(txt, x, y);
  ctx.restore();
}

In particular within the function I need to split the txt if txt is greater than imgWidth into smaller chunks with each chunk of max size imgWidth

Upvotes: 0

Views: 991

Answers (1)

Synthetx
Synthetx

Reputation: 609

Unfortunately canvas doesn't take "\n" into account so you have to manage multiple lines yourself.

Example over here: https://codesandbox.io/s/lucid-worker-zm0ct

From input variable 'txt'. (There is probably a more elegant way of doing this.)

  let lines = [];
  let lineCount = 0;
  let tmpTxt = txt.split(" ");
  lines[lineCount] = [];
  for(let t = 0; t < tmpTxt.length; t++){
    if(measureText(lines[lineCount].join(" "), font).width > ctx.canvas.width) {
      let lastItem = lines[lineCount].pop();
      lineCount++;
      lines[lineCount] = [lastItem];
    }
    lines[lineCount].push(tmpTxt[t]);
  }

And then you will have to render each line with a Y offset which you can get programmatically from measureText().height

  let offset = measureText(txt, font).height;
  for(let l = 0; l < lines.length; l++) {
    ctx.fillText(lines[l].join(" "), x, y + (l * offset));
  }

Upvotes: 2

Related Questions