仅使用Chrome进行慢速图像绘制

Slow image draw with Chrome only

本文关键字:图像 绘制 Chrome      更新时间:2024-04-26

这是一个基本的文本输入,它将化身图像和文本添加到类似聊天的框div中,化身可以是数百的任何数字,所以我不能只将其作为一个类。

问题:通过html插入使用标准<img>会导致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;
}

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

我没有任何关于Chrome内部的参考工作来说明为什么会发生这种情况,但以下是当它发生在我身上时我是如何解决的。2件事:

1.不要使用img src

将图像作为背景图像加载到div。Chrome必须以不同的方式加载/缓存这些图像。。。?

2.预加载图像

这就说明了一切。在FF中,您可以通过创建一个包含图像的DOM元素来实现预加载,ala

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
}

小提琴http://jsfiddle.net/yo307pt7/4/

这最终成为了一个完整的FUBAR:我(在一些史前阶段)使用PHP强制浏览器通过无缓存选项获取新图像。一个非常糟糕的主意。

Chrome遵循了比其他浏览器更残酷的政策。

我的答案是,用一个"?作为一种广泛的js策略,图像url末尾的number_here将在不影响速度的情况下提供完美的更新。

当您希望在浏览器刷新时进行完美更新时,请更改"number_here"。使用变量可以变得聪明。

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