代码之家  ›  专栏  ›  技术社区  ›  Yoda ESG

如何在元素内更流畅地设置背景渐变的旋转动画?

  •  0
  • Yoda ESG  · 技术社区  · 7 年前

    我有一个按钮,我想通过旋转它来设置它的背景动画:

    .gradient-button {
      animation: rotate-gradient 1s infinite;
      background-image: linear-gradient(0deg, red, yellow, green);
    }
    
    @keyframes rotate-gradient {
      0% {
        background-image: linear-gradient(0deg, red, yellow, green);
      }
      /* Adding a step in the middle */
      20% {
        background-image: linear-gradient(60deg, red, yellow, green);
      }
      40% {
        background-image: linear-gradient(120deg, red, yellow, green);
      }
      60% {
        background-image: linear-gradient(180deg, red, yellow, green);
      }
      80% {
        background-image: linear-gradient(240deg, red, yellow, green);
      }
      100% {
        background-image: linear-gradient(300deg, red, yellow, green);
      }
    }
    <button id="fill" class="gradient-button">Fill Form</button>

    但是只有6个步骤和动画不流畅,手动添加24帧是适得其反的。

    或者我试过JS:

    $(document).ready(function () {
        AnimateRotate(360);
    });
    
    
    function AnimateRotate(d){
        var elem = $("#mybutton");
    
        $({deg: 0}).animate({deg: d}, {
            duration: 2000,
            step: function(now){
                elem.css({
                     "background-image":"linear-gradient("+now+"deg, red, yellow, green);"
                });
            }
        });
    }
    

    但那没用。 问:如何使这部动画流畅? 运行代码: https://codepen.io/anon/pen/OaojNP

    3 回复  |  直到 7 年前
        1
  •  3
  •   Chris W.    7 年前

    如果是我,我可能会采取一个不同的路线错觉,因为线性渐变将很难做一个平滑的关键帧动画,而不经过每一个属性的变化。相反,作为一种替代方法,也许对伪元素的转换可以得到相同的期望结果?

    像这样的;

    .gradient-button {
      position: relative;
      overflow: hidden;
      background-color: transparent;
    }
    
    .gradient-button:after {
      content: '';
      display: block;
      z-index: -1;
      position: absolute;
      top: -2rem; right: 0; bottom: -2rem; left: 0;
      background-image: linear-gradient(red, yellow, green);
      animation: rotate-gradient linear 1s infinite;
    }
    
    @keyframes rotate-gradient {
      to { transform: rotate(360deg) }
    }
    <button id="fill" class="gradient-button">Fill Form</button>
        2
  •  3
  •   tao    7 年前

    background-image 不是 . 您可以添加一个绝对定位(伪)元素并使用transform来旋转它,只要您隐藏溢出并确保限制永远不可见。

    但是如果你 真正地 想要一个旋转的背景(因为它很酷,而且你可以),你可以使用 <svg>

    <svg width="240" height="60" version="1.1" xmlns="http://www.w3.org/2000/svg">
      <defs>
          <linearGradient id="Gradient" x1="0" x2="0" y1="0" y2="1">
            <animate attributeName="x1" values="0;0;1;1;0" keyTimes="0;.25;.5;.75;1" dur="1s" repeatCount="indefinite" />
            <animate attributeName="y1" values="0;1;1;0;0" keyTimes="0;.25;.5;.75;1" dur="1s" repeatCount="indefinite" />
            <animate attributeName="x2" values="1;1;0;0;1" keyTimes="0;.25;.5;.75;1" dur="1s" repeatCount="indefinite" />
            <animate attributeName="y2" values="1;0;0;1;1" keyTimes="0;.25;.5;.75;1" dur="1s" repeatCount="indefinite" />
            <stop offset="0%" stop-color="red"/>
            <stop offset="50%" stop-color="yellow"/>
            <stop offset="100%" stop-color="green"/>
          </linearGradient>
      </defs>
      <rect x="0" y="-90" width="240" height="240" fill="url(#Gradient)"/>
      
    </svg>

    澄清 :我发布这个答案是因为这是唯一的方法(我知道)实际旋转渐变背景的方向而不旋转元素本身。它可能在某些边缘情况下很有用,在这种情况下,一个人需要对其他东西进行元素转换,或者他们不想转换它。
    可能的用例:复杂的容器形状(思考路径)或需要溢出的元素。

    polyfill

    也就是说,仅仅因为它在技术上是可能的,并不意味着它应该被优先考虑 transform . 我的直觉是SMIL有点贵(就计算而言),但我还没有进行任何测试来支持这一点。
    也, 不太冗长,因此更实用。

        3
  •  2
  •   ksav    7 年前

    你能改变你的标记吗?如果是这样,可以在单独的元素上设置旋转动画。

    .gradient-button {
      position: relative;
      overflow: hidden;
      width: auto;
      display: inline-block;
    }
    
    .gradient-button>.bg {
      position: absolute;
      width: 100%;
      height: 100%;
      background-position: center center;
      background-image: linear-gradient(90deg, red 45%, yellow 50%, green 55%);
      animation: spin 1s linear infinite;
    }
    
    .gradient-button>.label {
      position: relative;
    }
    
    @keyframes spin {
      from {
        transform: rotate(0deg) scale(5);
      }
      to {
        transform: rotate(360deg) scale(5);
      }
    }
    <a id="fill" class="gradient-button">
      <span class="bg"></span>
      <span class="label">Fill Form</span>
    </a>

    Codepen