Make SVG follow cursor using CSS and JS
Tags: beginners, webdev, css, javascript
Published: 2022-01-09 15:29:09

In this article, we are going to make an SVG Eye that will follow the mouse pointer with a clean UI and smooth transition. First, As always let's see what are we building.

#PREVIEW

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ccgl9mpy95eryjuax67.gif)
#HTML
```
<img src="face-with-rolling-eyes.png" class="image">
  <div class="container">
    <svg width="100" height="100" class="eye">
        <circle cx="50" cy="50" r="50" fill="white" class="eyeball_left" />
        <circle cx="50" cy="50" r="20" fill="#0D0D20" class="pupil_left" />
    </svg>
    <svg width="100" height="100" class="eye">
      <circle cx="50" cy="50" r="50" fill="white" class="eyeball_right" />
      <circle cx="50" cy="50" r="20" fill="#0D0D20" class="pupil_right" />
    </svg>
  </div>
```
We will have an outer div with class `.container`. It will have two separate children SVG which will be the eyes of our character.
Inside SVG we create 2 circles one for eyeball and one for pupil.
The `img` tag will be the face of the character

I guess now you have an overview of what are we doing. Now let's get into the CSS.
#CSS

```
body{
    margin:0;
    padding:0;
    background: #282631;
    display: flex;
    width: 100%;
    height:100vh;
  }
  .container{
    margin: auto;
  }
  .image{
    position: absolute;
    top: 250px;
    left: 620px;
    z-index: -1;
  }
  .pupil_left{
    position:relative;
  }
  .pupil_right{
    position:relative;
  }
```
Everything above is self-explanatory but If you have any queries then comment down.

#JAVASCRIPT
This is where the fun begins. Let's see from the scratch.
First, we need to find elements with an "`eyeball_left`" and "`pupil_left`" class
```
    let eyeball_left = document.querySelector(".eyeball_left"),
    pupil_left = document.querySelector(".pupil_left"),

```
Now, We will get the radius of the circles to find the center of the circles. The `getBoundingClientRect` returns a DOMRect object with eight properties: left, top, right, bottom, x, y, width, height.
```
    eyeArea_left = eyeball_left.getBoundingClientRect(),
    pupil_leftArea = pupil_left.getBoundingClientRect(),
    R_left = eyeArea_left.width/2,
    r_left = pupil_leftArea.width/2,
    centerX_left = eyeArea_left.left + R_left,
    centerY_left = eyeArea_left.top + R_left;

```
Copy the same code for right eye. Just change the variable names to `###_right` for right Eye.
```
    let eyeball_right = document.querySelector(".eyeball_right"),
    pupil_right = document.querySelector(".pupil_right"),
    eyeArea_right = eyeball_right.getBoundingClientRect(),
    pupil_rightArea = pupil_right.getBoundingClientRect(),
    R_right = eyeArea_right.width/2,
    r_right = pupil_rightArea.width/2,
    centerX_right = eyeArea_right.left + R_right,
    centerY_right = eyeArea_right.top + R_right;

```
Now, let us create a mouse event. Through which, we will find the distance between the pointer and center of the eyeball. `Math.atan2` will return the angle in radians between the two points. By using the formula, we can convert radian to degree.
Using this angle we will position the pupil inside the eyeball
```
document.addEventListener("mousemove", (e)=>{
  let x_left = e.clientX - centerX_left,
      y_left = e.clientY - centerY_left,
      theta_left = Math.atan2(y_left,x_left),
      angle_left = theta_left*180/Math.PI + 360;

```
Create a same for the right eye
```
  let x_right = e.clientX - centerX_right,
      y_right = e.clientY - centerY_right,
      theta_right = Math.atan2(y_right,x_right),
      angle_right = theta_right*180/Math.PI + 360;
  
  

```
Finally, we will use JS style property to move and rotate the pupil inside the Eye to follow the cursor
```
  pupil_left.style.transform = `translateX(${R_left - r_left +"px"}) rotate(${angle_left + "deg"})`;
  pupil_left.style.transformOrigin = `${r_left +"px"} center`;

  pupil_right.style.transform = `translateX(${R_right - r_right +"px"}) rotate(${angle_right + "deg"})`;
  pupil_right.style.transformOrigin = `${r_right +"px"} center`;

});
```
Now we have covered all the aspects of this now let's see the full Javascript code.

```
<script>
    let eyeball_left = document.querySelector(".eyeball_left"),
    pupil_left = document.querySelector(".pupil_left"),
    eyeArea_left = eyeball_left.getBoundingClientRect(),
    pupil_leftArea = pupil_left.getBoundingClientRect(),
    R_left = eyeArea_left.width/2,
    r_left = pupil_leftArea.width/2,
    centerX_left = eyeArea_left.left + R_left,
    centerY_left = eyeArea_left.top + R_left;

    let eyeball_right = document.querySelector(".eyeball_right"),
    pupil_right = document.querySelector(".pupil_right"),
    eyeArea_right = eyeball_right.getBoundingClientRect(),
    pupil_rightArea = pupil_right.getBoundingClientRect(),
    R_right = eyeArea_right.width/2,
    r_right = pupil_rightArea.width/2,
    centerX_right = eyeArea_right.left + R_right,
    centerY_right = eyeArea_right.top + R_right;

document.addEventListener("mousemove", (e)=>{
  let x_left = e.clientX - centerX_left,
      y_left = e.clientY - centerY_left,
      theta_left = Math.atan2(y_left,x_left),
      angle_left = theta_left*180/Math.PI + 360;

  let x_right = e.clientX - centerX_right,
      y_right = e.clientY - centerY_right,
      theta_right = Math.atan2(y_right,x_right),
      angle_right = theta_right*180/Math.PI + 360;
  
  
  pupil_left.style.transform = `translateX(${R_left - r_left +"px"}) rotate(${angle_left + "deg"})`;
  pupil_left.style.transformOrigin = `${r_left +"px"} center`;

  pupil_right.style.transform = `translateX(${R_right - r_right +"px"}) rotate(${angle_right + "deg"})`;
  pupil_right.style.transformOrigin = `${r_right +"px"} center`;

});
</script>
```
The final product will look like:-

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g4a59uhad9nigc6gz9nf.gif)

You can use the following CSS in `body` selector to change the cursor by any image

```
cursor: url("heart.png"), auto;
```
# Wrapping Up
I hope you enjoyed the article, if yes then don't forget to press ❤️. You can also bookmark it for later use. It was fun to make this Project and If you have any queries or suggestions don't hesitate to drop them. See you again.