Skip to content

Instantly share code, notes, and snippets.

@stanwmusic
Created July 1, 2020 08:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stanwmusic/832ce89ba1c41c9fba318edabc2eb317 to your computer and use it in GitHub Desktop.
Save stanwmusic/832ce89ba1c41c9fba318edabc2eb317 to your computer and use it in GitHub Desktop.
Magnetic Hover Interaction
<main>
<button>
<ion-icon name="logo-facebook"></ion-icon>
</button>
<button>
<ion-icon name="logo-twitter"></ion-icon>
</button>
<button>
<ion-icon name="logo-instagram"></ion-icon>
</button>
<button>
<ion-icon name="logo-youtube"></ion-icon>
</button>
<button>
<ion-icon name="logo-dribbble"></ion-icon>
</button>
</main>
<div class="cursor cursor--large"></div>
<div class="cursor cursor--small"></div>
<div class="support">
<a href="https://twitter.com/DevLoop01" target="_blank"><i class="fab fa-twitter-square"></i></a>
<a href="https://dribbble.com/devloop01" target="_blank"><i class="fab fa-dribbble"></i></a>
</div>
console.clear();
const { gsap } = window;
const cursorOuter = document.querySelector(".cursor--large");
const cursorInner = document.querySelector(".cursor--small");
let isStuck = false;
let mouse = {
x: -100,
y: -100,
};
// Just in case you need to scroll
let scrollHeight = 0;
window.addEventListener('scroll', function(e) {
scrollHeight = window.scrollY
})
let cursorOuterOriginalState = {
width: cursorOuter.getBoundingClientRect().width,
height: cursorOuter.getBoundingClientRect().height,
};
const buttons = document.querySelectorAll("main button");
buttons.forEach((button) => {
button.addEventListener("pointerenter", handleMouseEnter);
button.addEventListener("pointerleave", handleMouseLeave);
});
document.body.addEventListener("pointermove", updateCursorPosition);
document.body.addEventListener("pointerdown", () => {
gsap.to(cursorInner, 0.15, {
scale: 2,
});
});
document.body.addEventListener("pointerup", () => {
gsap.to(cursorInner, 0.15, {
scale: 1,
});
});
function updateCursorPosition(e) {
mouse.x = e.pageX;
mouse.y = e.pageY;
}
function updateCursor() {
gsap.set(cursorInner, {
x: mouse.x,
y: mouse.y,
});
if (!isStuck) {
gsap.to(cursorOuter, {
duration: 0.15,
x: mouse.x,
y: mouse.y,
});
}
requestAnimationFrame(updateCursor);
}
updateCursor();
function handleMouseEnter(e) {
isStuck = true;
const targetBox = e.currentTarget.getBoundingClientRect();
gsap.to(cursorOuter, 0.2, {
x: targetBox.left + targetBox.width / 2,
y: (targetBox.top + targetBox.height / 2) + scrollHeight,
width: targetBox.width,
height: targetBox.width,
borderRadius: 0,
backgroundColor: "rgba(255, 255, 255, 0.1)",
});
}
function handleMouseLeave(e) {
isStuck = false;
gsap.to(cursorOuter, 0.2, {
width: cursorOuterOriginalState.width,
height: cursorOuterOriginalState.width,
borderRadius: "50%",
backgroundColor: "transparent",
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.1.1/gsap.min.js"></script>
<script src="https://unpkg.com/ionicons@5.0.0/dist/ionicons.js"></script>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
background: rgb(18, 18, 18);
cursor: none;
}
.cursor {
width: var(--size);
height: var(--size);
border-radius: 50%;
position: absolute;
left: 0;
top: 0;
transform: translate(-50%, -50%);
pointer-events: none;
z-index: 100;
&--large {
--size: 40px;
border: 1px solid rgb(255, 60, 60);
}
&--small {
--size: 10px;
background: rgb(255, 60, 60);
}
}
main {
display: flex;
flex-wrap: wrap;
justify-content: center;
button {
--size: 60px;
border: none;
min-width: var(--size);
min-height: var(--size);
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2rem;
background: rgba(255, 255, 255, 0.08);
color: #fff;
transition: background 200ms ease, color 200ms ease;
cursor: none;
}
&:hover {
button {
background: rgba(255, 255, 255, 0.04);
color: rgba(255, 255, 255, 0.04);
&:hover {
color: #fff;
}
}
}
}
.support{
position: absolute;
right: 10px;
bottom: 10px;
padding: 10px;
display: flex;
a{
margin: 0 10px;
color: #fff;
font-size: 1.8rem;
backface-visibility: hidden;
transition: all 150ms ease;
&:hover{
transform: scale(1.1);
}
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.1/css/all.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Montserrat&amp;display=swap"rel="stylesheet" rel="stylesheet" />
@stanwmusic
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment