[英]Change canvas size per zoom using Fabric.js
我正在構建一個文檔查看器,文檔的每一頁都變成了一個圖像,並且所有頁面都在一個 html 畫布上一個接一個地組合在一起。
我正在使用 FabricJS 用圖像填充畫布。 當我縮放畫布內的圖像時,它們會完美地放大和縮小,但畫布本身保持相同的大小。
我希望畫布大小發生變化,以便滾動條在需要時隱藏和顯示。
這是構建和填充畫布的代碼:
buildCanvas: function (images, length, maximumWidth, totalHeight) {
var height = 10;
var canvasContainer = document.getElementById("canvasContainer");
var c = document.createElement("canvas");
c.width = canvasContainer.offsetWidth - 20;
c.height = totalHeight;
engine.canvasObject = new fabric.Canvas(c);
for (var index = 0; index < length; index++) {
var imgInstance = new fabric.Image(images[index], {
left: ((canvasContainer.offsetWidth / 2) - (maximumWidth / 2)),
top: height
});
var ratio = 1;
if (images[index].width > engine.maxWidth) {
ratio = engine.maxWidth / images[index].width;
imgInstance.scale(ratio);
maximumWidth = engine.maxWidth;
}
engine.canvasObject.add(imgInstance);
height += (images[index].height * ratio) + 15;
}
canvasContainer.appendChild(c);
},
這是我用來放大和縮小的代碼:
zoom: function (ratio) {
var canvasContainer = document.getElementById("canvasContainer");
var middleX = canvasContainer.offsetWidth / 2;
var middleY = 0;
var zoom = engine.canvasObject.getZoom();
engine.canvasObject.setHeight(engine.canvasObject.getHeight() * ratio);
//engine.canvasObject.setWidth(engine.canvasObject.getWidth() * (zoom + (ratio - 1)));
engine.canvasObject.zoomToPoint({ x: middleX, y: middleY }, zoom + (ratio - 1));
}
按照此行中的描述更改畫布的高度:
engine.canvasObject.setHeight(engine.canvasObject.getHeight() * ratio);
似乎可以完成這項工作,但我未能找到更改寬度的公式。 無論我嘗試過什么 當我在幾次單擊后縮小頁面時,由於畫布寬度減少的變化太大,頁面開始被“剪切”(主要在右側)。
我想我正在尋找的是一種了解畫布內實際繪制圖像的高度和寬度的方法。
我嘗試使用 getImageData 方法和 toDataUrl 方法獲取它,但它們對我沒有好處。
謝謝你的幫助
更新額外信息:
一些假設,因為我沒有足夠的信息。
engine.canvasObject.zoomToPoint
執行統一縮放zoomToPoint
之后,必須縮放畫布width
和height
以適合其內容。getHeight
返回並由setHeight
設置時沒有四舍五入然后畫布分辨率可以按(zoom + (ratio - 1)) / zoom
例如...
const currentZoom = engine.canvasObject.getZoom();
const newZoom = currentZoom + (ratio - 1);
const height = engine.canvasObject.getHeight();
const width = engine.canvasObject.getWidth();
const zoomBy = newZoom / currentZoom; // the amount to scale canvas
engine.canvasObject.setHeight(height * zoomBy);
engine.canvasObject.setWidth(width * zoomBy);
engine.canvasObject.zoomToPoint({ x: middleX, y: middleY }, newZoom);
這將工作放大或縮小。
請注意,如果zoom === -(ratio - 1)
縮放量(zoom + (ratio - 1))
可能會失敗,因為結果縮放為零。
注意如果縮放當前縮放非常小而新縮放很大,則畫布尺寸可能會變得太大。 為安全起見,您應該審查新的縮放值以防止可能使頁面崩潰或使其變得非常緩慢的非常大的畫布。
如果畫布大小四舍五入(或舍入)為整數,則隨着時間的推移,此錯誤會增加。 只有在多次縮放畫布時才會出現此問題。
為避免此錯誤,您需要有一個參考比例。 畫布在特定比例下的大小。
例如
const canvasScaleReference = {
zoom: 2, // At this zoom the canvas
width: 500, // is 500
height: 1000, // by 1000
};
這意味着在縮放 1 時畫布是 250 x 500
因此,縮放和調整畫布大小的功能是
const zoom = engine.canvasObject.getZoom() + (ratio - 1);
const height = canvasScaleReference.height / canvasScaleReference.zoom * zoom;
const width = canvasScaleReference.width / canvasScaleReference.zoom * zoom;
engine.canvasObject.setHeight(height);
engine.canvasObject.setWidth(width);
engine.canvasObject.zoomToPoint({ x: middleX, y: middleY }, zoom);
因為這使用固定參考,舍入誤差不能累積。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.