【问题标题】:Performance issues when loading local images into the browser将本地图像加载到浏览器时的性能问题
【发布时间】:2013-07-03 03:36:03
【问题描述】:

我正在使用FileReader 在 Backbone 应用程序中显示本地图像。较小的图像会立即显示,没有任何问题,但当图像为几兆字节或更大时,Chrome 需要 2 或 3 秒才能加载图像(在具有 8 GB RAM 的全新 MacBook Pro 上)。

正如 cmets 中所指出的,大图像会在 this File API tutorial 中即时加载,因此问题不在于 FileReader,而在于我在 Backbone 中的特定实现。

我在下面包含了相关的 Backbone 模型和视图。以下是逻辑的概要:

  1. 模型会创建一个新的FileReader,文件路径会传入其中。
  2. 加载文件后,会创建一个Image,并将Imagesrc 设置为FileReader 提供的数据URL。
  3. 加载图像后,模型会更新为图像的宽度和高度(在应用程序的其他地方使用)并且模型的initialized 属性设置为true(因此触发change模型上的事件)。
  4. 当视图检测到模型上的change 事件时,会调用render 函数,它将div 的背景图像替换为数据URL。

主干模型

var PhotoModel = Backbone.Model.extend({

  initialize: function() {
    this.set({"available": true});
    this.initialized = false;
    if (this.get("file")) { 
      this.uploadPhoto();
    }
  },

  uploadPhoto: function() {
    var file = this.get("file");
    var reader = new FileReader();
    var model = this;
    reader.onload = function(event) {
      var image = new Image();
      image.onload = function() {
        model.set({width: this.width, height: this.height});
        model.set("initialized", true);
      };
      image.src = event.target.result; 
      model.set("dataURL", event.target.result);
    }
    reader.readAsDataURL(file);
  },
});

主干视图

var PhotoFormView = Backbone.View.extend({

  className: "photo-form",

  initialize: function() {
    this.listenTo(this.model, "change", this.render);
    this.render();
  },

  render: function() {
    $(this.el).find(".photo").css({"background-image": "url(" + this.model.get("dataURL") + ")"});
  },
});

以下是 Chrome 时间线的屏幕截图。最大的延迟似乎发生在数据 URL 请求和加载事件之间(大约 0.5 秒)。我不确定“重新计算样式”是什么意思。我也不确定为什么会有这么多的绘制事件(它似乎在滚动条区域呈现)。

解决方案

我曾假设浏览器能够比任何 JavaScript 解决方案更有效地在本机调整图像大小,但这个假设是错误的。通过调整图像的大小在显示之前,我能够将延迟减少到大约 50 毫秒。我使用了一个名为 JavaScript Load Image 的开源插件来处理图像加载和调整大小(它使用 HTML5 canvas 标签)。这是我修改后的 Backbone 模型:

var PhotoModel = Backbone.Model.extend({

  initialize: function() {
    this.set({available: true});
    this.set({initialized: false});
    if (this.get("file")) { 
      this.uploadPhoto();
    }
  },

  uploadPhoto: function() {
    var model = this;
    loadImage(this.get("file"), function (img) {
      model.set({img: img});
      model.set({initialized: true});
    }, {maxHeight: 344});
  },
});

【问题讨论】:

    标签: javascript jquery html css backbone.js


    【解决方案1】:

    我在使用 FileReader 加载大图像时遇到了同样的问题。如果您不打算以全尺寸显示它们,似乎解决方法涉及在使用 canvas 元素显示之前缩放图像。

    在我自己的实现取得了不同程度的成功后,我选择使用JavaScript Load Image(MIT 许可证)及其maxWidth 选项,它解决了这个以及更多(未预见的)问题。

    试试the demo,看看你的图片是否加载良好。

    【讨论】:

    • 这正是问题所在。我曾假设浏览器在本地调整图像大小而不是调用 JavaScript 解决方案时会更有效。然而,事实并非如此。通过在显示之前调整图像大小,我完全消除了延迟。您建议的插件非常适合这种情况。谢谢!
    • 我很高兴这对你有用,感谢 github.com/blueimp 的辛勤工作!
    猜你喜欢
    • 2011-04-29
    • 2015-12-31
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    相关资源
    最近更新 更多