Main ideas:

  • The mouse click event triggers the dot to appear over the mouse

  • Dot size, color, number random

  • There is a small white circle as a track, constantly changing the radius gets bigger and lighter and disappears

  • As the dot moves outward, it becomes smaller and disappears. As you move farther, your speed changes

Need to deal with the dot can be determined from the mouse to click the x, y, but still go, move is a problem, so make sure the dot target coordinates, then from the dot of the original coordinates (i.e., the mouse to click) moving to the target coordinates, and x, y is proportional to move wouldn’t in the x, y mobile distance under the condition of equal imbalance

Random generation of dot target coordinates function code:



let endpos = (x, y) => {
  let angle = random(0.360) * Math.PI / 180,
    value = random(20.150),
    radius = [-1.1] [random(0.1)] * value;

  return {
    x: x + radius * Math.cos(angle),
    y: y + radius * Math.sin(angle)
  }
}Copy the code

Because a large number of random numbers are required, a random number generating function is encapsulated



let random = (min.max) => Math.floor(Math.random() * (max - min + 1)) + min;Copy the code

For the dot movement function, we need to move from the original coordinate to the target coordinate quickly and slowly. The generation ratio is divided into three sections. The original coordinate to the first coordinate is the first segment, the first segment to the second segment is the second segment, and the second segment to the target is the third segment. If the current coordinate is in the first segment, the faster the speed, and so on

Max (current, ff) == current? (math.max (current, ff) == current? (Math.max(current, mm) == current ? S: m) : f), the second case is that the target coordinate is less than the original coordinate, then reverse, the first segment is the segment farthest from the original coordinate.



// Set the pace according to the different distance, divided into3// Distinguish the cases where the target point is smaller than the starting point. // Ratio is the proportion of the distance between two points. The greater the proportion, the slower the walk.end, current) {
    let s = random(26.35),
      m = random(20.25),
      f = random(15.20),
      ff = start.x+ ~ ~ ((end.x - start.x) / 3),
      mm = ff + ~~((end.x - start.x) / 3),
      ratio = end.x >= start.x ? (Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f) : (Math.max(current, ff) == current ? f : (Math.max(current, mm) == current ? m : s)),
      mp = {
        x: end.x - start.x,
        y: end.y - start.y
      };

    return {
      x: Math.abs(mp.x / ratio),
      y: Math.abs(mp.y / ratio)
    }
  }Copy the code

Each dot as an individual, with its own moving function, and moving target coordinates. Each time the Animation, the dot is redrawn to update the latest coordinates

Dot code:



class Circle {
  constructor(x, y) {
    this.r = random(9.13)
    this.opos = {}
    this.x = this.opos.x = x
    this.y = this.opos.y = y

    this.colors = ['#FF1461'.'#18FF92'.'#5A87FF'.'#FBF38C']
    this.color = this.colors[random(0.this.colors.length)];
    this.tpos = endpos(x, y)
  }

  creatCircle(ctx) {
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.r, 0.2 * Math.PI)
    ctx.closePath()
    ctx.fillStyle = this.color
    ctx.fill()
  }

  // According to different distance set pace, divided into three stages, the starting distance is the fastest, the middle is the average speed, the farthest is the slowest speed
  // Distinguish between cases where the target point is smaller than the starting point
  // Ratio is the walking proportion of the distance between two points. The larger the ratio value is, the slower the walking will be
  moveFun(start, end, current) {
    let s = random(26.35),
      m = random(20.25),
      f = random(15.20),
      ff = start.x + ~~((end.x - start.x) / 3),
      mm = ff + ~~((end.x - start.x) / 3),
      ratio = end.x >= start.x ? (Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f) : (Math.max(current, ff) == current ? f : (Math.max(current, mm) == current ? m : s)),
      mp = {
        x: end.x - start.x,
        y: end.y - start.y
      };

    return {
      x: Math.abs(mp.x / ratio),
      y: Math.abs(mp.y / ratio)
    }
  }

  // Move according to the calculated move value
  // If the target coordinate is larger than the original coordinate, the move to the right cannot exceed the target coordinate; otherwise, the move to the left cannot be smaller than the target coordinate
  move() {
    var movepos = this.moveFun(this.opos, this.tpos, this.x);

    this.x = (this.opos.x > this.tpos.x) ? Math.max(this.x - movepos.x, this.tpos.x) : Math.min(this.x + movepos.x, this.tpos.x)
    this.y = this.opos.y > this.tpos.y ? Math.max(this.y - movepos.y, this.tpos.y) : Math.min(this.y + movepos.y, this.tpos.y)
    this.r = Math.max(Math.abs((this.r - Math.random() / 1.2).toFixed(2)), 0)}}Copy the code

The big circle is a circle created from the mouse click, and it keeps changing its radius and expanding outward, and becoming more and more transparent. When it is big and transparent, it means that our animation is over, so using this as a standard, stop the animation and clear the screen

Large circle code:



class BigCircle {
  constructor(x, y) {
    this.bR = random(16.32)
    this.overR = random(60.100)
    this.x = x
    this.y = y
    this.op = 1
  }

  creatBigCircle(ctx) {
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.bR, 0.2 * Math.PI)
    ctx.closePath()
    ctx.strokeStyle = 'rgba(128, 128, 128, ' + this.op + ') '
    ctx.stroke()
  }

  changeR() {
    this.bR = Math.min(this.bR += random(1.4), this.overR);
    this.op = Math.max((this.op - Math.random() / 12).toFixed(2), 0)}// Check whether the operation is complete and clear the screen with a large circle as the standard
  complete() {
    return this.bR >= this.overR && this.op <= 0; }}Copy the code

Full code:



// Canvas mouse click fireworks effects

let endpos = (x, y) = > {
  let angle = random(0.360) * Math.PI / 180,
    value = random(20.150),
    radius = [- 1.1][random(0.1)] * value;

  return {
    x: x + radius * Math.cos(angle),
    y: y + radius * Math.sin(angle)
  }
}

let random = (min, max) = > Math.floor(Math.random() * (max - min + 1)) + min;

class Circle {
  constructor(x, y) {
    this.r = random(9.13)
    this.opos = {}
    this.x = this.opos.x = x
    this.y = this.opos.y = y

    this.colors = ['#FF1461'.'#18FF92'.'#5A87FF'.'#FBF38C']
    this.color = this.colors[random(0.this.colors.length)];
    this.tpos = endpos(x, y)
  }

  creatCircle(ctx) {
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.r, 0.2 * Math.PI)
    ctx.closePath()
    ctx.fillStyle = this.color
    ctx.fill()
  }

  // According to different distance set pace, divided into three stages, the starting distance is the fastest, the middle is the average speed, the farthest is the slowest speed
  // Distinguish between cases where the target point is smaller than the starting point
  // Ratio is the walking proportion of the distance between two points. The larger the ratio value is, the slower the walking will be
  moveFun(start, end, current) {
      let s = random(26.35),
        m = random(20.25),
        f = random(15.20),
        ff = start.x + ~~((end.x - start.x) / 3),
        mm = ff + ~~((end.x - start.x) / 3),
        ratio = end.x >= start.x ? (Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f) : (Math.max(current, ff) == current ? f : (Math.max(current, mm) == current ? m : s)),
        mp = {
          x: end.x - start.x,
          y: end.y - start.y
        };

      return {
        x: Math.abs(mp.x / ratio),
        y: Math.abs(mp.y / ratio)
      }
    }
    
    // Move according to the calculated move value
    // If the target coordinate is larger than the original coordinate, the move to the right cannot exceed the target coordinate; otherwise, the move to the left cannot be smaller than the target coordinate
  move() {
    var movepos = this.moveFun(this.opos, this.tpos, this.x);

    this.x = (this.opos.x > this.tpos.x) ? Math.max(this.x - movepos.x, this.tpos.x) : Math.min(this.x + movepos.x, this.tpos.x)
    this.y = this.opos.y > this.tpos.y ? Math.max(this.y - movepos.y, this.tpos.y) : Math.min(this.y + movepos.y, this.tpos.y)
    this.r = Math.max(Math.abs((this.r - Math.random() / 1.2).toFixed(2)), 0)}}class BigCircle {
  constructor(x, y) {
    this.bR = random(16.32)
    this.overR = random(60.100)
    this.x = x
    this.y = y
    this.op = 1
  }

  creatBigCircle(ctx) {
    ctx.beginPath()
    ctx.arc(this.x, this.y, this.bR, 0.2 * Math.PI)
    ctx.closePath()
    ctx.strokeStyle = 'rgba(128, 128, 128, ' + this.op + ') '
    ctx.stroke()
  }

  changeR() {
    this.bR = Math.min(this.bR += random(1.4), this.overR);
    this.op = Math.max((this.op - Math.random() / 12).toFixed(2), 0)}// Check whether the operation is complete and clear the screen with a large circle as the standard
  complete() {
    return this.bR >= this.overR && this.op <= 0; }}window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;

window.clearRequestTimeout = window.cancelAnimationFrame || window.mozCancelRequestAnimationFrame || window.webkitCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame;


let c = document.getElementById("fireworks"),
  w = c.width = c.offsetWidth,
  h = c.height = c.offsetHeight,

  ctx = c.getContext("2d"),
  nums = 40,
  circles = [],
  bCircle = null,
  animationId = false;

let int = function(x, y) {
  circles = []

  if (animationId) clearRequestTimeout(animationId)

  for (let i = nums; i-- > 0;) {
    circles.push(new Circle(x, y))
  }

  bCircle = new BigCircle(x, y)
  creat()
}

let creat = function() {
  ctx.clearRect(0.0, w, h);

  circles.forEach(function(v) {
    v.move();
    v.creatCircle(ctx)
  })

  bCircle.changeR()
  bCircle.creatBigCircle(ctx)

  animationId = requestAnimationFrame(creat)

  if (bCircle.complete()) {
    // Using the large circle as the standard, clear the screen to stop animation
    ctx.clearRect(0.0, w, h);
    clearRequestTimeout(animationId)
  }
}

c.onclick = function(e) {
  e = e || window.event;
  int(e.clientX, e.clientY)
}
Copy the code

HTML for



<canvas id="fireworks" width="500px" height="500px"></canvas>Copy the code