CYCLING COLORS ON HOVER With JavaScript/jQuery
I'm trying to take a block of text, color each letter according to calculated position between HSL 0deg and 360deg, and on hover animate the colors to the right. I know this is weird, but bear with me. What I want is animated rainbow text on hover.
I've covered the logic of making all of this happen once, but can't get hover cycling behavior to work.
here is a link to the codepen.io: http://cdpn.io/txmlf
I've tried using JavaScript mouse events and jQuery's .hover(). My initial thought was to set an interval on mouse enter and clear it on exit.
I'd truly appreciate any help on this obviously very important project.
You might wanna think about how this'll affect UX, but what about this: http://jsfiddle.net/7Xuep/6/
Ok, so rotating through all the colours of the rainbow is easy enough using CSS-animations. The issue is then linking them up to all your span tags such that the animation starts in the right place. (i.e. you need the green letter to start it's animation from the colour green etc.) To do this, we can use animation-delay
:
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay
which we can use to start the rainbow animation at the appropriate colour for each letter. By using a linear
timing function, it's simple to determine at what time the animation will arrive at each colour. Therefore, it's just a matter of attaching the right animation-delay
value to each <span>
element. I do that by just taking your already generated HTML and adding in the CSS rules to each element's style
attribute:
var animTime = 6, // time for the animation in seconds
hueChange = 3, // the hue change from one span element to the next
prefixes = ["", "-webkit-", "-moz-", "-o-"],
numPrefixes = prefixes.length;
$('.unicorn').find('span').each(function (i) {
for (var j = 0; j < numPrefixes; j++) {
$(this).css(prefixes[j] + 'animation-delay', (animTime * ((i * hueChange) % 360) / 360) - animTime + 's');
}
});
but you could do this at the same time as you're generating all your span
elements.
Then it's just a case of setting up the animation using CSS:
.unicorn:hover span {
animation: colorRotate 6s linear 0s infinite;
}
@keyframes colorRotate {
from {
color: rgb(255, 0, 0);
}
16.6% {
color: rgb(255, 0, 255);
}
33.3% {
color: rgb(0, 0, 255);
}
50% {
color: rgb(0, 255, 255);
}
66.6% {
color: rgb(0, 255, 0);
}
83.3% {
color: rgb(255, 255, 0);
}
to {
color: rgb(255, 0, 0);
}
}
All this gets us to here: http://jsfiddle.net/P6WVg/7/
Now, if you don't want the colours to reset once someone is no longer hovering over .unicorn
then you can use animation-play-state
:
https://developer.mozilla.org/en-US/docs/Web/CSS/animation-play-state
However, I was finding that Chrome has an issue with combining an initial value of -webkit-animation-play-state:paused;
and a negative value of -webkit-animation-delay
such that it just displayed the first frame (i.e. color: rgb(255,0,0);
in this case). Therefore I had to use an event listener to add a class containing the animation CSS on the first hover, and this leads us to:
http://jsfiddle.net/7Xuep/6/
(that bug in chrome can be tracked here: https://code.google.com/p/chromium/issues/detail?id=269340)
Why not keep it simple, (with only your HTML) this is all you need:
Live demo
var step = 4, // colorChage step, use negative value to change direction
ms = 10, // loop every
$uni = $('.unicorn'),
txt = $uni.text(),
len = txt.length,
lev = 360/len,
newCont = "",
itv;
alert(lev+' '+len);
for(var i=0; i<len; i++)newCont += "<span style='color:hsla("+ i*lev +", 100%, 50%, 1)'>"+ txt.charAt(i) +"</span>";
$uni.html(newCont); // Replace with new content
var $ch = $uni.find('span'); // character
function stop(){ clearInterval(itv); }
function anim(){
itv = setInterval(function(){
$ch.each(function(){
var h = +$(this).attr('style').split(',')[0].split('(')[1]-step % 360;
$(this).attr({style:"color:hsla("+ h +", 100%, 50%, 1)"});
});
}, ms);
}
$uni.hover(anim,stop);
Tested in FF, Chrome, Opera
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With