【教你】js如何实现平滑的 CSS渐变过渡?💭

2,481 阅读5分钟

jym好😘,我是珑墨,今天给大家分享如何写出平滑的css渐变过渡,嘎嘎的😍,看下面

引言:如果你尝试仅使用 CSS 对渐变进行动画处理或过渡,最终会遇到一个问题 - 所有现代浏览器本身都无法平滑地过渡渐变中的颜色。💢因此,如果我们尝试悬停或与从一个渐变过渡到另一个渐变的元素进行交互,我们最终会突然发生变化,即使与类似的东西一起使用也是如此。transition: all 0.1s ease-out如下:

68f5a9a2753e4843858600339c911b87_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.webp

一、单纯的css实现,并不能平滑过渡😓

image.png

#gradient-button {
    background: linear-gradient(180deg, #ff7147, #e0417f);
    padding: 0.5rem 1.5rem;
    transition: all 0.1s ease-out;
    font-variation-settings: 'wght' 500;
    font-size: 1.25rem;
    border-radius: 100px;
    transform: scale(1);
    margin: 0 0 2rem 1rem;
}

#gradient-button:hover {
    background: linear-gradient(45deg, #0037ff, #00adff);
    transform: scale(1.1);
}

使用 CSS 和 js 对渐变进行动画处理和过渡😍

在本文中,我将研究如何解决这个问题,我将介绍如何使用 Javascript 平滑地为渐变过渡设置动画。这意味着创建一个能够在多种颜色之间平滑过渡的功能。😍

虽然没有原生方法可以有效地做到这一点,但我们可以使用Javascript来做到这一点。下面的按钮解决了这个问题,允许我们在您将鼠标悬停在按钮上时使用 Javascript 和一些 CSS 平滑地制作渐变过渡动画。🧐

CSS 中两个渐变之间的平滑过渡😎

第一步,我们需要创建一个函数,允许我们在两种颜色之间找出一种颜色。为此,我们需要我们开始的颜色,以及我们想要过渡到的颜色。

我们将创建的函数如下所示。➡它可以支持超过 2 种颜色的渐变 - 但为此,我们只使用两种。我们还将采用初始渐变颜色,并将其应用于我们的按钮 - 这样我们就可以完全从我们的 Javascript 中操作渐变。

    const gradientStopOne = [
        { pct: 0,  color: { r: 255, g: 113, b: 71 } }, // 渐变中的第一种颜色
        { pct: 100, color: { r: 0, g: 55, b: 255 } }   // 你想让你的第一种颜色过渡到的颜色
    ];
    const gradientStopTwo = [
        { pct: 0,  color: { r: 224, g: 65, b: 127 } }, // 渐变中的第二种颜色
        { pct: 100, color: { r: 0, g: 173, b: 255 } }  // 你想让第二种颜色过渡到的颜色
    ]
    const complexGradientOne = [
        { pct: 0,  color: { r: 224, g: 65, b: 127 } }, 
        { pct: 33, color: { r: 0, g: 173, b: 255 } },
        { pct: 66, color: { r: 203, g: 252, b: 5 } },
        { pct: 100, color: { r: 98, g: 5, b: 252 } }
    ]
    const complexGradientTwo = [
        { pct: 0,  color: { r: 255, g: 113, b: 71 } },
        { pct: 33,  color: { r: 0, g: 55, b: 255 } },
        { pct: 66, color: { r:30, g: 177, b: 7 } },
        { pct: 100, color: { r:228, g: 44, b: 200 } }
    ]
    // 以编程方式应用我们的渐变,这样我们就可以完全从JS而不是CSS操作渐变
    let c1 = gradientStopOne[0].color;
    let c2 = gradientStopTwo[0].color;
    document.getElementById('gradient-button-transition').style.background = `linear-gradient(${angle}deg, rgb(${c1.r}, ${c1.g}, ${c1.b}), rgb(${c2.r}, ${c2.g}, ${c2.b}))`;
   
    // 这个函数在两种rgb颜色之间转换
    const getColor = function(pct, colorSet) {
        for (var i = 1; i < colorSet.length - 1; i++) {
            if (pct < colorSet[i].pct) {
                break;
            }
        }
        // 这个转换计算出两个rgb值之间的转换
        var lower = colorSet[i - 1];
        var upper = colorSet[i];
        var range = upper.pct - lower.pct;
        var rangePct = (pct - lower.pct) / range;
        var pctLower = 1 - rangePct;
        var pctUpper = rangePct;
        var color = {
            r: Math.floor(lower.color.r * pctLower + upper.color.r * pctUpper),
            g: Math.floor(lower.color.g * pctLower + upper.color.g * pctUpper),
            b: Math.floor(lower.color.b * pctLower + upper.color.b * pctUpper)
        };
        // 返回rgb代码e
        return `rgb(${color.r}, ${color.g}, ${color.b})`;
    }

✔现在我们有一个函数可以让我们在两种颜色之间过渡,并且已经定义了我们的渐变,我们可以开始在它们之间过渡了。我们将创建一个函数来设置一个间隔 - 根据用户是否悬停,我们将操作动画的方向。💕

下面代码中的注释解释了我们在这里尝试做什么。间隔每 16.67 毫秒运行一次 - 或每秒运行 60 次。这将为我们提供每秒 60 帧的流畅动画。在间隔函数中,我们计算帧总数,并在过渡时间结束时停止动画。🍭

    let previousTime, start = 0;        // <-- 将数据存储在动画中
    let angle = 180;                    // <-- 倾斜角
    let animationDirection = 'forwards' // <-- 存储动画方向
    let intervalFrame;                          // <-- 存储间隔帧
    let currentPct = 0;                         // <-- 通过动画的当前百分比
    let elapsed = 0;  // <-- 已经失效的帧数
    
        // 这是我们在悬停时运行的动画
    const animateGradient = function() {
        if(intervalFrame === undefined) {
            intervalFrame = setInterval(() => {
                let time = transitionTime / 1000; // time in seconds
                let numberOfFrames = time * 60; // 60 frames per second -> 1 second = 60 frames
                
                // 如果动画是向前的
                if(animationDirection === 'forwards') {
                    // 给elapsed加1
                    elapsed += 1;
                    // 超出最大帧数的经过帧数
                    currentPct = Math.min(elapsed / numberOfFrames, 1) * 100;
                }
                else {
                    // 否则我们要往回走,从ellapped减去1
                    elapsed -= 1;
                    // 超出最大帧数的经过帧数
                    currentPct = Math.max(elapsed / numberOfFrames, 0) * 100;
                }
                
                // 在此时间内计算每个渐变颜色的当前颜色
                let colorOne = getColor(currentPct, gradientStopOne);
                let colorTwo = getColor(currentPct, gradientStopTwo);

                // 生成CSS字符串
                let generateGradient = `linear-gradient(${angle}deg, ${colorOne}, ${colorTwo})`;

                // 将它添加到我们的背景中.
                document.getElementById(element).style.backgroundImage = generateGradient;

                // 结束后就结束停止
                if(currentPct === 100 || currentPct === 0) {
                    clearInterval(intervalFrame);
                    intervalFrame = undefined;
                }
            }, 16.667); // 60 frames per second
        }
    };

最后放到侦听器中,运行。当用户悬停时,我们会更新动画方向,以便我们可以将渐变移动到我们想要的颜色。

        animationDirection = 'forwards';
        animateGradient();
    });
    document.getElementById('gradient-button-transition').addEventListener('mouseleave', function() {
        animationDirection = 'backwards';
        animateGradient();
    });

多种颜色渐变过渡🧐

💖由于我们可以运行多种颜色,并且还可以随时运行 - 我们可以创建一些有趣的效果,可以在 4 种不同的渐变之间自动过渡:image.png

结语🍭

虽然现在的CSS是不可能的,但Javascript实际上给了我们更大的灵活性,可以平滑地为我们的渐变过渡制作动画。

感谢jym浏览本文🤞,若有更好的建议,欢迎评论区讨论哈🌹。

如果jym觉得这篇干货很有用,加个关关🥰,点个赞赞🥰,后面我会继续卷,分享更多干货!感谢支持!😍