Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 Canvas - repeat text all the canvas size

Is there a way to draw inside a cavnas all the size of it? I've checked that I can repeat an image but I just want to repeat a text.

As a plus, if it the text could be shifted each line, could be great. Example of the effect I need if i set "1234567" as text:

1234567 1234567 1234567 1234567 1234567 1234567
234567 1234567 1234567 1234567 1234567 1234567 
34567 1234567 1234567 1234567 1234567 1234567 1
4567 1234567 1234567 1234567 1234567 1234567 12
567 1234567 1234567 1234567 1234567 1234567 123
67 1234567 1234567 1234567 1234567 1234567 1234
7 1234567 1234567 1234567 1234567 1234567 12345
 1234567 1234567 1234567 1234567 1234567 123456
1234567 1234567 1234567 1234567 1234567 1234567
like image 597
JoséMi Avatar asked Jan 24 '16 15:01

JoséMi


2 Answers

measureText(txt)

You can measure text with canvas

canvas.measureText(txt).width

Here is a basic example with various limitations. Some more math is needed to create bigger canvases...

txtHeight is basically line-height. offset is the distance you want to shift the text.

The rest is math which should be improved for a solid function.

Code

var b = document.createElement('canvas');
b.width = 320;
b.height = 160;
c = b.getContext("2d");

function draw(txt) {
  c.font = "20px Arial";
  var txtHeight = 25;
  var offset = 5;
  var w = Math.ceil(c.measureText(txt).width);
  var txt = new Array(w * 2).join(txt + ' '); //change the multipler for more lines
  for (var i = 0; i < Math.ceil(b.height / txtHeight); i++) {
    c.fillText(txt, -(i * offset), i * txtHeight);
  }
}
document.body.appendChild(b);
draw('1234567');

Demo

https://jsfiddle.net/wav0xmLz/1/

For more precision measuring every line or writing letter per letter would be better.

EDIT

Unless you use a monospaced font it's a mess to remove the half visible txt....as every letter has different spacing. iiii is always shorter than TTTT with non monospaced fonts.

monospaced fonts have a fixed spacing .... find that and you know exactly how width every charachter is ... do some math and your done.

You can then use split,shift,join,push to create then each line

https://jsfiddle.net/kds7zkkf/

like image 100
cocco Avatar answered Oct 11 '22 23:10

cocco


Here is a partial answer. Just the first part.

CanvasRenderingContext2D.prototype.wrapText = function (text, x, y, maxWidth, lineHeight) {

  var lines = text.split("\n");

  for (var i = 0; i < lines.length; i++) {

    var words = lines[i].split(' ');
    var line = '';

    for (var n = 0; n < words.length; n++) {
      var testLine = line + words[n] + ' ';
      var metrics = this.measureText(testLine);
      var testWidth = metrics.width;
      if (testWidth > maxWidth && n > 0) {
        this.fillText(line, x, y);
        line = words[n] + ' ';
        y += lineHeight;
      } else {
        line = testLine;
      }
    }

    this.fillText(line, x, y);
    y += lineHeight;
  }
};



var myCanvas = document.getElementById("myCanvas");
var ctx = myCanvas.getContext("2d");

ctx.font = "12px sans-serif";
ctx.textBaseline = "top";
var str = '';
for (var i = 0; i < 100; i++) {
  str += '1234567 ';
}
ctx.wrapText(str,0,0,myCanvas.width,16);
canvas {
  border:1px solid red;  
}
<canvas id="myCanvas" width="400" height="200"></canvas>

References: HTML5 canvas ctx.fillText won't do line breaks?

like image 25
Mosh Feu Avatar answered Oct 12 '22 01:10

Mosh Feu