Skip to content

Canvas Partical Network Animation#

What Is The Canvas Partical Network Animation?#

  • One day, when I was working and I looked into the desktop of my wife, she sat next to me, and I saw she is accessing a website with beautiful effect as in the image below.

 #zoom

  • So from that time, I took some hours for searching on google about it and I got the key word for this effect, it is Canvas Partical Network Animation.
  • Then I continue to search and found the source code for on this github. Then I started playing with it.

The Problem In This Source Code#

  • I tried to clone the source and run it, everything is good until I put more sone div above the canvas. The my mouse and the point in the canvas are not synchronized. Let's see the image below.

 #zoom

  • If you are not clear, please continue to view the image below.

 #zoom

  • So, this issue is not a big deal but it brings me a little bit bad experience. So, I decided reading the source code to find the root cause.

The Root Cause#

  • After reading the source code and researched on Google, I found the root cause in the source code as below.
particle-network.js
1
2
3
4
5
6
7
8
9
...

// Mouse event listeners  
this.canvas.addEventListener('mousemove', function (e) {  
  this.mouseParticle.x = e.clientX - this.canvas.offsetLeft;  
  this.mouseParticle.y = e.clientY - this.canvas.offsetTop;  
}.bind(this));

...
  • As you can see, there is a function which is used for calculating the point in the canvas with the mouse position. In which, the x is the vertical coordinate and y is the horizontal coordinate of the point inside the canvas.
  • Then for calculating the x coordinate of the point, it uses e.clientX - this.canvas.offsetLeft;. In which.
    • e.clientX returns the horizontal client coordinate of the mouse pointer when a mouse event occurs.
    • this.canvas.offsetLeft returns the number of pixels that the upper left corner of the current element is offset to the left within the offsetParent node.
  • Then for calculating the y coordinate of the point, it uses e.clientY - this.canvas.offsetTop;. In which.

    • e.clientY returns the vertical client coordinate of the mouse pointer when a mouse event occurs.
    • this.canvas.offsetTop returns the distance of the outer border of the current element relative to the inner border of the top of the offsetParent, the closest positioned ancestor element.
  • Okay, so to understand why this formula is not correct in this case, let's continue follow these steps below.

  • Firstly, let's check the HTML file in this source code.
<html>
    <head>
        <style type="text/css">
            body {
                margin:0;
                padding:0;
            }
            #particle-canvas {
                width:100%;
                height:100%;
            }
        </style>
    </head>
    <body>
        <div>This is the div 1</div>
        <div>This is the div 2</div>
        <div>This is the div 3</div>
        <div>This is the div 4</div>
        <div>This is the div 5</div>
        <div>This is the div 6</div>
        <div id="particle-canvas"></div>
        <script type="text/javascript" src="particle-network.min.js"></script>
        <script type="text/javascript">
            var canvasDiv = document.getElementById('particle-canvas');
            var options = {
                particleColor: '#888',
                background: 'img/demo-bg.jpg',
                interactive: true,
                speed: 'medium',
                density: 'high'
            };
            var particleCanvas = new ParticleNetwork(canvasDiv, options);
        </script>
    </body>
</html>
  • As you can see, the particle-canvas div is used for creating the ParticleNetwork and it is the last div in the body. Then when we open the browser and inspect the element, you can see the canvas tag is created inside this div as in the image below.

 #zoom

  • So we have the parent of the canvas tag is the particle-canvas div and the distance between particle-canvas div and canvas tag is 0 for both canvas.offsetLeft and canvas.offsetTop.
  • So with 0 values, we can have the formula below.
particle-network.js
1
2
3
4
5
6
7
8
9
...

// Mouse event listeners  
this.canvas.addEventListener('mousemove', function (e) {  
  this.mouseParticle.x = e.clientX;  
  this.mouseParticle.y = e.clientY;  
}.bind(this));

...
  • Then the point is calculated based on the e.clientX and e.clientY. However, the canvas is not displayed fully in the viewport because we have some divs above it. So applying the e.clientY for the y of the point is not correct and the point will be dropped down from the mouse position with the distance equal to the distance of the canvas to the top of the viewport. Let's see the image below to understand how is the formula wrong in this case.

 #zoom

  • In general, using this.canvas.offsetLeft and this.canvas.offsetTop in calculating the position of the point in canvas is not correct because they return the distance from the canvas to the parent div of it. So we need to find another way to calculate it.

The Solution#

  • After taking some research on the google, I found a way to get the distance of the canvas to the top and to the left of the viewport no matter how many div in between. It is Element.getBoundingClientRect() which return a DOMRect object providing information about the size of an element and its position relative to the viewport. See the image below.

 #zoom

So let's update the formula in the source as below, then the issue will be fixed

particle-network.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
...

// Mouse event listeners  
this.canvas.addEventListener('mousemove', function (e) {  
  var canvasRect = this.canvas.getBoundingClientRect();  
  this.mouseParticle.x = e.clientX - canvasRect.left;  
  this.mouseParticle.y = e.clientY - canvasRect.top;  
}.bind(this));

...

 #zoom

Summary#

  • Finally, after the fixing this issue for the canvas partical network animation, I applied it into the homepage of this website. It's great right?. From this issue, I learnt a lots although I doesn't know the Javascript before.
    • Sometimes, putting some comments in the source to explain complicated code or is necessary because without it maybe I would not fix this issue by myself.
    • Don't scare when you have to work on the programming language that you are not good at. Believe me, be confident, just read it and at least I think you can understand what does it say?
    • Google is a good friend, when you need a solution for something, let's try to search and search.
    • Basic concept is very important, like the offsetTop or offsetLeft I took a lot of time to understand why did I always got 0. So I usually write down concepts, core functions when I learn something new.

Reference#