【问题标题】:Flicker on jQuery Background ChangejQuery背景更改闪烁
【发布时间】:2013-04-17 09:07:50
【问题描述】:

我为我当前的代码创建了一个 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 + ')');
}

【问题讨论】:

  • Shawn,我在 chrome (windows) 上看起来很流畅。你在哪里看到闪烁?作为与您的问题不同的问题,这些图像本身几乎是 1MG,这对于获取 bg 图像来说是相当大的页面加载。
  • 我同意,但图像已从原始尺寸优化。那么,您是否建议进一步减小图像尺寸?实际上有 200 张图像正在运行以提供电影效果。很高兴阅读它正在您的机器上运行。当您缓慢滚动时,它仍然响应良好吗?我会看看我们是否可以进一步缩小图像。
  • 好吧,不管你做什么,它们仍然会很大。我建议你为一个很酷的效果付出了相当高的代价,所以你可能想考虑不使用它。不过,暂时忽略这一点,我在 IE 中尝试了你的小提琴,并且能够看到闪烁的效果。我仍在寻找解决方案。
  • 这似乎是在图像尚未完成预加载时发生的,而在我这种缓慢的 DSL 连接上,加载完成最多需要 10 秒。您无法采取任何措施来防止这种情况发生,因为您无法控制用户的互联网连接速度。一个建议是:使用onload 单独跟踪每个图像何时完成预加载。然后仅执行switchImage代码,索引为已完成预加载的图像。
  • 我理解 Jonah,但唯一的问题是我必须使用这个效果和代码。我的另一个解决方案是使用 HTML5 视频背景并弄清楚如何正向和反向播放,但这似乎是一个更好的解决方案。

标签: javascript jquery css preload


【解决方案1】:

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

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

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

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

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

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

基本上在body 上拉伸绝对定位的DIV,而不是使用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 显示选项会更少闪烁,而且似乎可以解决问题。

这是Fiddle

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

您还可以考虑制作一个非常大的 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>

这是另一个 fiddle,它基于滚动隐藏/取消隐藏 SVG 元素。

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

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

【讨论】:

  • 谢谢卷云。我一定会检查一下。试图使用 div 而不是背景,但项目的时间已经不多了。在网站上进行了三周的周转,并对其他项目感到疯狂。我已经看到了通过正确设置标题来更新 htaccess 的修复程序。我同意精灵可能是最简单的解决方案之一。他们的设计公司给了我们一个视频,但这些图像似乎是一条更容易前进的道路。感谢您的提醒...很快就会深入了解。
  • 我刚刚读到您有 200 张图片。在这种情况下,我倾向于使用视频而不是静态。但是,绘制矢量仍然是最好的选择。你能让设计师给你SVG吗?一开始只需使用它代替图像,但随着时间的推移,您可以优化它以仅显示您需要的组件。
  • 我可以看到关于获取 SVG 并询问星期一。我没有使用过SVG,所以现在开始研究。他们确实为我们提供了 mp4,但我不知道如何根据滚动事件来加载和播放视频,这就是我选择图像的原因。我们不得不匆忙启动该网站。由于它正在运行广告,因此让这件事顺利运行更像是个人兴趣。非常感谢您的支持和反馈。根据我的研究,我将在周一早上首先深入研究代码。
  • 通过 SVG 演示查看更新的答案。您可以让它们提供多个 SVG 帧并像处理图像一样使用它们,但我认为如果您有一个 SVG 并手动钻入它并挑选出每个帧所需的元素并打开它们会更好或有选择地关闭。例如,您可以添加 class="frame1", class="frame2"。
  • 谢谢伙计。你摇滚。我正在为另一个项目而努力。由于日程安排,将在星期四看一看,但肯定会让你知道会发生什么。我会给你赏金来帮助我。衷心感谢您对 Cirrus 的了解和帮助。
【解决方案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上用特定的参数触发函数,让它以此为基础改变绘图。

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

【讨论】:

  • 谢谢艾伦达尔。我同意画画会更好。我有一家设计公司提供的所有图纸以及 vid 版本。由于时间不多了,所以我选择了阵列并迅速将其组合在一起。我也会尝试一下这个解决方案,看看它是否可行。我真诚地感谢反馈。将解决此问题并让您知道结果。
  • Allendar,你有关于画布的 tut 的链接吗?老实说,我没有任何经验,但我可以深入研究,看看我会在哪里结束。说真的,谢谢。
  • @ShawnAltman 很高兴听到这是一个可能的解决方案。我个人喜欢这些网站作为参考; diveintohtml5.info/canvas.html、developer.mozilla.org/en-US/docs/HTML/Canvas/…、html5rocks.com/en/tutorials/canvas/integrating。互联网上到处都是很棒的 Canvas 教程和示例; duckduckgo.com/?q=html5+canvas。祝你好运!
  • 哦,顺便说一句,还有一个小费;您也可以在彼此之上绘制两个绝对的 &lt;canvas&gt; 对象。所有始终的形状都绘制在最低的&lt;canvas&gt; 上。这样,您只需 重新绘制 更改前面 &lt;canvas&gt; 的形状,这将使访问者浏览器上的“渲染负载”比原来更轻,并且还分隔了 的大列表shape-drawings 来自较小的变化形状列表中的原始背景。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    这是一个适用于 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]);
        }
    }
    

    附:谢谢肖恩奥特曼

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-17
      • 2017-08-24
      • 2018-12-29
      • 1970-01-01
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多