Hello Coders! Welcome to another JavaScript Blog. In this, we're going to see how you can create a button which tracks the movement of your mouse cursor without using any GSAP plugin. We are also going to change the design of our default mouse cursor using pure JAVASCRIPT. Here's a preview -
That being said, let us get started.
Step - 1: Like always, create 3 files - index.html, style.css and script.js.
Step - 2: Copy the below HTML code and paste it into your code editor.
##HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CodePen - Magnetic menu (Native JS)</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="cursor-circle" class="cursor-in"></div>
<div class="container">
<a href="#">
<div class="title-container">
<div class="title">Button</div>
</div>
</a>
</div>
<script src="./script.js"></script>
</body>
</html>
Step - 3: Below is the CSS code for styling.
##CSS
:root {
--primary-color: #b74096;
--secondary-color: #F5F5DC;
--background-color: #f6f7fc;
}
html, body {
width: 100vw;
height: 100vh;
margin: 0;
}
a { text-decoration: none; }
#cursor-circle {
position: absolute;
top: -100px;
contain: layout style size;
border-radius: 50%;
background-color: var(--primary-color);
will-change: transform;
transform: translate(-50%, -50%);
z-index: 0;
}
.cursor-in {
width: 80px !important;
height: 80px !important;
transition: width .7s, height .7s, left .15s ease-out, top .15s ease-out;
}
.cursor-out {
width: 0 !important;
height: 0 !important;
transition: width .7s, height .7s;
}
.container {
width: 100%;
height: 100%;
background-color: var(--background-color);
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
}
.title-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 150px;
height: 150px;
z-index: 0;
border-radius: 50%;
}
.title-container::before {
content: '';
position: absolute;
width: 65%;
height: 65%;
background-color: var(--primary-color);
border-radius: 50%;
transition: .5s;
}
.title-container.active::before {
width: 75%;
height: 75%;
}
.title {
font-size: 24px;
font-weight: bold;
font-family: 'Roboto', sans-serif;
color: var(--secondary-color);
pointer-events: none;
z-index: 1;
transition: .5s ease-out;
}
Step - 4: Below is the JavaScript code which is the most important part in this animation.
##JS
const circle = document.querySelector('#cursor-circle')
const titleContainers = document.querySelectorAll('.title-container')
document.addEventListener('mousemove', e => {
const active = document.querySelector('.title-container.active')
if (active) {
const midTopPos = active.offsetTop + (active.clientHeight / 2)
const midLeftPos = active.offsetLeft + (active.clientWidth / 2)
circle.style.top = `${midTopPos}px`
circle.style.left = `${midLeftPos}px`
} else {
circle.style.top = `${e.pageY}px`
circle.style.left = `${e.pageX}px`
}
})
document.addEventListener('mouseenter', e => {
circle.classList.add('cursor-in')
circle.classList.remove('cursor-out')
})
document.addEventListener('mouseleave', e => {
circle.classList.remove('cursor-in')
circle.classList.add('cursor-out')
})
titleContainers.forEach(titleContainer => {
const title = titleContainer.querySelector('.title');
const activeAfter = window.getComputedStyle(titleContainer,':before')
console.log(activeAfter)
titleContainer.addEventListener('mousemove', e => {
const midWidth = titleContainer.clientWidth / 2
const midHeight = titleContainer.clientHeight / 2
title.style.transform = `translate(${(e.offsetX - midHeight) / 2.7}px,
${(e.offsetY - midWidth) / 2.7}px)`
})
titleContainer.addEventListener('mouseenter', e => {
titleContainer.classList.add('active')
})
titleContainer.addEventListener('mouseleave', e => {
title.style.transform = `translate(0, 0)`
titleContainer.classList.remove('active')
})
})
And that's it. You're done.
Let me know in the comments if you have any doubt related to this.
Follow @creocodigo for more projects and web related content.
If you find this useful, below are some other posts that I am sure you'll love.