首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Fabric JS:超大型图像(20mb+)的性能

Fabric JS:超大型图像(20mb+)的性能
EN

Stack Overflow用户
提问于 2018-11-12 17:21:50
回答 1查看 1.6K关注 0票数 3

我使用Fabric来处理非常大的图像(20mb+)。我发现,与使用标准canvas相比,Fabric在处理画布中的大型图像时要慢得多。

下面的代码片段有两个输入按钮,一个用于使用标准canvas向画布添加图像,另一个使用Fabric。每个方法还将使用toDataUrl()将画布转换为数据url。每个方法还记录三次:启动时间、img.onload函数完成的时间和toDataUrl()完成的时间。

下面是比较我测试过的不同图像大小的import+export时间的表:500 to至50 to照片的导入时间

以下是显示织物import+export时间与Canvas:图表性能的图表

问题:

  • 为什么布匹性能比画布上的importing+exporting大图像上的画布API慢得多?
  • 在使用大型图像时,有没有提高织物性能的方法?
  • 我的测试用例是否准确地表示织物的性能?

代码语言:javascript
运行
复制
// Standard Import
function handleFiles(e) {
  var t0 = performance.now();
  console.log('Standard Import')
  console.log('Start Time: ', Math.round(t0/1000))  
  var promise = new Promise(function(resolve) {
    var URL = window.webkitURL || window.URL;
    var ctx = document.getElementById('canvas').getContext('2d');
    canvas = document.getElementById('canvas');
    var url = URL.createObjectURL(e.target.files[0]);
    var img = new Image();
    img.onload = function() {
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0);
        resolve("done")
    };
    img.src = url;  
  });

  promise.then(function(result) {
    var t1 = performance.now()
    console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
    var dataURL = canvas.toDataURL('image/png')
    return    
  }).then(function(result){
    t2 = performance.now()
    console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
    return
  });
}

// Fabric Import
function handleFilesFabric(e) {
  var t0 = performance.now();
  console.log('Fabric Import')
  console.log('Start Time: ', Math.round(t0/1000))
  var promise = new Promise(function(resolve) {   
    var canvas = new fabric.Canvas('canvas');
    var reader = new FileReader();
    reader.onload = function (event){
      var imgObj = new Image();
      imgObj.src = event.target.result;
      imgObj.onload = function () {
        var image = new fabric.Image(imgObj);
        canvas.setHeight(imgObj.height);
        canvas.setWidth(imgObj.width);
        canvas.add(image);
        canvas.renderAll();
        canvas.forEachObject(function(object){ 
          object.selectable = false; 
        });
        resolve("done")
      }
    }
    reader.readAsDataURL(e.target.files[0]);
  });
  
  promise.then(function(result) {
    var t1 = performance.now()
    console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
    var dataURL = canvas.toDataURL('image/png')
    return
  }).then(function(result){
    t2 = performance.now()
    console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
    return
  });
}

window.onload = function() {
  // Standard Import 
  var input = document.getElementById('input');
  input.addEventListener('change', handleFiles, false);
  // Fabric Import
  var input2 = document.getElementById('input2');
  input2.addEventListener('change', handleFilesFabric, false);  
};
代码语言:javascript
运行
复制
canvas {
  border: 2px solid;
}
代码语言:javascript
运行
复制
<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Upload & Display Image w/ Canvas</title>
  <link rel="stylesheet" href="css/style.css">
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.min.js"></script>
</head>
<body>
    <h1> Upload & Display Image</h1>
    <canvas width="400" height="400" id="canvas"></canvas>
    <br>
    <b>Standard Add Image</b><br>
    <input type="file" id="input"/>
    <br>
    <b>Fabric Add Image</b><br>
    <input type="file" id="input2"/>
    <script src="js/index.js"></script>
</body>
</html>

EN

回答 1

Stack Overflow用户

发布于 2018-11-14 12:29:46

为了更公平起见,我对代码进行了一些重构:加载图像的方式相同,这两个事件都在两个不同的画布上运行。

此外,还删除用于此测试的其他fabricJS功能,这些功能没有意义。我认为对于更大的图像,差异应该更小,你能尝试一下大图像的片段吗?

顺便说一下,您不能将文件中的URL.createObjectUrl与dataUrl上的文件读取器进行比较。只是不公平。createObjectUrl在内存中创建对您上传的文件的引用。

ReadAsDataUrl读取文件,在base64中编码,创建一个string对象,然后浏览器必须再次读取该字符串,从base64解码。

区别还可能在于fabricJS使用drawImage和9个args绘制图像,而您使用的是3 args版本。

代码语言:javascript
运行
复制
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e) {
  var t0 = performance.now();

  var promise = new Promise(function(resolve) {
    var URL = window.webkitURL || window.URL;
    var ctx = document.getElementById('canvas').getContext('2d');
    canvas = document.getElementById('canvas');
    var url = URL.createObjectURL(e.target.files[0]);
    var img = new Image();
    img.onload = function() {
      console.log('Standard Import')
  console.log('Start Time: ', Math.round(t0/1000))  
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0);
        resolve("done")
    };
    img.src = url;  
  });

  promise.then(function(result) {
    var t1 = performance.now()
    console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
    var dataURL = canvas.toDataURL('image/png')
    return    
  }).then(function(result){
    t2 = performance.now()
    console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
    return
  });
}

// Fabric Import
function handleFilesFabric(e) {
  var t0 = performance.now();
  var canvas = new fabric.StaticCanvas('canvas2', {enableRetinaScaling: false, renderOnAddRemove: false });
  var promise = new Promise(function(resolve) {   
    
    var reader = new FileReader();
    var URL = window.webkitURL || window.URL;
    var url = URL.createObjectURL(e.target.files[0]);
      var imgObj = new Image();
      
      imgObj.onload = function () {
        console.log('Fabric Import')
  console.log('Start Time: ', Math.round(t0/1000))

        var image = new fabric.Image(imgObj);
        canvas.setDimensions({ width: imgObj.width, height: imgObj.height});
        canvas.add(image);
        resolve("done")
      }
      imgObj.src = url;
  });
  
  promise.then(function(result) {
    var t1 = performance.now()
    console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
    canvas.renderAll();
    var dataURL = canvas.lowerCanvasEl.toDataURL('image/png')
    return
  }).then(function(result){
    t2 = performance.now()
    console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
    return
  });
}

window.onload = function() {
  // Standard Import 
  var input = document.getElementById('input');
  input.addEventListener('change', handleFiles, false);
  input.addEventListener('change', handleFilesFabric, false);
};
代码语言:javascript
运行
复制
canvas {
  border: 2px solid;
}
代码语言:javascript
运行
复制
<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>Upload & Display Image w/ Canvas</title>
  <link rel="stylesheet" href="css/style.css">
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.min.js"></script>
</head>
<body>
    <h1> Upload & Display Image</h1>
    <canvas width="400" height="400" id="canvas"></canvas>
    <canvas width="400" height="400" id="canvas2"></canvas>
    <br>
    <b>Standard Add Image</b><br>
    <input type="file" id="input"/>
    <br>
</body>
</html>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53267113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档