loading...
Cover image for Let's code some happy text.

Let's code some happy text.

victorqribeiro profile image Victor Ribeiro ・2 min read

Happy Text

Let's start this tutorial by normalizing the CSS.

body {
  margin: 0;
  padding: 0;
}

canvas {
  display: block;
}

This will get rid of side bars when working with a full sized canvas.

Now, let's create a canvas the same size as the page and append it to the body of the page.

const canvas = document.createElement('canvas');
const w = innerWidth,
  h = innerHeight,
  w2 = w / 2,
  h2 = h / 2;
canvas.width = w;
canvas.height = h;

document.body.appendChild(canvas);

Now we can get a canvas 2D context and define some text as well some text parameters.

const c = canvas.getContext('2d');
const fontsize = 30;
c.font = fontsize + "px Arial";

let text = "Happy Text!";

Then we create a function that clear the canvas and draws our text to screen every frame.

function draw() {

  /* clear the canvas from 0,0 to w,h - width and height of the page */
  c.clearRect(0, 0, w, h);

  /* draw the text on coords 10, 10 */
  c.fillText(text, 10, 10 );

  /* calls the draw function every frame */
  requestAnimationFrame(draw);
}

draw();

Well, that's all fine, but that text is not happy at all.

Instead of just drawing the text, we should draw each letter individually and then animate them.

We can do that with a for loop, iterating each char from the text, and with a sine wave, controlling the Y position of each letter.

So, now our draw function looks like this:

/* angle that controls the sine wave */
let a = 0;

/* the size of the text, so we can centralize it on the screen */
const xoffset = c.measureText(text).width;

function draw() {
  c.clearRect(0, 0, w, h);
  /* for loop to iterate each char from text */
  for (let i = 0; i < text.length; i++) {
    c.fillText(text[i], 
      (w2 - xoffset) + (i * fontsize), /* centralized X position */
      h2 + (Math.sin(a - i) * 10)); /* sine wave offset by char position */
  }
  a += 0.08; /* increase the angle each frame, so the sine wave moves */
  requestAnimationFrame(draw);
}

draw();

That's it. Our happy text is all done.

The complete code:

const canvas = document.createElement('canvas');
const w = innerWidth,
  h = innerHeight,
  w2 = w / 2,
  h2 = h / 2;
canvas.width = w;
canvas.height = h;

document.body.appendChild(canvas);

const c = canvas.getContext('2d');
const fontsize = 30;
c.font = fontsize + "px Arial";

let text = "Happy Text!";

let a = 0;

const xoffset = c.measureText(text).width;

function draw() {
  c.clearRect(0, 0, w, h);
  for (let i = 0; i < text.length; i++) {
    c.fillText(text[i],
      (w2 - xoffset) + (i * fontsize),
      h2 + (Math.sin(a - i) * 10));
  }
  a += 0.08;
  requestAnimationFrame(draw);
}

draw();

Link to JSFiddle with the code.

Posted on by:

Discussion

markdown guide