仅在Chrome浏览器中图片绘制缓慢

4
这是一个基本的文本输入框,它将头像图片和文本添加到类似聊天框的 div 中,头像可以是数百种不同的形式,所以我不能只使用一个类。
问题:使用标准的 <img> 标签通过 html 插入会导致 Chrome 显示图像时出现缓慢的重绘。IE 和 Firefox 可以立即显示图片(在缓存第一个条目后)。
我已经计时了主要函数本身,它完成时间大约为 6 毫秒(非常好),但此时 Chrome 已经渲染了文本,甚至还没有开始渲染图片。在另一台更快的电脑上测试 - 没有变化。 http://jsfiddle.net/chrisadmin/yw24h2aj/ html:
<div id="newMsg" style="border:1px solid black"></div>
<br/>Type some stuff and hit enter<br/>
<input class="ui-widget-content ui-corner-bl ui-corner-br" maxlength="400" type="text" id="outgoing" onkeydown="if (event.keyCode == 13) displayMsg()" />

js:

ngcClientTag = 0;
opt_avatar = '1';

function displayMsg() {
    var message = $('#outgoing').val();
    $('#outgoing').val('');
    ngcClientTag++;
    var innerHtml =
        '<div id="c_m_' + (ngcClientTag - 1) + '" class="msg1">' +
        '<div style="float:left">' +
        '<img class="msg2" src="http://parkbenchgames.com/images/ava/' + opt_avatar + '.png"/>' +
        '</div>' +
        '<div>' +
        '<div class="msg3" id="s_m_' + (ngcClientTag - 1) + '">' +
        '</div>' +
        '</div>' +
        '<div style="clear:both">' + '</div>' +
        '</div>';
    $("#newMsg").append(innerHtml);
    $("#s_m_" + (ngcClientTag - 1)).text(message);
}

CSS:

.msg1 {
    position:relative;
    margin-bottom:1px;
}
.msg2 {
    position:relative;
    margin-right:5px;
    border:none;
    height:25px;
    width:46px;
}
.msg2a {
    position:relative;
    margin-right:5px;
    border:none;
    height:25px;
    width:3px;
}
.msg3 {
    position:relative;
    top:4px;
    margin-bottom:4px;
    overflow:hidden;
}

你的想法很对,但是在你的fiddle里。如果你输入一个单独的字母比如A并按下回车键,它会快速加载达15次,然后变慢。如果你在第四或第五行后面输入“AAAAAAAAAAAAAAA”,即使下一行是“A”,它仍然会再次变慢。一旦它变慢了,就不会再回来了 :-( - ChrisAdmin
明天我会检查一下。下次请在答案上发表评论,这样我就能收到通知了 :) - chiliNUT
2个回答

1

太烦人了!我也遇到过完全相同的问题:动态创建的图像在Firefox中不会闪烁,但在Chrome中会闪烁。

我没有任何关于Chrome内部的参考资料说明为什么会出现这种情况,但以下是当我遇到这个问题时如何解决的。两件事:

1. 不要使用img src

将图片作为背景图加载到div中。Chrome必须以不同的方式加载/缓存它们...?

2. 预加载图片。

这真的很重要。在Firefox中,您可以通过创建包含该图像的DOM元素来实现预加载

var $img=$('<img>');
$img.attr('src','image.ext');

然而,如果您想要预加载图像,Chrome要求您将其实际附加到DOM中(在屏幕之外的某个位置),类似于:
var $img=$('<img>');
$img.attr('src','image.ext');
$img.css({position:'absolute',top:'-10000px',left:'-10000px'});
$('body').append($img);

既然您已经准备好了displayMsg()函数,您可以通过使用空的message调用它来预加载图片,然后立即删除它创建的元素,以避免在屏幕上混乱。

HTML/CSS未更改。

JS

ngcClientTag = 0;
opt_avatar = '1';

/* PRELOAD *///===========================
//you know the avatar number, grab the image
var img='http://parkbenchgames.com/images/ava/' + opt_avatar + '.png';
//make it a background style instead of an img tag
var bgStyle="background-image:url("+img+")";
$(document).ready(function () {
//preload the image!
displayMsg();
//use setTimeout to make sure we are on the next iteration of event loop
setTimeout(function() {$('.msg1').remove()},0);
});


function displayMsg() {
    var message = $('#outgoing').val();
    $('#outgoing').val('');
    ngcClientTag++;
    var innerHtml =
        '<div id="c_m_' + ngcClientTag + '" class="msg1">';
                 //display img in div instead of img tag
                 //borrow class msg2 to give it the same dimensions as the img
    innerHtml +='<div style="float:left;'+bgStyle+'" class="msg2">' +
        '</div>' +
        '<div>' +
        '<div class="msg3" id="s_m_' + ngcClientTag + '">' +
        '</div>' +
        '</div>' +
        '<div style="clear:both">' + '</div>' +
        '</div>';
    $("#newMsg").append(innerHtml);
    $("#s_m_" + ngcClientTag).text(message); // for text safe insert
}

fiddle http://jsfiddle.net/yo307pt7/4/


哦,抱歉了 - 我会做的。 - ChrisAdmin
@user975033 我尝试过调试,但是出现闪烁的情况(等待15次、输入大量字母等)不够具体,无法在相同条件下可靠地重现。有时会闪烁,有时则不会。话虽如此,我不会再深入研究这个问题了。我认为当前的方法已经涵盖了大多数情况。 - chiliNUT
我觉得我的电脑可能会慢一些,出现了缓慢的重绘而不是闪烁,但还是感谢你的努力。经过一些调查,我发现这可能是Chrome v40的问题。不过你的回答将在未来帮助其他人。 - ChrisAdmin
只支持Chrome v40?天啊,这一点也不让我惊讶。那个浏览器总是为了速度而进行奇怪的优化,自然会适得其反,导致某些东西比FF重绘得更慢!希望这些代码能对你有所帮助! - chiliNUT
虽然没有得到确认,但可以确定的是,六个月前的Chrome浏览器以通常的速度进行绘制。最近我所阅读到的内容表明,Chrome 40似乎存在一些问题,并且在某些层面上使用了某种不同的引擎。 - ChrisAdmin
是的,这是一个有趣的方法,我会将其保留在我的技能库中。谢谢兄弟。 - ChrisAdmin

0

这最终成为了一个完全的混乱局面:我曾经(在某个史前阶段)使用PHP通过no-cache选项强制浏览器获取新图像。 这是一个非常糟糕的想法。

Chrome比其他浏览器遵循更加无情的策略。

我的回答重点是,在图像URL的末尾使用“?number_here”作为广泛的js策略,将在不影响速度的情况下提供完美的更新。

当您希望在浏览器刷新时进行完美更新时,请更改“number_here”。 使用变量来更加智能。

pv = '?24';
...
output = '<img src="\images\icon20.png"'+pv+'>';
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接