【问题标题】:Cycling animation of rainbow-coloured text彩虹色文字的循环动画
【发布时间】:2024-05-21 22:55:02
【问题描述】:

使用 JavaScript/jQuery 在悬停时循环颜色

我正在尝试获取一段文本,根据 HSL 0deg 和 360deg 之间的计算位置为每个字母着色,然后在悬停时将颜色动画向右。我知道这很奇怪,但请耐心等待。 我想要的是悬停时的动画彩虹文字。

我已经介绍了让所有这一切发生一次的逻辑,但无法让悬停循环行为发挥作用。

这里是 codepen.io 的链接: http://cdpn.io/txmlf

我尝试过使用 JavaScript 鼠标事件和 jQuery 的 .hover()。我最初的想法是在鼠标进入时设置一个间隔并在退出时将其清除。

对于这个显然非常重要的项目,我非常感谢任何帮助。

【问题讨论】:

  • 显然非常重要的项目???????????? +1
  • 是的,您没有看到 kickstarter 活动? :)

标签: javascript jquery css css-animations


【解决方案1】:

您可能想考虑一下这将如何影响用户体验,但是这又如何:http://jsfiddle.net/7Xuep/6/

好的,所以使用 CSS 动画旋转彩虹的所有颜色很容易。然后问题是将它们链接到所有跨度标签,以便动画在正确的位置开始。 (即,您需要绿色字母从绿色等开始动画。)为此,我们可以使用animation-delay

https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay

我们可以使用它为每个字母以适当的颜色开始彩虹动画。通过使用linear 计时函数,很容易确定动画将在什么时间到达每种颜色。因此,只需将正确的animation-delay 值附加到每个<span> 元素即可。为此,我只需获取您已经生成的 HTML 并将 CSS 规则添加到每个元素的 style 属性:

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');
    }
});

但您可以在生成所有span 元素的同时执行此操作。 那么这只是一个使用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);
    }
}

所有这些都将我们带到这里:http://jsfiddle.net/P6WVg/7/

现在,如果您不想在有人不再将鼠标悬停在 .unicorn 上时重置颜色,那么您可以使用 animation-play-state

https://developer.mozilla.org/en-US/docs/Web/CSS/animation-play-state

但是,我发现 Chrome 在将初始值 -webkit-animation-play-state:paused; 和负值 -webkit-animation-delay 组合在一起时存在问题,因此它只显示第一帧(即在这种情况下为 color: rgb(255,0,0);)。因此,我不得不使用事件监听器在第一次悬停时添加一个包含动画 CSS 的类,这导致我们:

http://jsfiddle.net/7Xuep/6/

(可以在此处跟踪 chrome 中的错误:https://code.google.com/p/chromium/issues/detail?id=269340

【讨论】:

  • 哟,我试图避免在样式表中添加任何 CSS,但使用 js 操作 CSS。想要利用硬件加速,但将所有需要的代码留在一个 js 文件中。你的回答非常有帮助,所以我会选择它作为正确的,但如果你对我上面描述的事情有任何建议,那就太好了。
  • @Todd 这应该使用 JS 动态插入 CSS:jsfiddle.net/BYoassrian/7Xuep/4
  • @Todd Opera 似乎在动态注入 CSS 时遇到了问题,所以我做了一些微调以使其正常工作:jsfiddle.net/BYoassrian/7Xuep/5
  • 抱歉,响应时间太长了。令人难以置信的工作,我的朋友。你得到的赏金正确吗?非常感谢。
  • 我知道这已经有 4 年历史了,但在硬件加速性能方面,这仍然可能是最好的方法吗?我知道渐变在移动设备上慢得要命。你们怎么看?
【解决方案2】:

为什么不保持简单,(仅使用您的 HTML)这就是您所需要的:

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);

在 FF、Chrome、Opera 中测试

【讨论】:

  • 我也非常喜欢这个解决方案。我唯一的问题是关于 var “lev”。对于大于 360 的长度,lev 似乎为零。@Roko
  • 抱歉含糊不清,@Roko。我不明白你为什么使用基数为 10 的 parseInt() 方法。当 txt.length 大于 360 时,它返回 0。为了解决这个问题,我将 lev 设置为 360/len。当我遍历字符时,我设置了 hue = (Math.ceil(ilev)lev) : 360
  • @Todd 已编辑,您完全正确,我不知道我为什么使用 parseInt... 感谢您的说明
  • 如何让它在没有悬停的情况下工作,所以它总是会重复元素
  • @IdanShechter 见 JS 底部:jsbin.com/eZUwUZE/4/edit?html,js,output