So I have seen lots of posts about people sharing fun little projects they have made so I would like to share my Rainbow slinky with you guys. Please go easy on me. This is my first post so I'm not entirely sure what I'm doing but anyways, lets get into it!๐
The way this will work is by creating a bunch of empty div elements. On the mousemove
event we will pull the X and Y coordinates of the mouse and then incrementally update the div's
to move to that location on the screen creating a really cool slinky effect.
HTML
To begin we will need create our markup. This will be very simple. It will consist of 2 div's
, 1 that we will use as our cursor because we will hide the default mouse cursor and then another div
to contain all the rings of our slinky.
<div id="ring_container"></div>
<div class="dot mouse_el"></div>
CSS
We can now add our CSS
. This will remove the cursor from the page, give our rings a default style and also style the dot which will become our new cursor
* {
cursor: none !important;
}
html,
body {
height: 100vh;
overflow: hidden;
background-color: #000;
}
.mouse_el {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
}
.ring {
border: 5px solid #fff;
}
.dot {
height: 10px;
width: 10px;
background-color: #fff;
}
Javascript
Now that our HTML
and CSS
is pretty much done we can get onto the logic behind the slinky. First we need to define some global variables. The rings
variable will store our collection of rings so we can use it in multiple functions. The dot
is our cursor and the colors
will be the colors we loop through when creating our div's
, in this case the colors of the rainbow but these can be changed.
let rings;
let dot = document.querySelector('.dot');
let colors = ['#9400D3', '#4B0082', '#0000FF', '#00FF00', '#FFFF00', '#FF7F00', '#FF0000'];
We now need to create the div's
and append them to the rings container. Once all the rings are created we will then set the colors of the div's
function createRings(numRings) {
if (numRings > 0) {
for (let i = 0; i <= numRings; i++) {
const div = document.createElement('div');
div.classList.add('mouse_el', 'ring');
document.getElementById('ring_container').appendChild(div);
}
setColors();
}
}
function setColors() {
let index = 0;
const dimensions = 60;
rings = document.querySelectorAll('.ring');
rings.forEach((el) => {
index = index < colors.length ? index : 0;
el.style.borderColor = colors[index];
el.style.width = dimensions + 'px';
el.style.height = dimensions + 'px';
index++;
})
}
Now we need to create the function that will update the X and Y coordinates of all the div's
. Here we will need to get the size of the border because we will need to take this into account when trying to calculate the center of the rings for the cursor.
function updateCursor(eventObj) {
let lag = 50;
const x = eventObj.clientX;
const y = eventObj.clientY;
let ringBorderSize = parseInt(window.getComputedStyle(rings[0]).getPropertyValue('border-top-width'));
calcPosition(dot, x, y, ringBorderSize);
rings.forEach((el, i) => {
lag += 50;
setTimeout(() => { calcPosition(el, x, y) }, lag + 50);
})
}
Now its time for some quick math. We need to check if the ringBorderSize > 0
because then we know that we are trying to calculate the position for the cursor in which case we will need to take the size of the borders into account or else the dot won't sit perfectly in the center of the rings.
function calcPosition(el, x, y, border_size = 0) {
if (border_size <= 0) {
el.style.left = x - (el.clientWidth / 2) + 'px';
el.style.top = y - (el.clientHeight / 2) + 'px';
} else {
el.style.left = x - ((el.clientWidth / 2) - border_size) + 'px';
el.style.top = y - ((el.clientHeight / 2) - border_size) + 'px';
}
}
The last step is to setup the eventListener
and call the createRings
function. If you find it lagging a bit, try reduce the number passed to create rings and see what works best for you
window.addEventListener('mousemove', (e) => { updateCursor(e) });
createRings(75);
I hope you guys have as much fun with this as I've had!๐ฅณ
Top comments (2)
This is very cool and fun, I love it.
Thanks Adam! Glad you like it๐