【问题标题】:Bugs and efficiencies in jQuery background positioning vs CSS animation positioningjQuery 背景定位与 CSS 动画定位中的错误和效率
【发布时间】:2018-01-02 13:50:19
【问题描述】:

我目前正在一个网站上工作,其中舞台/英雄有一组带有循环背景图像(文本图像)的 div,并且我正在使用 jQuery 为它们的位置设置动画,以呈现“海洋”的外观在屏幕上移动的图像。

var position = 0;

setInterval(function () { 
    position -= 1;
    $(".sub-image-1").css({ "background-position":+ position +"px 0px" }) 
}, 20 );

setInterval(function () { 
    position -= 1;
    $(".sub-image-2").css({ "background-position":+ position +"px 0px" }) 
}, 140 );

setInterval(function () { 
    position -= 1;
    $(".sub-image-3").css({ "background-position":+ position +"px 0px" }) 
}, 200 );
.stage-image {
    width:100vh;
    height:30vh;
}

.stage-sub-image { 
    position:absolute; top:0;
    width:100%;
    height:100%;
    background-repeat:repeat-x;
} 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="stage-image">
  <div class="stage-sub-image sub-image-1" style="background:url(https://upload.wikimedia.org/wikipedia/commons/c/ca/Triple-Spiral-4turns_green_transparent.png)"></div>
  <div class="stage-sub-image sub-image-2" style="background:url(https://upload.wikimedia.org/wikipedia/commons/b/be/Blender3D_Lisc_lipy-Transparent.png)"></div>
  <div class="stage-sub-image sub-image-3" style="background:url(https://cdn0.iconfinder.com/data/icons/ball/256/transparent.png)"></div>
</div>

我很好奇这个解决方案是否有更好的方法来减少浏览器密集度。我觉得setInterval 在这种情况下给网站增加了不必要的开销。有没有更好的方法来处理这样的事情?除了性能问题之外,通过 JS 完成的动画非常不稳定,我希望效果更流畅。

这是我目前在上面的 CodePen:

https://codepen.io/stufu/pen/GvJdxq

更新

@FuriousD 在下面给出了一个很好的建议,使用 CSS 来实现这一点,虽然这更接近我所希望的,但 CSS 动画在到达背景位置的末尾时会导致跳跃。

这是一个基于他们的回答的 Codepen,但在动画完成后出现了“跳跃”的新问题:

codepen.io/stufu/pen/YxXaLR

【问题讨论】:

    标签: javascript jquery html performance


    【解决方案1】:

    您可以使用 CSS 动画。注意,图片的宽度(-250px)需要硬编码到动画中,但这可以动态生成:

    var containers = $('.stage-sub-image');
    var containerWidth = $(containers[0]).width();
    var styleElem = document.createElement('style');
    var animClass = 'animateMe';
    
    document.body.append(styleElem);
    
    styleElem.innerHTML =
      '@keyframes animBg {' +
        'from { background-position: 0px top; }' +
        'to { background-position: -' + containerWidth + 'px top }' +
      '}' +
      '.' + animClass + ' { animation: animBg 10s linear infinite; background-size: 100% auto; }';
    
    
    containers.addClass(animClass);
    .stage-sub-image {
      width: 200px;
      height: 130px;
      background-color: #909;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="stage-image">
        <div class="stage-sub-image" style="background-image:url(http://via.placeholder.com/250x130)"></div>
        <div class="stage-sub-image" style="background-image:url(http://via.placeholder.com/250x130)"></div>
        <div class="stage-sub-image" style="background-image:url(http://via.placeholder.com/250x130)"></div>
    </div>

    【讨论】:

    • 感谢@FuriousD 的评论。我没有充分解释我的问题,不幸的是,使用上面硬编码的方法,这些值将无法正常工作。一旦到达宽度的末端就会出现“跳跃”
    • 您可以使用几种方法将 JS 与 CSS 动画结合使用 - 例如使用 JS 重新触发动画等等。我不确定是否有一个简单的解决方案,尽管它不涉及硬编码值。
    • 我认为这是问题的一部分。当您对宽度进行硬编码时(即使它在 vw 中),它将在最后跳过。我设置了一个代码笔来显示发生了什么:codepen.io/stufu/pen/YxXaLR 纯 JS 方法的优点是它“无限”地将背景位置更改为无限,CSS 将重新启动它。但我很难吞下 setInterval
    • 一种方法是将背景图像设置为其容器的 100% 宽度。然后,您可以动态生成 CSS 动画(它会读取类似 from { background-position-x: 0px } to { background-position-x: -(bgContainer.width()) + 'px' 的内容)并将其注入页面。它比 setInterval 工作更多,但性能更高
    • 看看我更新的答案。这种方法的缺点是背景图像将始终是其容器的 100% 宽度,因此会发生缩放。如果背景图像需要保留其原始尺寸,那么您可以合并一些代码来确定背景图像的大小并使用它来生成动画 CSS 而不是容器宽度。看到这个答案:stackoverflow.com/questions/3098404/…
    【解决方案2】:

    我想发布一个更新,在@FuriousD 的回答的帮助下,我能够成功完成此任务。最终他的见解导致了这一点,我接受了他的回答,但是我想提供一个我通过纯 CSS 完成的工作版本。

    基本上,这需要知道背景图片的尺寸。将图像编码到 CSS 动画中可以使其平滑滚动并具有良好的可伸缩性。这是我的结果:

    CSS:

    @keyframes animBg1 {
      from {
        background-position: 0px top;
      }
      to {
        background-position: -613px top;
      }
    }
    
    @keyframes animBg2 {
      from {
        background-position: 0px top;
      }
      to {
        background-position: -327px top;
      }
    }
    @keyframes animBg3 {
      from {
        background-position: 0px top;
      }
      to {
        background-position: -256px top;
      }
    }
    
    .stage-image {
      .stage-sub-image { 
        position:absolute; top:0;
        width:100vw;
        height:100vh;
        background-repeat:repeat-x;
        animation-fill-mode: forwards;
        animation-iteration-count: infinite;
        animation-timing-function: linear;
      }
      .sub-image-1 {
        animation-name: animBg1;
        animation-duration: 5s;
      }
      .sub-image-2 {
        animation-name: animBg2;
        animation-duration: 2s;
      }
      .sub-image-3 {
        animation-name: animBg3;
        animation-duration: 3s;
      }
    }
    

    HTML

    <div class="stage-image">
        <div class="stage-sub-image sub-image-1" style="background-image:url(https://upload.wikimedia.org/wikipedia/commons/c/ca/Triple-Spiral-4turns_green_transparent.png)"></div>
        <div class="stage-sub-image sub-image-2" style="background-image:url(https://upload.wikimedia.org/wikipedia/commons/1/16/Rainbow_trout_transparent.png)"></div>
        <div class="stage-sub-image sub-image-3" style="background-image:url(https://cdn0.iconfinder.com/data/icons/ball/256/transparent.png)"></div>
    </div>
    

    Codepen example

    【讨论】:

      猜你喜欢
      • 2011-05-03
      • 1970-01-01
      • 2011-07-07
      • 2011-03-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 2011-07-27
      相关资源
      最近更新 更多