【问题标题】:Change background image on pagescroll to create animation? Is canvas more efficient?更改页面滚动上的背景图像以创建动画?画布更有效吗?
【发布时间】:2014-09-22 18:00:57
【问题描述】:

我正在一个视差网站上工作,其中有一系列图像(大约 400 张图像)。背景图像根据页面滚动而变化,以创建平滑移动的动画。我设法让滚动工作,但是当用户滚动时,背景图像的变化并不顺畅(我们可以看到空白区域一秒钟左右,具体取决于互联网连接)。此外,图像没有被缓存,页面每次都会发出新请求。如何优化此代码以使动画流畅,并且不会每次都请求新图像并使用缓存的图像。在画布中创建动画效率高吗?我尝试了画布,但它也会对每个滚动上的图像提出新的请求。这是我使用基于页面滚动的标准背景更改的代码:

HTML

<div class="container">
    <div id="background-images" class="background-images">
        <div class="test"></div>
    </div>
</div>

CSS

#background-images{
    height: 4000px;
}
.container{
    border: 1px solid red;
    height: 400px;
    overflow: auto;
}
.test{
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    width: 600px;
    height: 600px;
}

Javascript

var $container = $(".container");
var $bgImage = $(".test");

// Attaching the scroll to the background image
$container.scroll(function(event) {
    var position = $container.scrollTop();
    setBgImage(position);
});

// preload the given total amount of iamges
function preload(totalImages) {
    for (var i = 0; i < totalImages; i++) {
        $('<img/>')[0].src = getImgUrl(i);
    }
}
preload(36); // Preload 36 images, the cache should keep these so we wont't need to load these while we scroll

// Set the background image
function setBgImage(position){
    var imageNum;
    var lineCount = 0;

    imageNum = parseInt(position  / 100);

    console.log("IMG: " + imageNum + ", Position: " + position);
    $bgImage.css("background-image", "url('" + getImgUrl(imageNum) + "')");
}
// Set a placeholder background image
function getImgUrl(num){
    return "http://placehold.it/200x200/&text=" + num;  
}

JSFiddle:http://jsfiddle.net/4j9u8qtf/1/

【问题讨论】:

  • 您能否打开 firebug 或 chrome 开发工具并验证您的资源是否按预期通过预加载加载(网络选项卡)?
  • 是的。它加载状态码为 200 的所有内容,然后每次页面滚动时都会以状态 200 再次加载它们
  • 查看this excellent answer 了解如何预加载背景图片。
  • 可能无关紧要,但是您在测试时是否打开了控制台?打开控制台可能会使事情变慢很多,尤其是当您正在安慰某些事情时(在每个滚动事件中都是如此)
  • 我尝试删除控制台日志并关闭控制台,但同样的问题仍然存在。问题只是延迟是因为接收图像的时间。

标签: javascript jquery css scroll background-image


【解决方案1】:

您可以添加所有隐藏的图像,并在实际图像元素中显示正确的图像,而不是使用 css 背景图像。我编辑了你的 jsfiddle 来演示:

function create(totalImages) {
    for (var i = 0; i < totalImages; i++) {
        var img = $('<img/>')
        img[0].src = getImgUrl(i);
        $bgImage.append(img)
    }
    setBgImage(0)
}

create(37);

function setBgImage(position){
    var imageNum;
    var lineCount = 0;

    imageNum = parseInt(position  / 100);

    console.log("IMG: " + imageNum + ", Position: " + position);

    $bgImage.find("img").hide().eq(imageNum).show()
}

http://jsfiddle.net/y92g7vvL/1/

【讨论】:

  • 看起来不错,但我不确定 jQuery 在滚动时更新图像的速度有多快。我会及时通知你进展如何。谢谢
  • 更新图像应该不是问题。如果你有很多图片,你必须按需加载它们,这里我们在启动时加载所有图片,如果它们很大并且数量太多,那就太多了。
【解决方案2】:

预加载图像的最佳方法是使用Image 构造函数,如下例所示。使用Image 构造函数可以让您不必担心将图像附加到文档的任何位置以使其加载。

function preload(url) {
  var image = new Image();
  image.src = url;
}

我更新了your Fiddle 以使用此预加载并且不使用jQuery 来设置background-image。它现在工作得很好。所有图像仅预加载/加载一次。

$(function () {
    var $container = $(".container");
    var $bgImage = $(".test");
    var bgImage = $bgImage.get(0);

    $container.scroll(function (event) {
        var position = $container.scrollTop();
        setBgImage(position);
    });

    // preload the given total amount of iamges
    function preload(totalImages) {
        function fetch(url) {
          var image = new Image();
          image.src = url;
        }

        for (var i = 0; i < totalImages; i++) {
            fetch(getImgUrl(i));
        }
    }

    preload(36);

    function setBgImage(position) {
        var imageNum;
        var lineCount = 0;

        imageNum = parseInt(position / 100);
        var url = getImgUrl(imageNum);

        bgImage.style.backgroundImage = "url('"+ url +"')";
    }


    function getImgUrl(num) {
        return "http://placehold.it/200x200/&text=" + num;
    }
})

【讨论】:

    【解决方案3】:

    试试

    html

    <div class="container">
        <div id="background-images" class="background-images">
            <div class="test"></div>
        </div>
    </div>
    <!-- hidden container for `img` elements -->
    <div id="imgs"></div>
    

    css

    #imgs {
      display:none;
    }
    

    js

    $(function () {
        var $container = $(".container");
        var $bgImage = $(".test");
    
        $container.scroll(function (event) {
            var position = $container.scrollTop();
            setBgImage(position);
        });
    
        // preload the given total amount of iamges
        function preload(totalImages) {
            for (var i = 0; i < totalImages; i++) {
                $('<img/>', {
                    "src": getImgUrl(i)
                })
                // append `img` elements to `#imgs` container
                // to `cache` the images , 
                // images not requested again at 
                // `$bgImage` `background-image` adjustments
                .appendTo("#imgs");
    
            }
        }
    
        preload(36);
    
        function setBgImage(position) {
            var imageNum;
            var lineCount = 0;
    
            imageNum = parseInt(position / 100);
    
            console.log("IMG: " + imageNum + "
                       , Position: " + position
                       , $("#imgs img[src$=" + imageNum + "]"));
    
            // utilize images already in DOM ,  
            // load `#imgs img` `src` as `$bgImage` `background-image` , 
            // from hidden `#imgs` `div`
            // images _not_ requested again from server , 
            // see `network` tab at console 
            $bgImage.css("background-image"
            , "url('" + $("#imgs img[src$=" + imageNum + "]").attr("src") + "')");
        }
    
    
        function getImgUrl(num) {
            return "http://placehold.it/200x200/&text=" + num;
        }
    });
    

    jsfiddle http://jsfiddle.net/guest271314/bh91g0tv/

    【讨论】:

      【解决方案4】:

      一遍又一遍地请求它们的原因是您正在使用 jQuery 背景分配,它会重新加载图像。

      这很愚蠢。您在这里不需要或不需要 jQuery,它具有您不了解的副作用,导致您的问题。

      只需设置背景的 X 位置即可。完成。

      function offset_to(id, posX, posY) {
          document.getElementById(id).style.backgroundPosition = posX.toString() + 'px ' + posY.toString() + 'px';
      }
      

      【讨论】:

        【解决方案5】:

        要为您的图像过渡创建平滑效果,只需在您的情况下添加 css 过渡:-

        .test{
            -webkit-transition: all 0.5s ease;
            -moz-transition: position 10s;
            -ms-transition: position 10s;
            -o-transition: position 10s;
            transition: all 0.8s ease;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-09-30
          • 1970-01-01
          • 2011-02-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-13
          • 1970-01-01
          相关资源
          最近更新 更多