1) Fabri c. js увеличивает холст, если devicePixelRatio равен> 1. Вот почему вы получаете увеличенное изображение, когда рисуете пиксели, полученные из getImageData()
. Лучше было бы использовать drawImage()
и указать ширину / высоту назначения, чтобы ваш браузер решал, следует ли уменьшать или увеличивать эти пиксели в соответствии с размерами исходного изображения.
2) Вы Право насчет сброса преобразования окна просмотра, но этого недостаточно - вам следует применить это новое преобразование и каким-то образом перерисовать холст. Это то, что делает Fabri c. js, когда вы вызываете toDataURL()
- он вызывает toCanvasElement()
, который создает копию canvas и отображает все объекты на нем. Ваша реализация должна отражать эту логику c.
В приведенном ниже решении представлен метод drawOnCopyCanvas()
, который является исправленной версией toCanvasElement()
. Вместо этого он не использует промежуточный холст и dr aws непосредственно на поставляемом холсте.
fabric.StaticCanvas.prototype.drawCopyOnCanvas = function(canvasEl) {
// save values
var scaledWidth = this.width,
scaledHeight = this.height,
vp = this.viewportTransform,
originalInteractive = this.interactive,
newVp = [1, 0, 0, 1, 0, 0],
originalRetina = this.enableRetinaScaling,
originalContextTop = this.contextTop;
// reset
this.contextTop = null;
this.enableRetinaScaling = false;
this.interactive = false;
this.viewportTransform = newVp;
this.calcViewportBoundaries();
// draw on copy
this.renderCanvas(canvasEl.getContext('2d'), this._objects);
// restore values
this.viewportTransform = vp;
this.calcViewportBoundaries();
this.interactive = originalInteractive;
this.enableRetinaScaling = originalRetina;
this.contextTop = originalContextTop;
}
function afterRender() {
// remove 'after:render' listener as canvas.toCanvasElement()
// calls renderCanvas(), which results in an infinite recursion
canvas.off('after:render', afterRender);
// draw c1 contents on c2
canvas.drawCopyOnCanvas(c2);
setTimeout(() => {
// re-attach the listener in the next event loop
canvas.on('after:render', afterRender);
});
}
canvas.on('after:render', afterRender);