我正在将FabricJS用于一个项目,在该项目中,我需要能够设置画布的背景图像。画布可以是任何大小,可以随时调整大小。最后,无论尺寸大小,图像都应始终填充在画布上,但绝不能以任何方式失真。
例如,如果我有一个800x600(WxH)的画布和一个1200x700的背景图像,则该图像应缩小为1029x600,以使其覆盖整个画布而不会失真。
我编写了一个函数,该函数应该计算画布和图像的尺寸并相应地设置图像的大小和位置,但是我无法使其正常工作。它在大多数时间都有效,但不是“防弹”。有时图像会失真,而有时图像却无法填满整个画布。
我需要帮助的是将其重构为防弹解决方案,无论画布或图像的大小如何,该解决方案都将始终符合我的尺寸标准。
我创建了一个fiddle with the code。小提琴将加载800x600的画布,然后首先设置横向背景图像以演示代码如何不调整图像的大小以覆盖画布,然后设置纵向图像以显示有时会扭曲图像。
这里是代码本身:
var canvas = window._canvas = new fabric.Canvas('c'),
canvasOriginalWidth = 800,
canvasOriginalHeight = 600,
canvasWidth = 800,
canvasHeight = 600,
canvasScale = .5,
photoUrlLandscape = 'https://images8.alphacoders.com/292/292379.jpg',
photoUrlPortrait = 'https://presspack.rte.ie/wp-content/blogs.dir/2/files/2015/04/AMC_TWD_Maggie_Portraits_4817_V1.jpg';
setCanvasSize({height: canvasHeight, width: canvasWidth});
setTimeout(function() {
setCanvasBackgroundImageUrl(photoUrlLandscape, 0, 0, 1)
}, 50)
setTimeout(function() {
setCanvasBackgroundImageUrl(photoUrlPortrait, 0, 0, 1)
}, 4000)
function setCanvasSize(canvasSizeObject) {
canvas.setWidth(canvasSizeObject.width);
canvas.setHeight(canvasSizeObject.height);
setZoom();
}
function setZoom() {
setCanvasZoom();
canvas.renderAll();
}
function setCanvasZoom() {
var width = canvasOriginalWidth;
var height = canvasOriginalHeight;
var tempWidth = width * canvasScale;
var tempHeight = height * canvasScale;
canvas.setWidth(tempWidth);
canvas.setHeight(tempHeight);
}
function setCanvasBackgroundImageUrl(url, top, left, opacity) {
if(url && url.length > 0) {
fabric.Image.fromURL(url, function(img) {
var aspect, scale;
if(parseInt(canvasWidth) > parseInt(canvasHeight)) {
if(img.width >= img.height) {
// Landscape canvas, landscape source photo
aspect = img.width / img.height;
if(img.width >= parseInt(canvasWidth)) {
scale = img.width / parseInt(canvasWidth);
} else {
scale = parseInt(canvasWidth) / img.width;
}
img.width = parseInt(canvasWidth)
img.height = img.height / scale;
} else {
// Landscape canvas, portrait source photo
aspect = img.height / img.width;
if(img.width >= parseInt(canvasWidth)) {
scale = img.width / parseInt(canvasWidth);
} else {
scale = parseInt(canvasWidth) / img.width;
}
img.width = parseInt(canvasWidth);
img.height = img.height * scale;
}
} else {
if(img.width >= img.height) {
// Portrait canvas, landscape source photo
aspect = img.width / img.height;
if(img.height >= parseInt(canvasHeight)) {
scale = img.width / parseInt(canvasHeight);
} else {
scale = parseInt(canvasHeight) / img.height;
}
img.width = img.width * scale;
img.height = parseInt(canvasHeight)
} else {
// Portrait canvas, portrait source photo
aspect = img.height / img.width;
if(img.height >= parseInt(canvasHeight)) {
scale = img.height / parseInt(canvasHeight);
} else {
scale = parseInt(canvasHeight) / img.height;
}
img.width = img.width * scale;
img.height = parseInt(canvasHeight);
}
}
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
top: parseInt(top) || 0,
left: parseInt(left) || 0,
originX: 'left',
originY: 'top',
opacity: opacity ? opacity : 1,
scaleX: canvasScale,
scaleY: canvasScale
});
canvas.renderAll();
setZoom();
});
} else {
canvas.backgroundImage = 0;
canvas.setBackgroundImage('', canvas.renderAll.bind(canvas));
canvas.renderAll();
setZoom();
}
};
这里是一个小提琴琴,它完成了您想要实现的(我认为):
https://jsfiddle.net/whippet71/7s5obuk2/
用于缩放图像的代码非常简单:
function scaleAndPositionImage() {
setCanvasZoom();
var canvasAspect = canvasWidth / canvasHeight;
var imgAspect = bgImage.width / bgImage.height;
var left, top, scaleFactor;
if (canvasAspect >= imgAspect) {
var scaleFactor = canvasWidth / bgImage.width;
left = 0;
top = -((bgImage.height * scaleFactor) - canvasHeight) / 2;
} else {
var scaleFactor = canvasHeight / bgImage.height;
top = 0;
left = -((bgImage.width * scaleFactor) - canvasWidth) / 2;
}
canvas.setBackgroundImage(bgImage, canvas.renderAll.bind(canvas), {
top: top,
left: left,
originX: 'left',
originY: 'top',
scaleX: scaleFactor,
scaleY: scaleFactor
});
canvas.renderAll();
}
基本上,您只是想知道图像的纵横比是大于还是小于画布的纵横比。一旦知道可以计算出比例因子,最后一步便是确定如何偏移图像,使其在画布上居中。
fabric.Image.fromURL("image.jpg", function (img) {
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
});
将图像设置为全画布