I have a mouseover (hover) state I’m trying to work out. I have a set of anchors, and I’m wrapping each letter in a span and assigning a color to each from an array. What I’m looking to do is on mouseover, assign a color to each span again repeatedly in a sequence (from the array), like a constantly animating color sequence across each letter of a word.
Updated: Currently the current anchor cycles (with help from Andrew Shearer I ended up targeting the current instead of all anchors), but not each individual cycling to its next color ... it’s working but a bit weird.
A simple visual of what I’m trying to do
My start below:
var colors = [
"red",
"lightsalmon",
"violet",
"skyblue"];
$('a').each(function (index) {
var characters = $(this).text().split("");
$this = $(this);
$this.empty();
$.each(characters, function (i, el) {
$this.append(`<span style="color: ${colors[i % colors.length]}">${el}</span>`);
});
});
$('a').on('mouseover', function () {
var span = $(this).find('span');
intervalId = setInterval(function () {
color = colors.shift();
span.each(function (i) {
$(this).next().attr("style", `color:${colors[i % colors.length]}`);
});
colors.push(color);
}, 500);
}).on('mouseleave', function () {
clearInterval(intervalId);
});
https://jsfiddle.net/34bj70tn/
CodePudding user response:
To achieve the effect you're describing, you could use the setInterval
function to repeatedly reassign colors to each span
element. Inside the mouseover
event handler, you can use setInterval to call a function that updates the colors of each span element at a regular interval. You can then use the clearInterval
function to stop the interval when the mouse leaves the a
element:
var colors = [
"red",
"lightsalmon",
"violet",
"skyblue"
];
var intervalId; // Declare a variable to store the interval ID
$('a').each(function (index) {
var characters = $(this).text().split("");
$this = $(this);
$this.empty();
$.each(characters, function (i, el) {
$this.append(`<span style="color: ${colors[i % colors.length]}">${el}</span>`);
});
});
$('a').on('mouseover', function() {
// Start the interval
intervalId = setInterval(function() {
color = colors.shift();
$('span').each(function() {
$(this).css('color', color);
});
colors.push(color);
}, 1000); // Update colors every 1 second
}).on('mouseleave', function() {
// Stop the interval when the mouse leaves the element
clearInterval(intervalId);
});
CodePudding user response:
A CSS Solution
The rainbow marquee can be created using only css:
- Wrap each character in a span element
- Add some css variables to configure the marquee
- Add a key frame animation for colour sequence
- Apply the animation to each span using nth-child
Details
We can avoid having to create multiple animations by adding a negative timing delay to each character. This causes the animation to start immediately but at a forward frame. And this way each character stars with different colour.
The animations use step-end timing. This causes the animation to make sharp (rather than gradual) colour transitions like a physical marquee.
The snippet uses a bit of JavaScript on page load to wrap the text characters in spans. However, if you were to add the spans in the markup then no JavaScript is required.
Snippet
// This is called once at to wrap each character in a span to be animated.
// Alternatively, you could add the spans in the markup
document.querySelectorAll('.rainbow')
.forEach(element => {
element.innerHTML = element.innerText
.split('')
.map(char => `<span>${char}</span>`)
.join('');
});
/* Set colors and timing via root variables */
:root {
--rainbow-color-1: red;
--rainbow-color-2: lightsalmon;
--rainbow-color-3: violet;
--rainbow-color-4: skyblue;
--rainbow-speed: 1;
}
.rainbow span {
animation: calc(var(--rainbow-speed) * 1s) step-end reverse infinite;
}
.rainbow span:nth-child(4n 1) {
animation-name: rainbow-animation;
}
.rainbow span:nth-child(4n 2) {
animation-delay: calc(var(--rainbow-speed) * -0.25s);
animation-name: rainbow-animation;
}
.rainbow span:nth-child(4n 3) {
animation-delay: calc(var(--rainbow-speed) * -0.5s);
animation-name: rainbow-animation;
}
.rainbow span:nth-child(4n 4) {
animation-delay: calc(var(--rainbow-speed) * -0.75s);
animation-name: rainbow-animation;
}
@keyframes rainbow-animation {
0% {
color: var(--rainbow-color-1);
}
25% {
color: var(--rainbow-color-2);
}
50% {
color: var(--rainbow-color-3);
}
75% {
color: var(--rainbow-color-4);
}
}
/* for demo page only */
body {
font-family: sans-serif;
background-color: whitesmoke;
}
.card {
background-color: white;
box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
font-size: 2rem;
font-weight: bold;
display: inline-block;
border: 1px solid lightgray;
border-radius: 0.5rem;
padding: 1rem;
margin: 0.5rem;
}
<div >Stack Overflow!</div>
<div >Hello World</div>