Я использую Fabric JS для манипулирования очень большими изображениями (20 Мб +).Я обнаружил, что Fabric значительно медленнее обрабатывает большие изображения на холсте по сравнению со стандартным Canvas API.
В приведенном ниже фрагменте кода есть две кнопки ввода: одна для добавления изображения на холст с помощью стандартного Canvas API, а другая - с помощью Fabric JS.Каждый метод также преобразует холст в URL данных, используя toDataUrl()
.Каждый метод также регистрирует три раза: время начала, время завершения функции img.onload и время завершения toDataUrl()
.
Вот таблица, в которой сравниваются времена импорта и экспорта, которые я тестировал для изображений разных размеров: время импорта для фотографий размером от 500 КБ до 50 МБ
Вот график, показывающий производительностьИмпорт матрицы + время экспорта и API Canvas: график
Вопросы:
- Почему производительность Fabric намного ниже, чем у Canvas API вимпорт + экспорт больших изображений на холст?
- Есть ли способ повысить производительность Fabric при использовании больших изображений?
- Точно ли мои тестовые примеры отражают производительность Fabric?
// 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);
};
canvas {
border: 2px solid;
}
<!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>