我正在尝试创建一个动画重复模式(水平滑动的斜条纹),作为加载块的占位符(在本例中为 li)。

如何使动画平滑/连续,给人一种图案无限滑动的错觉?

  • 如何计算元素 width 使模式连续? (条纹不应该看起来破损/中断)。
  • 如何让它循环看起来不是重新启动而是无限滑动? (100% 帧应该无任何故障地传递到 0% 帧)

  • 目标是拥有一个可以添加到任何块的类,并且在视觉上看起来像加载/处理。

    注意: 没有 JS;纯 CSS。

    li {
      display: inline-block;
      width: calc(20px * 8); /* how to calculate this, relative to the width (of the pattern or the step), to achieve pattern continuity exactly?
        Of course without doing trying&error to know it should be 24.75px * 8.
      */
      height: 200px;
      background-color: blue;
    
      background-image: repeating-linear-gradient(-45deg, transparent, transparent 10px, black 10px, black 20px);
      animation: loading-slide 1s linear infinite;
    
    }
      @keyframes loading-slide {
        from { background-position: 0% 0% }
        to { background-position: 100% 0% }
      }
    <ul>
        <li>test
        <li>test
    </ul>

    最佳答案

    正确的公式应该是 (20px / cos(45deg)) * N 。然后,您可以将 background-size 设为 200% 100%(比元素大两倍),并从左到右对其进行动画处理:

    li {
      display: inline-block;
      width: calc( (20px / 0.707) * 3); /*cos(45deg) = 0.707*/
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(-45deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    
    .alt li {
      width: calc( (20px / 0.707) * 6);
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>

    您可以考虑任何程度并根据需要调整公式。 (20px / cos(90deg - |Xdeg|)) * NX 之间的 -90deg90deg-60deg 示例

    li {
      display: inline-block;
      width: calc((20px / 0.866) * var(--n,3)); /*cos(30deg) = 0.866*/
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(-60deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    
    .alt li {
      --n:6;
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>
    30deg 示例

    li {
      display: inline-block;
      width: calc((20px / 0.5) * var(--n,8)); /*cos(60deg) = 0.5*/
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(30deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    
    .alt li {
      --n:12;
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>
    80deg 示例

    li {
      display: inline-block;
      width: calc((20px / 0.9848) * var(--n,8)); /*cos(10deg) = 0.9848*/
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(80deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    
    .alt li {
      --n:12;
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>

    您可以清楚地识别 X=+/-90deg(垂直条纹)和我们将有 cos(0)=1 的微不足道的情况,因此公式将是 20px * N 。此外,当 X=0 (水平条纹)我们将有 cos(90deg) = 0 并且任何宽度都可以工作,因为没有垂直模式(公式不再定义)

    li {
      display: inline-block;
      width: calc(20px * var(--n,8));
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(90deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    
    .alt li {
     background-image:repeating-linear-gradient(0deg, transparent, transparent 10px, black 10px, black 20px);
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>

    [-90deg,90deg] 之外的值呢?
    上面的范围已经涵盖了 180deg 并且由于我们正在处理一些对称的东西,所以所有的值都可以在该范围内表示。
    示例:110deg-70deg 相同

    li {
      display: inline-block;
      width: calc((20px / 0.9396) * var(--n,8)); /*cos(20deg) = 0.9396*/
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(110deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    .alt li {
      --n:12;
      background-image: repeating-linear-gradient(-70deg, transparent, transparent 10px, black 10px, black 20px);
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>

    示例:-150deg30deg 相同

    li {
      display: inline-block;
      width: calc((20px / 0.5) * var(--n,4)); /*cos(60deg) = 0.5*/
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      background-image: repeating-linear-gradient(-150deg, transparent, transparent 10px, black 10px, black 20px);
      background-size: 200% 100%;
      background-color: blue;
      animation: loading-slide 3s linear infinite;
    }
    .alt li {
      --n:6;
      background-image: repeating-linear-gradient(30deg, transparent, transparent 10px, black 10px, black 20px);
    }
    
    @keyframes loading-slide {
      from {
        background-position: left;
      }
      to {
        background-position: right;
      }
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>

    基本上我们添加/删除 180deg 直到我们进入 [-90deg,90deg] 以便能够应用公式。

    检查此答案以获取有关 background-size/background-position 如何工作的更多详细信息:Using percentage values with background-position on a linear-gradient

    另一种方法
    这是一个完全不同的想法,您可以依赖 skew 转换和伪元素。这里的技巧是您不必根据条纹定义宽度,但条纹将遵循您将定义的宽度,因此更易于处理。

    li {
      display: inline-block;
      width: calc( 20px * 3); /* it's only 20px * N */
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      position:relative;
      z-index:0;
      overflow:hidden
    }
    li::before {
      content:"";
      position:absolute;
      top:0;
      bottom:0;
      left:0;
      width:400%;
      /*we keep 0deg in the gradient*/
      background-image: repeating-linear-gradient(90deg, transparent, transparent 10px, black 10px, black 20px);
      transform:skewX(30deg);
      transform-origin:bottom left;
      animation: loading-slide 4s linear infinite;
    }
    
    @keyframes loading-slide {
      to {
        transform: translateX(-50%) skewX(30deg);
      }
    }
    
    .alt li {
      width: calc( 20px * 6);
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul class="alt">
      <li>test</li><li>test</li>
    </ul>

    如您所见,我们保留了垂直渐变,我们根据渐变的宽度定义元素的宽度。我们使伪元素足够大,并对其应用翻译。您唯一需要调整的是倾斜变换以控制程度。
    使用这种方法,您还将获得更好的性能,因为您将动画转换而不是 background-size
    更多例子:

    li {
      display: inline-block;
      width: calc( 20px * var(--n,3)); /* it's only 20px * N */
      height: 50px;
      margin-bottom:10px;
      background-color: blue;
      position:relative;
      z-index:0;
      overflow:hidden
    }
    li::before {
      content:"";
      position:absolute;
      top:0;
      bottom:0;
      left:-400%;
      right:-800%;
      /*we keep 0deg in the gradient*/
      background-image: repeating-linear-gradient(90deg, transparent, transparent 10px, black 10px, black 20px);
      transform:skewX(var(--d,30deg));
      animation: loading-slide 12s linear infinite;
    }
    
    @keyframes loading-slide {
      to {
        transform: translateX(-50%) skewX(var(--d,30deg));
      }
    }
    <ul>
      <li>test</li><li>test</li>
    </ul>
    
    <ul style="--n:6;--d:45deg">
      <li>test</li><li>test</li>
    </ul>
    <ul style="--n:8;--d:-70deg">
      <li>test</li><li>test</li>
    </ul>
    <ul style="--n:8;--d:30deg">
      <li>test</li><li>test</li>
    </ul>

    关于css - 如何使用线性渐变创建无限背景图案动画?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54909275/

    10-09 14:56