<body>
<div class="headings"><h1>It's Magical</h1>
<h2>Isn't it?</h2></div>
<div id="interactions">
<button>toggle default Cursor</button>
<button id="blend">toggle mix-blend-mode</button>
<button id="ballToggle">Toggle cursor-ball-amount</button>
<input value="yellow" type="color" id="color">
</div>
<div id="one" class="cursorHelper"></div>
<div id="two" class="cursorHelper"></div>
<div id="three" class="cursorHelper"></div>
<div id="four" class="cursorHelper"></div>
<div id="five" class="cursorHelper"></div>
</body>
:root {
--scale: 1;
--scaleX: 1;
--scaleY: 1;
--br: 25px;
--width: 50px;
--height: 50px;
--posX: -50px;
--posY: -50px;
--cursor: none;
--color: purple;
--blendMode: normal;
--zIndex: -2;
}
*{
cursor: var(--cursor);
}
body {
height: 100vh;
width: 100vw;
padding: 0;
margin: 0;
}
.headings {
color: white;
pointer-events: none;
user-select: none;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-family: sans-serif;
font-size: 2rem;
}
h2 {
color: lightblue;
}
.cursorHelper {
transform: translate3d(var(--posX), var(--posY), 0);
position: fixed;
top: 0;
left: 0;
z-index: var(--zIndex);
mix-blend-mode: var(--blendMode)
}
.cursorHelper::before {
pointer-events: none;
width: var(--width);
height: var(--height);
position: absolute;
content: " ";
background-color: var(--color);
border-radius: var(--br);
transition: transform 0.2s, background-color .3s, opacity .3s, border-radius .3s;
transform: scale(var(--scale));
}
.cursorHelper#one {
transition: transform .1s ease-out;
}
.cursorHelper#one::before {
transform: scale(calc(var(--scaleX) * 1), calc(var(--scaleY) * 1));
}
.cursorHelper#two {
transition: transform .2s ease-out;
opacity: .8;
}
.cursorHelper#two::before {
transform: scale(calc(var(--scaleX) * 1.2), calc(var(--scaleY) * 1.2));
}
.cursorHelper#three {
transition: transform .3s ease-out;
opacity: .6
}
.cursorHelper#three::before {
transform: scale(calc(var(--scaleX) * 1.4), calc(var(--scaleY) * 1.4));
}
.cursorHelper#four {
transition: transform .4s ease-out;
opacity: .4
}
.cursorHelper#four::before {
transform: scale(calc(var(--scaleX) * 1.6), calc(var(--scaleY) * 1.6));
}
.cursorHelper#five {
transition: transform .5s ease-out;
opacity: .2
}
.cursorHelper#five::before {
transform: scale(calc(var(--scaleX) * 1.8), calc(var(--scaleY) * 1.8));
}
body.hovering .cursorHelper:not(#one)::before {
opacity: 0;
}
#interactions {
right: 25px;
top: 25px;
position: absolute;
display: flex;
flex-direction: column;
}
#interactions > * {
margin: .5rem 0;
}
#interactions > input[type="color"] {
align-self: end;
}
.none {
display: none;
}
const cursor = document.querySelector(".cursorHelper")
const root = document.querySelector(':root')
const body = document.body
let cursorToggle = false
let isHovering = false
let color = "purple"
let zIndexIsNegative = true
let blendmodeIsOff = true
let baseScale = 1
const applyCursorPos = ({clientX, clientY}) => {
const x = `${clientX - 25}px`
const y = `${clientY - 25}px`
if(!isHovering) {
root.style.setProperty("--posX", x);
root.style.setProperty("--posY", y);
}
}
const increaseMouseSize = ({increase}) => {
root.style.setProperty("--scaleX", increase ? ".7" : baseScale);
root.style.setProperty("--scaleY", increase ? ".7" : baseScale);
}
const toggleCursor = () => {
cursorToggle = !cursorToggle
root.style.setProperty("--cursor", cursorToggle ? "auto" : "none");
}
cursorHoverState = (e, {hovering}) => {
isHovering = hovering
const rect = e.target.getBoundingClientRect();
body.classList.toggle("hovering")
root.style.setProperty("--posX", rect.x + (rect.width / 2) - 25 + "px");
root.style.setProperty("--posY", rect.y + (rect.height / 2) - 25 + "px");
root.style.setProperty("--color", hovering ? "orange" : color);
root.style.setProperty("--scaleX", hovering ? (rect.width + 10) / 50 : 1 );
root.style.setProperty("--scaleY", hovering ? (rect.height + 10) / 50 : 1 );
root.style.setProperty("--br", hovering ? "0" : "25px")
}
document.body.addEventListener("mousemove", applyCursorPos)
document.body.addEventListener("mousedown", () => {increaseMouseSize({increase: true})})
document.body.addEventListener("mouseup", () => {increaseMouseSize({increase: false})})
document.querySelector("button").addEventListener("click", toggleCursor)
document.querySelectorAll("button, a, input, select").forEach(btn => {
btn.addEventListener("mouseover", (e) => {cursorHoverState(e, {hovering: true})})
btn.addEventListener("mouseout", (e) => {cursorHoverState(e, {hovering: false})})
});
document.querySelector("input[type='color']").addEventListener("input", (e) => {
color = e.target.value
root.style.setProperty("--color", color)
})
document.querySelector("#blend").addEventListener("click", () => {
zIndexIsNegative = !zIndexIsNegative
blendmodeIsOff = !blendmodeIsOff
root.style.setProperty("--zIndex", zIndexIsNegative ? -2 : 0);
root.style.setProperty("--blendMode", blendmodeIsOff ? "normal" : "difference")
})
document.querySelector("#ballToggle").addEventListener("click", () => {
document.querySelectorAll(".cursorHelper:not(#one)").forEach(el => {
el.classList.toggle("none")
})
})
// document.querySelector(`input[type="number"]`).addEventListener("change", (e) => {
// const val = e.target.value
// baseScale = val
// root.style.setProperty("--scaleX", val);
// root.style.setProperty("--scaleY", val);
// })
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.