Нужно нарисовать блок и за мышкой его двигать. Чтобы при появлении и исчезновении он не прыгал относительно курсора, нужно самому блоку — курсору задать смещение.
В этом примере я сделал через отрицательый margin. При наведении на блок, где должен менять курсор — срабатывает плавное появление из центра кргуляшка ровно где курсор.
class Cursor {
constructor(options = {}) {
this.containerClass = '.j-cursor-container';
this.cursorClass = '.j-cursor';
this.cursor = document.querySelector(this.cursorClass);
this.container = document.querySelector(this.containerClass);
}
init() {
this._createCursor();
if (window.innerWidth > 1200) {
this._moveCursor();
}
}
_moveCursor() {
const cursor = this.cursor;
if (!cursor) {
this._createCursor();
}
document.addEventListener('mousemove', (event) => {
if (event.target.closest('.j-cursor-container') && !event.target.classList.contains('j-no-cursor')) {
this._showCursor();
this.cursor.innerHTML = event.target.closest('.j-cursor-container').dataset.title || '';
const contRect = document.body.getBoundingClientRect();
const cursRect = cursor.getBoundingClientRect();
let cursX = event.clientX - contRect.left - cursRect.width / 2;
const cursY = event.clientY - contRect.top - cursRect.height / 2;
cursor.style.top = `${cursY}px`;
cursor.style.left = `${cursX}px`;
}
else {
this._hideCursor();
}
}, {passive: true});
}
_createCursor() {
const cursor = this.cursor;
if (!cursor) {
document.body.insertAdjacentHTML('beforeend', '<div class="cursor j-cursor"></div>');
}
}
_showCursor () {
this.cursor.classList.remove('cursor-hide');
}
_hideCursor () {
this.cursor.classList.add('cursor-hide');
}
}
export default Cursor;.cursor {
display: none;
@media #{$desktop} {
display: flex;
align-items: center;
justify-content: center;
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 0 0 16px 0 rgba(255, 255, 255, 0.25) inset;
background-color: rgba(28, 29, 57, 0.5);
backdrop-filter: blur(5px);
--o-filter: blur(5px);
position: absolute;
z-index: 6;
pointer-events: none;
@include contentSmallTitleFont();
text-align: center;
transition: 0.1s ease-in-out;
transition-property: transform;
transform-origin: center center;
margin-top: -100px;
margin-left: -100px;
}
@media #{$ultra} {
width: 240px;
height: 240px;
margin-top: -120px;
margin-left: -120px;
}
&-hide {
transform: scale(0);
}
&-container {
@media #{$desktop} {
@media (hover) {
cursor: none !important;
}
}
}
}