Javascript 在替换图像时缩放图像以使其适合
我正在尝试实现一种行为,通过这种行为,我可以向画布(占位符)添加一个初始图像,然后我可以选择一个不同的图像来替换该图像-然后新图像应该在旧图像的范围内进行缩放以“适应”。例如,如果我选择一幅肖像图像作为“占位符”,然后选择一幅横向图像来替换它,我希望横向图像首先缩放其宽度并保持纵横比,然后在占位符尺寸的边界内垂直对齐 以下是我迄今为止所做工作的一小部分: 代码如下:Javascript 在替换图像时缩放图像以使其适合,javascript,fabricjs,Javascript,Fabricjs,我正在尝试实现一种行为,通过这种行为,我可以向画布(占位符)添加一个初始图像,然后我可以选择一个不同的图像来替换该图像-然后新图像应该在旧图像的范围内进行缩放以“适应”。例如,如果我选择一幅肖像图像作为“占位符”,然后选择一幅横向图像来替换它,我希望横向图像首先缩放其宽度并保持纵横比,然后在占位符尺寸的边界内垂直对齐 以下是我迄今为止所做工作的一小部分: 代码如下: var canvas = new fabric.Canvas('stage'); var cw = canvas.getWidth
var canvas = new fabric.Canvas('stage');
var cw = canvas.getWidth()
var ch = canvas.getHeight()
var _currentImage;
function setProductImage(url){
var oldWidth;
var oldHeight;
var oldLeft;
var oldTop;
fabric.Image.fromURL(url, function(img) {
if (_currentImage) {
oldWidth = _currentImage.getScaledWidth()
oldHeight = _currentImage.getScaledHeight()
oldLeft = _currentImage.left
oldTop = _currentImage.top
canvas.remove(_currentImage);
}
_currentImage = img;
img.set({ 'left': oldLeft || 0 })
img.set({ 'top': oldTop || 0 })
if (oldHeight && oldHeight > img.getScaledHeight()){
img.scaleToWidth(oldWidth);
img.set({'height': oldHeight })
} else if (oldWidth > img.getScaledWidth()){
img.scaleToHeight(oldHeight);
img.set({'width': oldWidth })
}
img.selectable = true
canvas.add(img).setActiveObject(img);
});
}
function addImage(url){
setProductImage(url)
canvas.renderAll()
}
您可以看到,图像确实按我所希望的方式缩放,但它不会自行对齐
我也在考虑在图像周围放置一个边界框,并可能尝试在该框内对齐和缩放,但我不确定这在织物上是否可行?这就是我所做的。
运行scaleToWidth
和scaleToHeight
时,scaleX
和scaleY
正在更改,您需要将oldHeight
和oldWidth
调整为新的img.scaleX
/img.scalaY
我还从fabric.Image.prototype
重写了\u renderFill
方法来创建偏移效果。
请点击此处:
代码
<html>
<head>
<title>Fabric kicking</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>
<style>
#stage {
border: solid 1px #333;
}
</style>
</head>
<body>
<button onclick="addImage('https://s.hs-data.com/bilder/spieler/gross/208995.jpg')">Add image</button>
<button onclick="addImage('https://cdn.images.express.co.uk/img/dynamic/67/590x/Mateusz-Klich-883903.jpg')">add another image</button>
<canvas id="stage" width="600" height="600"></canvas>
<script>
var canvas = new fabric.Canvas('stage');
var cw = canvas.getWidth()
var ch = canvas.getHeight()
var _currentImage;
function setProductImage(url){
var oldWidth;
var oldHeight;
var oldLeft;
var oldTop;
fabric.Image.fromURL(url, function(img) {
if (_currentImage) {
oldWidth = _currentImage.getScaledWidth()
oldHeight = _currentImage.getScaledHeight()
oldLeft = _currentImage.left
oldTop = _currentImage.top
canvas.remove(_currentImage);
}
_currentImage = img;
img.set({ 'left': oldLeft || 0 })
img.set({ 'top': oldTop || 0 })
if (oldHeight && oldHeight > img.getScaledHeight()){
img.scaleToWidth(oldWidth);
img.set({'height': oldHeight/img.scaleX})
} else if (oldWidth > img.getScaledWidth()){
img.scaleToHeight(oldHeight);
img.set({'width': oldWidth/img.scaleY })
}
img.selectable = true
canvas.add(img).setActiveObject(img);
});
}
function addImage(url){
setProductImage(url)
canvas.renderAll()
}
</script>
<img src="https://s.hs-data.com/bilder/spieler/gross/208995.jpg" />
<img src="https://cdn.images.express.co.uk/img/dynamic/67/590x/Mateusz-Klich-883903.jpg" />
</body>
</html>
fabric.Image.prototype._renderFill= (function(renderFill){
return function(ctx) {
var w = this.width, h = this.height, sW = w * this._filterScalingX, sH = h * this._filterScalingY,
x = -w / 2, y = -h / 2, elementToDraw = this._element;
y = y + Math.abs((this._element.height-h)/2);
x = x + Math.abs((this._element.width-w)/2);
elementToDraw && ctx.drawImage(elementToDraw,
this.cropX * this._filterScalingX,
this.cropY * this._filterScalingY,
sW,
sH,
x, y, w, h);
}
})()
这就是我所做的。
运行scaleToWidth
和scaleToHeight
时,scaleX
和scaleY
正在更改,您需要将oldHeight
和oldWidth
调整为新的img.scaleX
/img.scalaY
我还从fabric.Image.prototype
重写了\u renderFill
方法来创建偏移效果。
请点击此处:
代码
<html>
<head>
<title>Fabric kicking</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.0/fabric.js"></script>
<style>
#stage {
border: solid 1px #333;
}
</style>
</head>
<body>
<button onclick="addImage('https://s.hs-data.com/bilder/spieler/gross/208995.jpg')">Add image</button>
<button onclick="addImage('https://cdn.images.express.co.uk/img/dynamic/67/590x/Mateusz-Klich-883903.jpg')">add another image</button>
<canvas id="stage" width="600" height="600"></canvas>
<script>
var canvas = new fabric.Canvas('stage');
var cw = canvas.getWidth()
var ch = canvas.getHeight()
var _currentImage;
function setProductImage(url){
var oldWidth;
var oldHeight;
var oldLeft;
var oldTop;
fabric.Image.fromURL(url, function(img) {
if (_currentImage) {
oldWidth = _currentImage.getScaledWidth()
oldHeight = _currentImage.getScaledHeight()
oldLeft = _currentImage.left
oldTop = _currentImage.top
canvas.remove(_currentImage);
}
_currentImage = img;
img.set({ 'left': oldLeft || 0 })
img.set({ 'top': oldTop || 0 })
if (oldHeight && oldHeight > img.getScaledHeight()){
img.scaleToWidth(oldWidth);
img.set({'height': oldHeight/img.scaleX})
} else if (oldWidth > img.getScaledWidth()){
img.scaleToHeight(oldHeight);
img.set({'width': oldWidth/img.scaleY })
}
img.selectable = true
canvas.add(img).setActiveObject(img);
});
}
function addImage(url){
setProductImage(url)
canvas.renderAll()
}
</script>
<img src="https://s.hs-data.com/bilder/spieler/gross/208995.jpg" />
<img src="https://cdn.images.express.co.uk/img/dynamic/67/590x/Mateusz-Klich-883903.jpg" />
</body>
</html>
fabric.Image.prototype._renderFill= (function(renderFill){
return function(ctx) {
var w = this.width, h = this.height, sW = w * this._filterScalingX, sH = h * this._filterScalingY,
x = -w / 2, y = -h / 2, elementToDraw = this._element;
y = y + Math.abs((this._element.height-h)/2);
x = x + Math.abs((this._element.width-w)/2);
elementToDraw && ctx.drawImage(elementToDraw,
this.cropX * this._filterScalingX,
this.cropY * this._filterScalingY,
sW,
sH,
x, y, w, h);
}
})()
正如我所知,重写私有方法并不总是可以接受的。cgallagher需要的fabricjs不支持(我的意思是块中的偏移量)。我需要改变这个函数。如果@cgallagher不使用toSVG方法,我想不会产生任何问题,我不是说这是唯一的解决方案。这正是我第一次想到的,你的方法很有趣@MariusTurcu。与此同时,我自己也想出了一些似乎确实有效的办法。代码暂时是粗糙的,但我创建了一个占位符框,添加了第一个图像的尺寸,然后将第一个图像放在一个组中。在此之后添加的任何图像将根据其尺寸缩放为宽度/高度。我不确定我是否正在捕获边缘情况。正如我所知,重写私有方法并不总是可以接受的。cgallagher需要的fabricjs不支持的内容(我是指块中的偏移量)。我需要改变这个函数。如果@cgallagher不使用toSVG方法,我想不会产生任何问题,我不是说这是唯一的解决方案。这正是我第一次想到的,你的方法很有趣@MariusTurcu。与此同时,我自己也想出了一些似乎确实有效的办法。代码暂时是粗糙的,但我创建了一个占位符框,添加了第一个图像的尺寸,然后将第一个图像放在一个组中。在此之后添加的任何图像将根据其尺寸缩放为宽度/高度。我不确定我是否正在抓到边缘案例。