我怎样才能真正快速地在 webkit 中显示图像?

How can I display an image in webkit really fast?

我正在使用电子构建一个照片应用程序,从文件系统加载用户照片。这些照片的大小很容易达到 7MB 或更大。该应用程序允许用户使用键盘箭头在照片之间切换,此时我希望新照片显示得非常快。

对于 7MB 的图像,仅更改 DOM 中现有图像标签的 src 可能需要约 200-300 毫秒,webkit 必须加载文件、解码文件并渲染页面上的文件。加载和解码各需要 100-150 毫秒。 (实际上分析器只是说 2 x 解码,但下一步删除其中一个解码,所以我认为它与读取的文件有关)。

正在预加载 img 标签...

var img = new Image();
img.src = "/path/to/photo.jpg"

...意味着webkit 预加载文件,这去掉了文件加载时间,但是像这样追加仍然有100-150ms 的延迟...

domElement.appendChild(img);

...因为读取的数据仍然必须解码才能附加到 DOM。

有没有办法对图像进行预解码,让附加到DOM上不存在100-150ms的延迟,只需要快速渲染?

不,你不能"pre-decode"。但是,您可以通过应用样式 width: 1px; height: 1px; opacity: 0.01 以一种有效的不可见方式预先附加 img,如果您再次附加,webkit 将不会重做该工作。

您甚至可以同时删除图像,前提是它有时间完全解码,并且 webkit 会保留解码后的数据(尽管我不确定 for how long)。

如果您想绝对确定它会快速加载,您可以执行以下两项操作之一。通过删除上面的样式或通过在 DOM 的不同部分加载相同的 img 标签,同时保留 'pre-appended' 标签来显示 img 标签。根据我的经验,这将花费 3 毫秒到 20 毫秒。

如果您使用大量用户定义的照片内容,请注意清理

根据我的经验,简单地从 DOM 中删除许多 img 元素将 导致内存泄漏(和电子 windows 崩溃) .我建议您在 从 DOM 中删除图像后将 img.src 设置为空 ,或者如果不再需要则设置 the entire img to null图像实例。

您可以使用 chrome devtools 时间轴使用以下代码(使用您自己的图像)来测量不同场景下照片的渲染速度。

<style>
/*#preload img {
  width: 1px;
  height: 1px;
  opacity: 0.01;
}*/
</style>

<button>Toggle Image</button>

<div id="container"></div>

<div id="preload"></div>

<script>
  "use strict"

  const button = document.getElementsByTagName('button')[0]
      , container = document.getElementById('container')
      , preload = document.getElementById('preload')
      , img1 = new Image()
      , img2 = new Image()
  var current = img2

  img1.src = './img1.JPG'
  img2.src = './img2.JPG'

  preload.appendChild(img2)
  setTimeout(function(){
    preload.removeChild(preload.childNodes[0])
  }, 200)

  button.addEventListener('click', function(e){
     toggleImg()
  })

  function toggleImg(){
    if (current === img1) {
      setImg(img2);
    } else {
      setImg(img1)
    }
  }

  function setImg(img){
    if (container.hasChildNodes()) container.removeChild(container.childNodes[0])
    container.appendChild(img)
    current = img
  }
</script>

我建议尝试使用 HTML5 Canvas 来渲染您的图像,这样您就可以提前加载下一张图像并更直接地控制缓存策略。