sam999
sam999

Reputation: 115

Fabric js fit image in given size without stretching

Hello i am working on online print application where we create some designs in FabricJS and then users can edit those designing replacing text and image with their own...everything is working perfect but we are facing an issue with image replace when users replace image we want it to fit in already present image on canvas also maintain aspect ratio..below is current code for replacing image but its does not not fit image if image is vertical.

o  = activeCanvas.getActiveObject();
fabric.Image.fromURL(src, function(m) {
                var i = m.set({
                id: o.id,
                left: o.left,
                top: o.top,
                width: m.width,
                height: m.height
                });
                i.scaleToWidth(o.getScaledWidth());
                activeCanvas.remove(o);
                activeCanvas.add(i);
                renderAppChange();
                zoomoutIn(1);
                setActiveNew(i);
            });

Upvotes: 0

Views: 3015

Answers (1)

shkaper
shkaper

Reputation: 4988

From what I see, you want to scale your new image to fit the smallest of width and height dimensions of the old image:

const widthFactor = old.getScaledWidth() / newImg.width
const heightFactor = old.getScaledHeight() / newImg.height
const minFactor = Math.min(widthFactor, heightFactor)
newImg.scale(minFactor)

Here, scale() will preserve the aspect ratio.

And a snippet to test:

const canvas = new fabric.Canvas("c")

const url = "https://via.placeholder.com/100x50"
const url2 = "https://via.placeholder.com/50x100"
const url3 = "https://via.placeholder.com/100x100"

fabric.Image.fromURL(url, (img) => {
  canvas.add(img)
}, {
  left: 0,
  top: 10,
})

fabric.Image.fromURL(url2, (img) => {
  canvas.add(img)
}, {
  left: 120,
  top: 10,
})

fabric.Image.fromURL(url3, (img) => {
  canvas.add(img)
}, {
  left: 200,
  top: 10,
})

function insertAndFit (imageURL) {
  const o = canvas.getActiveObject();
  if (!o) {
    throw new Error('select an object first')
  }
  fabric.Image.fromURL(imageURL, function(m) {
    m.set({
      left: o.left,
      top: o.top
    })
    const widthFactor = o.getScaledWidth() / m.width
    const heightFactor = o.getScaledHeight() / m.height
    const minFactor = Math.min(widthFactor, heightFactor)
    m.scale(minFactor)
    canvas.remove(o)
    canvas.add(m)
  })
}

document.getElementById('b1').onclick = () => {
  insertAndFit("https://via.placeholder.com/100x300")
}

document.getElementById('b2').onclick = () => {
  insertAndFit("https://via.placeholder.com/300x100")
}

document.getElementById('b3').onclick = () => {
  insertAndFit("https://via.placeholder.com/200x200")
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.2/fabric.js"></script>
<canvas id='c' width="400" height="200"></canvas>
<button id='b1'>insert 100x300</button>
<button id='b2'>insert 300x100</button>
<button id='b3'>insert 200x200</button>

Upvotes: 2

Related Questions