absolute-hover-cursor
Version:
Elevate user experience with seamless cursor interactions using hover-cursor, a small JS library. Create captivating web interfaces by dynamically crafting bespoke hover cursors that you can style however you need.
152 lines (151 loc) • 7.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HoverCursor = void 0;
var gsap_1 = require("gsap");
require("./main.css");
var HoverCursor = /** @class */ (function () {
function HoverCursor(options) {
var _this = this;
this.mothers = document.querySelectorAll(options.containerQuery) || null;
this.snapPosition = options.snapPosition || null;
this.callbackFunction = options.toggledFunction;
this.activeTitle = options.title;
this.activeIcon = options.icon;
this.toggledIcon = options.toggledIcon;
if (this.mothers === null) {
console.error('No containerQuery specified!');
return;
}
this.mothers.forEach(function (mother) {
var cursorElement = null;
var moveHandler;
mother.style.position = 'relative';
// Handle mouse enter
mother.addEventListener('mouseenter', function () {
mother.style.cursor = 'none'; // Hide default cursor
// Only create and append the cursor once
if (!cursorElement) {
cursorElement = _this.registerCustomCursor(options.customClass || '');
mother.appendChild(cursorElement);
// Create move handler function to track mouse movement
moveHandler = function (event) {
_this.updateCursorPosition(cursorElement, event, mother);
};
// Add the move event listener
mother.addEventListener('mousemove', moveHandler);
// Snap cursor if needed
if (_this.snapPosition !== null) {
_this.snapCustomCursor(cursorElement);
}
}
});
// Handle mouse leave
mother.addEventListener('mouseleave', function () {
if (cursorElement) {
// If snapPosition is null, remove the cursor
if (_this.snapPosition === null) {
cursorElement.remove();
}
else {
// Otherwise snap cursor
_this.snapCustomCursor(cursorElement);
}
// Clean up event listener to avoid duplication
mother.removeEventListener('mousemove', moveHandler);
// Reset cursor element reference after it's removed
cursorElement = null;
}
});
// Handle mouse click (toggle content)
mother.addEventListener('click', function () {
_this.activeTitle = _this.activeTitle === options.title ? options.toggledTitle : options.title;
_this.activeIcon = _this.activeIcon === options.icon ? options.toggledIcon : options.icon;
_this.toggleCustomCursorContent(mother);
if (_this.callbackFunction) {
_this.callbackFunction();
}
});
});
}
HoverCursor.prototype.updateCursorPosition = function (cursorElement, event, mother) {
var x = event.clientX, y = event.clientY; // <- Get mouse position from MouseEvent
var containerRect = mother.getBoundingClientRect(); // <- Get container position and size
var containerScaleX = gsap_1.gsap.getProperty(mother, 'scaleX');
var containerScaleY = gsap_1.gsap.getProperty(mother, 'scaleY');
var containerTransformX = gsap_1.gsap.getProperty(mother, 'x');
var containerTransformY = gsap_1.gsap.getProperty(mother, 'y');
// Calculate the actual position within the scaled and transformed container
var containerX = (x - containerRect.left - containerTransformX) / containerScaleX; // <- Calculate cursor X position within container
var containerY = (y - containerRect.top - containerTransformY) / containerScaleY; // <- Calculate cursor Y position within container
gsap_1.gsap.to(cursorElement, { left: "".concat(containerX, "px"), top: "".concat(containerY, "px"), duration: 0 }); // <- Animate cursor to cursor position
};
HoverCursor.prototype.snapCustomCursor = function (cursorElement) {
if (this.snapPosition === null)
return; // If snapPosition is null, do nothing
// Snap cursor to snapPosition (snap mode) - note we do not use right or bottom here as we do not want to override the transform origin or any previously calculated transform values
switch (this.snapPosition) {
case 'L':
gsap_1.gsap.to(cursorElement, { left: '10%', top: '50%', duration: 0.2 });
break;
case 'M':
gsap_1.gsap.to(cursorElement, { left: '50%', top: '50%', duration: 0.2 });
break;
case 'R':
gsap_1.gsap.to(cursorElement, { left: '90%', top: '50%', duration: 0.2 });
break;
}
};
HoverCursor.prototype.registerCustomCursor = function (customClass) {
var cursor = document.createElement('div');
var cursorTitle = document.createElement('p');
var cursorIcon = document.createElement('img');
customClass ? cursor.classList.add("hover-cursor", customClass) : cursor.classList.add("hover-cursor");
cursorTitle.classList.add("hover-cursor--title");
cursorIcon.classList.add('hover-cursor--icon');
if (this.activeIcon) {
cursorIcon.src = this.activeIcon;
cursorIcon.alt = 'Custom cursor icon';
cursorIcon.width = 35;
cursorIcon.height = 35;
}
cursorTitle.innerHTML = this.activeTitle || '';
cursor.appendChild(cursorTitle);
cursor.appendChild(cursorIcon);
return cursor;
};
HoverCursor.prototype.toggleCustomCursorContent = function (mother) {
var cursor = mother.querySelector('div.hover-cursor');
if (cursor === null) {
console.error('Cursor not found, please open an issue at https://bitbucket.org/absm/hover-cursor if you see this.');
return;
}
var cursorTitle = cursor.querySelector('p.hover-cursor--title');
var cursorIcon = cursor.querySelector('img.hover-cursor--icon');
if (cursorTitle === null || cursorIcon === null) {
console.error('cursorTitle or cursorIcon not found, please open an issue at https://bitbucket.org/absm/hover-cursor if you see this.');
return;
}
cursorTitle.innerHTML = this.activeTitle || '';
cursorIcon.src = this.activeIcon || '';
};
HoverCursor.prototype.setIcon = function (icon) {
this.activeIcon = icon;
// Update the icon for any existing custom cursors
var cursor = document.querySelector('div.hover-cursor');
var cursorIcon = cursor === null || cursor === void 0 ? void 0 : cursor.querySelector('img.hover-cursor--icon');
if (cursorIcon) {
cursorIcon.src = icon; // Change the icon to the new source
}
};
HoverCursor.prototype.setToggledIcon = function (icon) {
this.toggledIcon = icon;
// Update the toggled icon for any existing custom cursors
var cursor = document.querySelector('div.hover-cursor');
var cursorIcon = cursor === null || cursor === void 0 ? void 0 : cursor.querySelector('img.hover-cursor--icon');
if (cursorIcon) {
cursorIcon.src = icon; // Change the toggled icon to the new source
}
};
return HoverCursor;
}());
exports.HoverCursor = HoverCursor;