HTML Canvas - Text moving and showing layers behind based on mouse movement

Viewed 157

This is going to be a short one. Basically, I am trying to recreate the Y as seen on the homepage of this site - https://yalantis.com/.

I've never used Canvas before and am not very proficient with JS.

I've managed to draw a canvas and got as far as getting the shape I want and a rotate animation but I cannot seem to find a source that explains how the canvas is moving on the yalantis site.

This is what I have done so far:

var canvas = document.getElementById('canvas');
const ctx = canvas.getContext("2d");
// create mouse event listener
const mouse = { x: 0, y: 0 };
function mouseEvents(e) {
  const bounds = canvas.getBoundingClientRect();
  mouse.x = e.pageX - bounds.left - scrollX;
  mouse.y = e.pageY - bounds.top - scrollY;
}
document.addEventListener("mousemove", mouseEvents);

// draw design at x,y and rotated by angle
function drawRotated(x, y, angle) {
  ctx.setTransform(1, 0, 0, 1, x, y);
  ctx.rotate(angle);
  ctx.beginPath();
  // ctx.arc(0, 0, 100, 0, Math.PI * 2);
  // ctx.moveTo(-100, 0);
  // ctx.lineTo(100, 0);
  // ctx.lineTo(60, -80);
  // ctx.stroke();
  ctx.font = '600pt Rig Sans';
  ctx.lineWidth = 1;
  ctx.strokeStyle = 'blue';
  ctx.strokeText('W', x, y);
  ctx.closePath();
  ctx.stroke();
}

// render loop called 60 times a second
function update(timer) {
  ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
  ctx.clearRect(0, 0, 300, 300);

  // get angle from center to mouse
  var angle = Math.atan2(mouse.y - 150, mouse.x - 150);

  // draw rotated design
  drawRotated(150, 150, angle);
  requestAnimationFrame(update);
}
requestAnimationFrame(update);



  $('#canvas').attr('height', $(document).height());
  $('#canvas').attr('width', $(document).width());

Although this is also a bit of a bust since it's duplicating itself on every mousemove and rotating on the spot in a weird position.

Any help would be appreciated. Thanks.

1 Answers

You could do something similar to this by drawing multiple letters and then offsetting them based on mouse position.

In the mouse position I offset the x and y by the position of the drawn letter, in this case the center of the canvas.

    mouse.x = e.x - bounds.x - canvas.width/2;
    mouse.y = e.y - bounds.y - canvas.height/2;

So when my mouse is positioned over the middle of the letter it appears as one letter. Now in my loop to create each letter I can use the i to offset each iteration. Dividing by 10 is just a number I picked to keep the letters from moving too much. Same with multiplying i*0.25. That's just based on what I thought looked good for how far each letter moves from the one before.

    ctx.strokeText('W', x - (mouse.x/10*(i*0.25)), y - (mouse.y/10*(i*0.25)));
    ctx.fillText('W', x - (mouse.x/10*(i*0.25)), y - (mouse.y/10*(i*0.25)));

You'll see the further away the mouse gets from the center of the letter the more spread each iteration of letter has.

var canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
let bounds = canvas.getBoundingClientRect();
// create mouse event listener
const mouse = { x: 0, y: 0 };
function mouseEvents(e) {
  bounds = canvas.getBoundingClientRect();
  mouse.x = e.x - bounds.x - canvas.width / 2;
  mouse.y = e.y - bounds.y - canvas.height / 2;
}
canvas.addEventListener("mousemove", mouseEvents);

// draw design at x,y and rotated by angle
function drawRotated(x, y) {
  ctx.textAlign = "center";
  ctx.beginPath();
  ctx.font = "300pt Rig Sans";
  ctx.fillStyle = "black";
  ctx.shadowColor = "rgb(255, 153, 51)";
  ctx.strokeStyle = "rgba(255, 153, 51, 0.2)";
  let j = 1;
  for (let i = 7; i > 1; i--) {
    ctx.lineWidth = j;
    ctx.shadowBlur = j;
    ctx.strokeText(
      "W",
      x - (mouse.x / 10) * (i * 0.25),
      y - (mouse.y / 10) * (i * 0.25)
    );
    ctx.fillText(
      "W",
      x - (mouse.x / 10) * (i * 0.25),
      y - (mouse.y / 10) * (i * 0.25)
    );
    ctx.closePath();
    j++
  }
}

function update() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  // draw rotated design
  drawRotated(canvas.width / 2, canvas.height / 2 + 100);
  requestAnimationFrame(update);
}
update();

window.addEventListener("resize", () => {
  bounds = canvas.getBoundingClientRect();
  canvas.width = innerWidth;
  canvas.height = innerHeight;
});
//$('#canvas').attr('height', $(document).height());
//$('#canvas').attr('width', $(document).width());
<canvas id="canvas"></canvas>

There may be a better way to do this but it's something to get you started.

Related