4

我为我当前的代码创建了一个 jsfiddle。http://jsfiddle.net/gL5sB/38/

我正在尝试更改滚动事件的正文背景 css。当背景发生变化时,当 css 更新并加载新图像时,它会闪烁。有时它看起来很顺利,然后似乎变得更糟。很奇怪。好奇是否有人知道如何优化?

我正在预加载图像。不知道为什么闪烁。有任何想法吗?

$(document).ready(function () {
    switchImage();
});

$(window).scroll(function () {
    switchImage();
});

var pics = []; // CREATE PICS ARRAY

//PRELOAD FUNCTION TO SET UP PICS ARRAY IN MEMORY USING IMAGE OBJECT
function preload() {
    for (i = 0; i < arguments.length; i++) {
        pics[i] = new Image();
        pics[i].src = arguments[i];
        //alert("preload " + arguments[i]);
    }
}
preload(
    'bgImage/100.jpg',
    'bgImage/101.jpg',
    'bgImage/102.jpg',
    'bgImage/103.jpg',
    'bgImage/104.jpg',
    'bgImage/105.jpg',
    'bgImage/106.jpg',
    'bgImage/107.jpg',
    'bgImage/108.jpg',
    'bgImage/109.jpg',
    'bgImage/110.jpg',
    'bgImage/111.jpg',
    'bgImage/112.jpg',
    'bgImage/113.jpg'
);

function switchImage() {
    var s = $(window).scrollTop()/10;
    var index = Math.floor(s / 5);

    $('body').css('background-image', 'url(' + pics[index].src + ')');
}
4

4 回答 4

3

为什么不使用一个图像(精灵图像)并移动它background-position而不是替换图像?(关于大小 - 您可以根据background-size您的情况设置百分比 - 高度将为1400%

因为无论如何您都在预加载所有图像-它不会花费您页面加载时间-而且它还可能节省一些时间,因为通过正确的压缩,14 的 1 图像的重量将小于 14 图像的 1

于 2013-04-27T22:36:36.947 回答
2

铬没问题。我可以在 IE 中看到闪烁。解决方案在这篇文章的底部。

我怀疑视频版本会比所有图像更快地压缩和加载,但正如@Allendar 绘图所建议的那样,它将是最高效的传输。我建议使用画布或 SVG。

另一种使用图像的方法是将单个组件作为图像或图标字体以绝对定位放置在显示器上,然后在脚本中打开或关闭它们。但这是一个非常复杂的解决方案。

我认为您今天解决问题的最简单和最快的方法就是调整您拥有的解决方案。正如其他人所建议的那样,多图像方法不会非常有效,如果您要采用该路线,至少请确保将 Web 服务器上的缓存标头设置为无限期缓存;

Cache-Control: public;
Expires: Mon, 31 Dec 2035 12:00:00 GMT

好的,所以闪烁问题只是 IE 中渲染引擎的错误/效率低下,所以这里有一个使用不同方法的解决方法。

基本上拉伸绝对定位DIV在 上body,而不是使用body本身。事实上,在这种情况下,我们使用多个DIVs,每个图像一个,并将它们叠加在另一个之上。您也可以在脚本中创建这些节点。

其次,DIV为您的内容添加另一个,并将其覆盖在body上面;

<body>
    <div id="b100" class="background" style="background-image:url('http://ingodwetrustthemovie.com/bgImage/100.jpg')"></div>
    <!-- rest omitted -->
    <div id="b113" class="background" style="background-image:url('http://ingodwetrustthemovie.com/bgImage/113.jpg')"></div>
    <div id="content">
        <div id="test">test div</div>
        here is some text
    </div>
</body>

一次只显示一个并隐藏其余部分;

function switchImage() {
    var s = $(window).scrollTop()/10;
    var index = Math.floor(s / 5);

    $('.background').hide();
    $('.background').eq(index).show();
}

我怀疑与更改 src 属性相比,调整 css 显示选项的闪烁会更少,而且它似乎可以解决问题。

这是小提琴

当然,您可能仍需要优化代码以允许首先显示第一个加载的图像而不是纯背景,但我认为这说明了修复的原理。

您还可以考虑制作一个非常大的 CSS Sprite,将图像捆绑成一个巨大的条带,然后使用background-position. 那可能会在body标签本身上起作用。当然,这意味着在显示任何图像之前下载一个巨大的文件,但有两个优点;

  1. 一张图像(尤其是具有这种相似性的图像)将比单独的每个单独的图像更好地压缩。
  2. 使用相同的缓存指令,一旦您第一次获取图像,这只是一个 HTTP/GET/302 周期而不是 13 个周期,因此您的页面加载速度可能会更快。

SVG

SVG 元素的工作方式与 DOM 非常相似。如果您可以将内容作为 SVG 交付,您可以深入了解图形、定位元素、给它们 ID 等,并像处理任何其他 DOM 元素一样操作它们;

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <ellipse id="e1" cy="420" cx="200" rx="420" ry="30" style="fill:3f5566" />
   <ellipse id="e2" cy="420" cx="170" rx="390" ry="20" style="fill:4f5566" />
   <ellipse id="e3" cy="420" cx="145" rx="370" ry="15" style="fill:5f5566" />
   <ellipse id="e4" cy="420" cx="100" rx="370" ry="20" style="fill:6f5566" />
   <ellipse id="e5" cy="420" cx="45"  rx="300" ry="15" style="fill:8f5566" />
</svg>

这是另一个基于滚动隐藏/取消隐藏 SVG 元素的小提琴。

理想情况下,假设他们已经在“图层”中生成了该图形,请尝试让您的设计师为您提供一个 SVG,其中图层被转换为。例如, Adobe Illustrator 可以做到这一点

然后,您可以根据需要轻松关闭图层/组以创建动画效果。

于 2013-04-27T22:29:08.093 回答
2

如果真的不需要图像,您可以为自己创建一些系统,在其中使用画布绘制并不断更新背景。这将是开始;

JSfiddle

HTML

<img id="template" src="http://ingodwetrustthemovie.com/bgImage/100.jpg" />
<canvas id="absBg" width="1000px" height="560px"></canvas>

CSS

body {
    margin: 0px;
}

#template {
    position: absolute;
    width: 1000px;
    height: 563px;
}

#absBg {
    position: absolute;
    /*background: rgba(0, 0, 0, 0.50);*/
    /*height: 100%;*/
}

JavaScript/jQuery

'use strict';

function drawBlock(ctx, color, line_width, start, lines) {
    ctx.lineWidth = line_width;
    ctx.strokeStyle = color;

    ctx.beginPath();

    ctx.moveTo(start[0], start[1]);

    for (var i = 0; i < lines.length; i++) {
        ctx.lineTo(lines[i][0], lines[i][1]);
    }

    ctx.closePath();
    ctx.stroke();
}

function drawBg() {
    var absBg = document.getElementById('absBg');
    var ctx = absBg.getContext('2d');

    var demo_red = 'red';
    var grey = '#28282';

    var color = demo_red;

    drawBlock(ctx, color, 1, [185, 87], [[205, 75], [226, 98], [207, 110]]);
    drawBlock(ctx, color, 1, [235, 60], [[253, 50], [272, 71], [254, 81]]);
}

$(document).ready(function () {
    drawBg();

    // Scroll trigger
    $(window).scroll(function () {

    });
});

该演示使用您拥有的实际背景图像作为背景模型,您可以在其中使用画布进行绘制。通过这种方式,您可以模仿您拥有的原始图像的外观。

您可以尝试管理某种“差异数组”,在其中存储哪些块在哪些位置不同。通过这种方式,您可以使用某些参数触发该功能,scroll以使其根据该参数更改绘图。

我希望你不“需要”图像本身。用画布绘图比加载大量图像要快得多:)

于 2013-04-27T22:30:38.000 回答
1

这是一个适用于 Firefox 30.0、chrome 35.0、opera 22.0 即 11.0 的解决方案(2014.7.11):

第 1 步:在 .htaccess 中添加这些行

# cache for images
<FilesMatch "\.(png)$">
Header set Cache-Control "max-age=10000, public"
</FilesMatch>

STEP 2:添加图片预加载,例如

var pics = []; // CREATE PICS ARRAY

$(document).ready(function(){
    ...
    preload(
        '/public/images/stars.red.1.star.png',
        '/public/images/stars.red.2.star.png',
        '/public/images/stars.red.3.star.png',
        '/public/images/stars.red.4.star.png',
        '/public/images/stars.red.5.star.png',
        '/public/images/stars.empty.png'
    );
    ...
    $('.rating').on('mousemove', function(event){
        var x = event.pageX - this.offsetLeft;
        var id = getIdByCoord(x); //
        if ($(this).data('current-image') != id) {
            $(this).css('background-image', 'url(' + pics[id].src + ')');
            $(this).data('current-image', id);
        }
    })
    ...
})

...

// PRELOAD FUNCTION TO SET UP PICS ARRAY IN MEMORY USING IMAGE OBJECT
function preload() {
    for (i = 0; i < arguments.length; i++) {
        pics[i] = new Image();
        pics[i].src = arguments[i];
        // alert("preload " + arguments[i]);
    }
}

PS感谢肖恩奥特曼

于 2014-07-11T06:36:42.353 回答