As I work on my website, I encounter the need for a cursor that smoothly changes its color. Specifically, I want the cursor to appear blue (#0059ff) when hovering over a white background and white when over a blue background, with a seamless transition like this: https://i.stack.imgur.com/szS27.png
To achieve the white color using mix-blend-mode, I calculate the inverted color by applying `adjust-hue($color, 180)` in SCSS, which gives me the desired shade for the cursor when on a white background. However, things get tricky when I try to make the cursor change to white when it is not over the white background.
Initially, I tried using `mix-blend-mode: difference` for "primary colors," such as #ff0000 and #ff00ff, which worked fine. But when dealing with #0000ff transitioning to #0059ff, the results were not satisfactory. The calculated inverted color of #ffa600 did not give the desired effect of white-on-blue and blue-on-white backgrounds.
I'm stuck at this point and unsure how to proceed to ensure the cursor displays correctly based on the background color. If you have any insights or suggestions, please share them with me!
Below is the current code snippet I've been working on:
const bigBall = document.querySelector('.cursor-ball-big');
const smallBall = document.querySelector('.cursor-ball-small');
const allHoverable = document.querySelectorAll('a, .hoverable');
TweenMax.to(bigBall, .3, {fill: 'none'});
allHoverable.forEach(hoverable => {
hoverable.addEventListener('mouseenter', () => {
TweenMax.to(bigBall, .3, {scale: 4});
TweenMax.to(bigBall.querySelector('circle'), .3, {strokeWidth: 1});
});
hoverable.addEventListener('mouseleave', () => {
TweenMax.to(bigBall, .3, {scale: 1});
TweenMax.to(bigBall.querySelector('circle'), .3, {strokeWidth: 2});
});
});
document.body.addEventListener('mousemove', e => {
const {clientX, clientY} = e;
TweenMax.to(smallBall, .1, {x: clientX - 5, y: clientY - 7});
TweenMax.to(bigBall, .4, {x: clientX - 15, y: clientY - 17});
});
:root {
--color1: #0059FF;
--color2: #FFFFFF;
--cursor: #ffa600;
}
body {
height: 100vh;
cursor: none;
margin: 0;
display: flex;
font-family: monospace;
}
.cursor {
pointer-events: none;
mix-blend-mode: difference;
}
.cursor .cursor-ball {
position: fixed;
top: 0;
left: 0;
z-index: 1000;
}
.cursor .cursor-ball.cursor-ball-small circle {
fill: var(--cursor);
}
.cursor .cursor-ball.cursor-ball-big circle {
stroke: var(--cursor);
}
a {
border-bottom: 2px solid transparent;
padding: 10px 0;
margin-top: 25px;
text-decoration: none;
display: inline-block;
cursor: none;
}
.left,
.right {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.left {
background-color: var(--color1);
}
.left a {
border-color: var(--color2);
}
.left h1,
.left p,
.left a {
color: var(--color2);
}
.right {
background-color: var(--color2);
}
.right a {
border-color: var(--color1);
}
[right h1,
.right p,
.right a {
color: var(--color1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<div class="cursor">
<div class="cursor-ball cursor-ball-big">
<svg xmlns="http://www.w3.org/2000/svg" height="30" width="30">
<circle cx="15" cy="15" r="12" stroke-width="2"/>
</svg>
</div>
<div class="cursor-ball cursor-ball-small">
<svg height="10" width="10">
<circle cx="5" cy="5" r="4" stroke-width="0"/>
</svg>
</div>
</div>
<div class="left">
<a href="#" title="Hover me">Hover me</a>
</div>
<div class="right">
<a href="#" title="Hover me">Hover me</a>
</div>