[英]Scale an image to fit when replacing an image
I'm trying to implement a behaviour by which I can add an initial image to a canvas (placeholder) and then subsequently I can then choose a different image to replace that image - that new image should then scale itself to "fit" within the bounds of the old image. 我正在尝试实现一种行为,通过该行为我可以将初始图像添加到画布(占位符),然后随后我可以选择其他图像来替换该图像-然后,该新图像应按比例缩放以“适合”旧图像的边界。 For example if I choose a portrait image as the "placeholder" and then choose a landscape image to replace it, Id expect the landscape image to first scale its width and maintain aspect ratio, and then vertically align itself within the boundaries of the placeholder dimensions. 例如,如果我选择一个肖像图像作为“占位符”,然后选择一个风景图像来代替它,则我希望该风景图像先缩放其宽度并保持宽高比,然后在占位符尺寸的边界内垂直对齐。
Here is a jsfiddle of what I have working so far: https://jsfiddle.net/cgallagher/co8dg527/1/ 这是到目前为止我正在工作的jsfiddle: https ://jsfiddle.net/cgallagher/co8dg527/1/
and here is the code: 这是代码:
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()
}
You can see that the image does scale the way I'd like but it doesn't then align itself. 您会看到图像确实按我想要的方式缩放,但随后无法对齐。
I'm toying with the idea of dropping a bounding box around the image too and possibly trying to align and scale within that but I'm not sure this is even possible with fabric? 我也想在图像周围放置一个边界框,并可能尝试在其中对齐和缩放,但是我不确定织物是否有可能?
This is what I had done. 这就是我所做的。 When you run scaleToWidth
and scaleToHeight
the scaleX
and scaleY
is changing and you need to adjust the oldHeight
and oldWidth
to the new img.scaleX
/ img.scalaY
I also rewrite _renderFill
method from fabric.Image.prototype
to create that offset effect. 当您运行scaleToWidth
和scaleToHeight
的scaleX
和scaleY
正在改变,你需要在调整oldHeight
和oldWidth
新img.scaleX
/ img.scalaY
我也改写_renderFill
从方法fabric.Image.prototype
创建抵消效果。 Check here: https://jsfiddle.net/mariusturcu93/co8dg527/37/ 在这里检查: https : //jsfiddle.net/mariusturcu93/co8dg527/37/
Code 码
<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
rewrite fabric.Image.prototype._renderFill
重写
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);
}
})()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.