Skip to content

Detecting element inside a and styling

I got some trouble with a canvas. I’ve created a bunch of words moving inside the element and I want to change the style of a single word on click. Th click function works great but: if I try to stop and scale the word the script works fine; if I try to change the color of the text it apply the transformation to another word (but stop from moving the correct one);

Here live example with codepen

This is the code to detect and style elements:

floatingWords.forEach((element) => {
                if (
                    y > element.pos.y &&
                    y <= element.pos.y + element.size &&
                    x > element.pos.x &&
                    x <= element.pos.x + element.width
                ) {
                    speed = element.speed;
                    size = element.size;
        element.opacity = 1;
                    element.speed -= speed;
                    //element.size = 120;            
                }

Answer

In the function floating.prototype.update() you need to set the fillStyle before calling fillText().

I added a color property to the elements.

$(document).ready(function() {
  $(window)
    .resize(function(event) {
      canvas = document.getElementById("canvas");
      ctx = canvas.getContext("2d");
      canvas.width = $(window).width();
      canvas.height = $(window).height();
    })
    .trigger("resize");

  createWords(36);
});

var elemLeft = canvas.offsetLeft + canvas.clientLeft,
  elemTop = canvas.offsetTop + canvas.clientTop;
var words = [
  "Lorem",
  "ipsum",
  "dolor",
  "sit",
  "amet",
  "consectetur",
  "adipiscing",
  "elit",
  "sed",
  "do",
  "eiusmod",
  "tempor",
  "incididunt",
  "ut",
  "labore",
  "et",
  "dolore",
  "magna",
  "aliqua",
  "Lorem",
  "ipsum",
  "dolor",
  "sit",
  "amet",
  "consectetur",
  "adipiscing",
  "elit",
  "sed",
  "do",
  "eiusmod",
  "tempor",
  "incididunt",
  "ut",
  "labore",
  "et",
  "dolore",
  "magna",
  "aliqua",
];
var floatingWords = [];

function floating(word) {
  this.pos = {
    x: Math.random() * canvas.width,
    y: Math.random() * canvas.height,
  };

  this.speed = Math.random() * 2 + 1;
  this.size = Math.round(Math.random() * 40 + 14);
  this.font = this.size + "px serif";
  this.color = {r:255,g:255,b:255};
  this.text = word;
  this.opacity = Math.random() * (1 - 0.1) + 0.1;
  ctx.font = this.font;
  this.width = ctx.measureText(this.text).width;

}

floating.prototype.update = function() {
  this.pos.x += this.speed;
  this.font = this.size + "px serif";


  if (this.pos.x >= canvas.width) {
    this.pos.x = -this.width;
    this.pos.y = Math.random() * canvas.height;
  }

  ctx.font = this.font;
  ctx.fillStyle = `rgba(${this.color.r},${this.color.g},${this.color.b},${this.opacity})`;
  ctx.fillText(this.text, this.pos.x, this.pos.y);
  

};

function createWords(n) {
  for (var i = 0; i < n; i++) {
    floatingWords.push(new floating(words[i]));
  }
  animateWords();
}

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

  for (var i = 0; i < floatingWords.length; i++) {
    floatingWords[i].update();
  }
  requestAnimationFrame(animateWords);
}
canvas.addEventListener("click", (event) => {
  var x = event.pageX - elemLeft;
  var y = event.pageY - elemTop;

  //console.log(x, y);
  floatingWords.forEach((element) => {
    if (
      y > element.pos.y &&
      y <= element.pos.y + element.size &&
      x > element.pos.x &&
      x <= element.pos.x + element.width
    ) {
      const word = element
      speed = element.speed;
      size = element.size;
      element.opacity = 1;
      element.speed -= speed;
      element.color = {r:255,g:0,b:0};         
    }

    if (element.speed === 0) {
      setTimeout(() => {
        element.speed += speed;
        element.size = size;
        element.color = {r:255,g:255,b:255};
      }, 1000);
    }
  });
});
html,
body {
  font-family: 'Open Sans', sans-serif;
  overflow: hidden;
  background-color: #2b2b2b;
  min-height: 100%;
  color: #fff;
}

#canvas {
  z-index: -1;
  background-image: #ffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas"></canvas>