0

I would like to fill a div with an image (but not stretch) just like in this post CSS Image size, how to fill, not stretch? but instead of using CSS I need to calculate values using JavaScript.

This is what I have:

image.onload = ()=> {
      var ratio: number = image.width / image.height;

      if (ratio > 1) {
        image.height = this._height;
        image.width = ratio * this._height;
        image.style.left = -((image.width - this._width) / 2) + "px";
      } else {
        ratio = 1 / ratio;
        image.width = this._width;
        image.height = ratio * this._width;
        image.style.top = -((image.height - this._height) / 2) + "px";
      }
    };

this is the div and image is a normal Image().

It works in most cases but not when for example this._width < ratio*this._height.

How can I get the algorithm to work for all cases? I know it's pretty simple but I can't get it to work.

Community
  • 1
  • 1
HischT
  • 933
  • 1
  • 9
  • 26

3 Answers3

2

I think the problem is that you compare ratio with 1, but you should compare it with div's ratio:

image.onload = ()=> {
      var imgRatio: number = image.width / image.height,
          divRatio: number = this._width / this._height;

      if (imgRatio > divRatio) {
        image.height = this._height;
        image.width = this._height * imgRatio;
        image.style.left = -((image.width - this._width) / 2) + "px";
      } else {
        image.width = this._width;
        image.height = this._width / imgRatio;
        image.style.top = -((image.height - this._height) / 2) + "px";
      }
};
Oriol
  • 274,082
  • 63
  • 437
  • 513
0

Im not sure if this will helps but this is the function that I have used in the past for setting image sizes for the canvas element.

The image will take up the whole element without skewing it.

function setCanvasImage(canvas, source) {

    var canvasWidth  = canvas.width;
    var canvasHeight = canvas.height;

    var context = canvas.getContext('2d');

    var image = new Image();

    image.src = source;

    image.onload = function () {

        var sourceWidth = canvasWidth / canvasHeight * image.height;
        var sourceX = (image.width - sourceWidth) / 2;

        if(sourceX > 0) {

            var sourceY = 0;
            var sourceHeight = image.height;

        } else {

            var sourceX = 0;
            var sourceWidth = image.width;

            var sourceHeight = canvasHeight / canvasWidth * image.width;
            var sourceY = (image.height - sourceHeight) / 2;
        }

        //placing
        var destinationX = 0;
        var destinationY = 0;
        var destinationWidth = canvas.width; 
        var destinationHeight = canvas.height; 

        context.drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, destinationX, destinationY, destinationWidth, destinationHeight);
    }
}
geschwe1
  • 323
  • 3
  • 14
0

There are 2 scale values that you need to calculate, the scale value that makes the image as wide as the container, and the scale value that makes the image as tall as the container. To scale the image to fit inside this container, you choose the smaller of these scales, and to scale the image to extend beyond the container, you choose the largest. You don't care about the ratio between the width and height of the image. Example of fitting the image inside the container and centring:

var xScale = _width/img.width;     // Scale by this much to fit x
var yScale = _height/img.height;   // Scale by this much to fit y

var width = _width;
var height = _height;
var top = 0;
var left = 0;

if (xScale !== yScale) {
    // Choose the smaller scale. To make the image extend, make this >
    if (xScale < yScale) {
        height = Math.round(xScale * height);
        top = Math.round((_height - height) / 2);
    } else {
        width = Math.round(yScale * width);
        left = Math.round((_width - width) / 2);
    }
}

img.width = width;
img.height = height;
img.top = top + "px";
img.left = left + "px";
Matt Esch
  • 22,661
  • 8
  • 53
  • 51