Animations
Adaptive cursor
05 Jul 2023
Cursor with adaptive scaling
HTML
SCSS
PostCSS
JS
<a class="link" data-adaptive-cursor href="#">About Us</a> <!--For default cursor -->
<a class="link" data-adaptive-cursor="invert" href="#">About Us</a> <!-- For cursor with color invertion -->
.link{
position: relative;
}
[data-adaptive-cursor] {
&:hover {
.adaptive-cursor {
opacity: 1;
transform: translate(-50%, -50%) scale(1.2);
}
}
&:active {
.adaptive-cursor {
transform: translate(-50%, -50%) scale(0.5) !important;
}
}
}
.adaptive-cursor {
position: absolute;
transform: translate(-50%, -50%);
z-index: -1;
display: block;
width: 24px;
height: 24px;
border-radius: 999px;
background: var(--primary-cl);
opacity: 0;
pointer-events: none;
@include transition-all(200ms);
&.adaptive-cursor--invert {
z-index: 1;
background: transparent;
backdrop-filter: invert(1);
}
}
.link{
position: relative;
}
[data-adaptive-cursor] {
&:hover {
.adaptive-cursor {
opacity: 1;
transform: translate(-50%, -50%) scale(1.2);
}
}
&:active {
.adaptive-cursor {
transform: translate(-50%, -50%) scale(0.5) !important;
}
}
}
.adaptive-cursor {
position: absolute;
transform: translate(-50%, -50%);
z-index: -1;
display: block;
width: 24px;
height: 24px;
border-radius: 999px;
background: var(--primary-cl);
opacity: 0;
pointer-events: none;
transition: setTransition(200ms, opacity, left, top, transform);
&.adaptive-cursor--invert {
z-index: 1;
background: transparent;
backdrop-filter: invert(1);
}
}
const adaptiveCursorItems = document.querySelectorAll("[data-adaptive-cursor]");
if (adaptiveCursorItems.length) {
adaptiveCursorItems.forEach((item) => {
const span = document.createElement("span");
span.classList.add("adaptive-cursor");
if (item.dataset.adaptiveCursor === "invert")
span.classList.add("adaptive-cursor--invert");
item.appendChild(span);
item.addEventListener(
"mousemove",
throttle(({ layerX, layerY, target: { offsetWidth } }) => {
span.style.left = layerX + "px";
span.style.top = layerY + "px";
let pxBetweenEdges = 0;
if (layerX > offsetWidth / 2) {
pxBetweenEdges = offsetWidth - layerX;
} else {
pxBetweenEdges = layerX;
}
pxBetweenEdges = pxBetweenEdges;
const scaleSize =
pxBetweenEdges > 20
? (pxBetweenEdges * 100) / (offsetWidth / 2) / 40
: 0.8; //For cursor min size
span.style.transform = `translate(-50%, -50%) scale(${scaleSize})`;
}, 100)
);
});
}
Посилання на Codepen для тесту.
Також для роботи потрібна функція Throttle
з бібліотеки Lodash
, її можна завантажити окремо від всієї бібліотеки.