代码之家  ›  专栏  ›  技术社区  ›  Thomas

如何在页面上的特定位置淡入移动元素?

  •  4
  • Thomas  · 技术社区  · 5 年前

    我试图创建一个CSS动画,在屏幕上移动一个元素,并使其淡入 及时 它会到达那里。

    下面是一个在Chromium中有效但在Firefox中无效的示例:

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
    }
    @keyframes mover {
      from {
        left: 0vmin;
        opacity: -3;
      }
      to {
        left: 90vmin;
        opacity: 6;
      }
    }
    .mover {
      background: red;
      animation: mover 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    <div class="mover" style="animation-timing-function: linear;"></div>
    <div class="mover" style="animation-timing-function: ease-in;"></div>
    <div class="mover" style="animation-timing-function: ease-out;"></div>
    <div class="marker"></div>

    在Chromium中,由于插值,红色块全部在蓝色块的正上方淡入 opacity 超出其预期范围[0,1]。铬似乎首先插值不透明度,然后才将其钳制到范围[0,1]。这是一个肮脏的把戏,但它有点奏效。

    我可以使它打破铬以及动画 transform 而不是 left ,从逻辑上讲,这不应该有什么区别:

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
    }
    @keyframes mover {
      from {
        transform: translate(0vmin, 0);
        opacity: -3;
      }
      to {
        transform: translate(90vmin, 0);
        opacity: 6;
      }
    }
    .mover {
      background: red;
      animation: mover 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    <<div class=“mover”style=“动画计时功能:轻松进入”></部门>
    <div class=“mover”style=“动画计时功能:放松;”gt</部门>

    这里哪个浏览器是正确的?更重要的是, 如何在不使用JavaScript的情况下实现这种效果?

    • Chromium 71.0.3578.98(官方版本)Arch Linux(64位)
    • Firefox 64.0(64位)
    1 回复  |  直到 5 年前
        1
  •  1
  •   Temani Afif BoltClock    5 年前

    考虑到您希望缓慢显示内容的事实,我将使用不同的方法来实现与不透明度类似的效果。我会考虑一个覆盖以上元素,我隐藏使用另一个动画。

    这里的想法是使用具有相同度量的动画,以便与移动器动画同步,并且仅在空间的所需点显示元素。

    90vmin - 0vmin = 90vmin )这将以相反的方向设置动画。此元素将具有渐变颜色,此颜色将创建 魔术

    以下是一个例子:

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
      z-index:0;
      overflow:hidden;
      color:#fff;
    }
    .mover:before {
      content:"";
      position:absolute;
      z-index:99;
      top:-1px;
      bottom:-1px;
      left:0;
      width:90vmin;
      background:linear-gradient(to right,#fff 33%,transparent);
      animation: fader 10s infinite;
      animation-timing-function:inherit;
    }
    
    .mover {
      background: red;
      animation: mover 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    
    @keyframes mover {
      from {
        left: 0vmin;
      }
      to {
        left: 90vmin;
      }
    }
    @keyframes fader {
      to {
        transform:translateX(-100%);
      }
    }
    <div class="mover" style="animation-timing-function: linear;">1</div>
    <div class="mover" style="animation-timing-function: ease-in;">2</div>
    <div class="mover" style="animation-timing-function: ease-out;">3</div>
    <div class="marker"></div>

    为了更好地理解正在发生的事情,让我们更改颜色并移除重叠部分:

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
      z-index:0;
      color:#fff;
      /*overflow:hidden;*/
    }
    .mover:before {
      content:"";
      position:absolute;
      z-index:99;
      top:-1px;
      bottom:-1px;
      left:0;
      width:90vmin;
      background:linear-gradient(to right,green 33%,transparent);
      animation: fader 10s infinite;
      animation-timing-function:inherit;
    }
    
    .mover {
      background: red;
      animation: mover 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    
    @keyframes mover {
      from {
        left: 0vmin;
      }
      to {
        left: 90vmin;
      }
    }
    @keyframes fader {
      to {
        transform:translateX(-100%);
      }
    }
    <<div class=“mover”style=“动画计时功能:放松;”gt;3</部门>
    <div class=“marker”></部门>

    33% 哪一个是 30vmin 因此,我们的元素将在此时开始显示。


    另一个想法是通过调整和设置背景动画来仅依赖背景 background-size background-position 因此,伪元素的大小将与主元素相同:

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
      z-index:0;
      overflow:hidden;
      color:#fff;
    }
    .mover:before {
      content:"";
      position:absolute;
      z-index:99;
      top:-1px;
      bottom:-1px;
      left:0;
      right:0;
      background-image:linear-gradient(to right,#fff 33%,transparent);
      background-size:90vmin 100%;
      background-position:left;
      animation: fader 10s infinite;
      animation-timing-function:inherit;
    }
    
    .mover {
      background: red;
      animation: mover 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    
    @keyframes mover {
      from {
        left: 0vmin;
      }
      to {
        left: 90vmin;
      }
    }
    @keyframes fader {
      to {
        background-position:right;
      }
    }
    <div class=“mover”style=“动画计时功能:线性;”gt;1</部门>
    <div class=“mover”style=“动画计时功能:轻松进入”>2</部门>

    为了控制衰落效应,我们增加了 背景尺寸 任何一个乘数 90vmin

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
      z-index:0;
      overflow:hidden;
      color:#fff;
    }
    .mover:before {
      content:"";
      position:absolute;
      z-index:99;
      top:-1px;
      bottom:-1px;
      left:0;
      right:0;
      background-image:linear-gradient(to right,#fff 33%,transparent);
      background-size:calc(var(--m,1)*90vmin) 100%;
      background-position:left;
      animation: fader 10s infinite;
      animation-timing-function:inherit;
    }
    
    .mover {
      background: red;
      animation: mover 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    
    @keyframes mover {
      from {
        left: 0vmin;
      }
      to {
        left: 90vmin;
      }
    }
    @keyframes fader {
      to {
        background-position:right;
      }
    }
    <div class="mover" style="animation-timing-function: linear;">1</div>
    <div class="mover" style="animation-timing-function: ease-in;--m:5">2</div>
    <div class="mover" style="animation-timing-function: ease-out;--m:20">3</div>
    <div class="marker"></div>

    这里有另一个想法,你可以有透明度,但没有褪色效果。诀窍是使用 clip-path 为了在需要的位置显示元素而设置动画。

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
      color:#fff;
    }
    
    .mover {
      background: red;
      animation: mover 10s infinite,
                 fader 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    
    @keyframes mover {
      from {
        left: 0vmin;
      }
      to {
        left: 90vmin;
      }
    }
    @keyframes fader {
      from {
        clip-path:polygon(30vmin 0%,  100vmin 0%,
                                      100vmin 100%,
                          30vmin 100% );
      }
      to {
        clip-path:polygon(-60vmin 0%,  10vmin 0%,
                                       10vmin 100%,
                          -60vmin 100% );
      }
    }
    
    html {
      background:radial-gradient(pink,yellow);
    }
    <<div class=“mover”style=“动画计时功能:放松;”gt;3</部门>
    <div class=“marker”></部门>

    下面是一个更好地理解发生了什么的示例:

    enter image description here

    橙色矩形是剪裁区域。它应该从标记开始( 30V分钟 )最后在 终止 考虑到元素的宽度( 90vmin + 10vmin = 100vmin

    该区域应保持固定在我们的透视图上,以便仅在元素到达标记时才能看到元素,因此我们应将其向相反方向移动,为此,我们只需更改 剪辑路径

    动画制作完成后,我们将进行以下操作:

    enter image description here

    10vmin )它应该保持相同的尺寸,因此需要从(-60vmin)开始。


    我们现在可以增加 剪辑路径 背景尺寸 衰退 效果,我们可以添加一个不透明度动画,更接近最初的要求。

    .mover, .marker {
      position: relative;
      width: 10vmin;
      height: 10vmin;
      color:#fff;
    }
    
    .mover {
      background: red;
      animation: mover 10s infinite,
                 fader 10s infinite;
    }
    .marker {
      background: blue;
      left: 30vmin;
    }
    
    @keyframes mover {
      from {
        left: 0vmin;
      }
      to {
        left: 90vmin;
      }
    }
    @keyframes fader {
      from {
        clip-path:polygon(300vmin 0%,  1000vmin 0%, /* x10*/
                                      1000vmin 100%,
                          300vmin 100% );
        opacity:0;
      }
      to {
        clip-path:polygon(-600vmin 0%,  100vmin 0%,
                                       100vmin 100%,
                          -600vmin 100% );
        opacity:1;
      }
    }
    
    html {
      background:radial-gradient(pink,yellow);
    }
    <div class=“mover”style=“动画计时功能:线性;”gt;1</部门>
    <div class=“mover”style=“动画计时功能:放松;”gt;3</部门>
    <div class=“marker”></部门>


    值得注意的是,剪辑路径仍然没有得到广泛支持( https://caniuse.com/#search=clip-path -webkit- 覆盖Safari浏览器的前缀。

    推荐文章