0

I have a fixed HTML5 canvas with dimensions 300x300. I'm resizing other images on the page to have maximum widths/heights of 300px (depending on which dimension is larger) via Javascript.

This doesn't actually resize the source images, though, and when I draw them on the canvas, the original size is used.

Is there a way to:

  1. Resize these images with Javascript so that they're drawn to the canvas with a maximum height or width of 300px.

AND

  1. Have the canvas retain its 300x300 dimensions with the resized image inside of it, so that a 300x300 square with the variable-sized image completely contained inside of it is created?

(Think making a 300x300 Photoshop file where you drop in various images and they resize to fit)

Is this even possible with Javascript/canvas?

EDIT

Here is the code I ended up using based on the accepted answer:

var ssItems = [exampleUrls], //array of image paths
imgHolder = document.getElementById("img-holder");

for (var i = 0; i < ssItems.length; i++) {
          var img = new Image(),
            imgSrc = "/ItemImages/Large/" + ssItems[i] + ".jpg",
            imgW,
            imgH;
          img.src = imgSrc;
          img.onload = function () {
              var canvas = document.createElement("canvas"),
                ctx = canvas.getContext("2d");
              canvas.setAttribute("class", "img-canvas");
              canvas.setAttribute("width", "300");
              canvas.setAttribute("height", "300");
              imgHolder.appendChild(canvas);
              imgW = (canvas.height * this.width) / this.height;
              imgH = (canvas.width * this.height) / this.width;
              if (this.height > this.width) {
                ctx.drawImage(this, canvas.width / 2 - imgW / 2, 0, imgW, canvas.height);
              } else {
                ctx.drawImage(this, 0, canvas.height / 2 - imgH / 2, canvas.width, imgH);
              }
            }
Tier
  • 3
  • 3
  • Do you mean like [this](https://stackoverflow.com/questions/21961839/simulation-background-size-cover-in-canvas/21961894#21961894), or something like [this](https://stackoverflow.com/questions/14087483/how-to-proportionally-resize-an-image-in-canvas/14087607#14087607)? –  Dec 14 '16 at 02:48
  • or even [SVG style](http://stackoverflow.com/questions/34428723/how-to-implement-svgs-preserveaspectratio-xminymin-slice-for-canvas-drawimage/34429774#34429774) ? – Kaiido Dec 14 '16 at 06:01
  • @K3N similar, yes, although it looks like the example mimics `background-size: cover` or a "zoom" effect. The blog post was helpful, though. – Tier Dec 14 '16 at 15:36
  • @Kaiido honestly I hadn't even considered SVG as an option as I haven't used it enough to fully understand the answer to that question, but I'll look at it more, thank you. – Tier Dec 14 '16 at 15:40
  • @Tier, this answer is for the canvas API but implement svg's preserveAspectRatio syntax where you can specify if you want the image being sliced or covering and the positions of x and y as min mid or max. – Kaiido Dec 14 '16 at 22:58

1 Answers1

2

I have created the fiddle that tries to match the scenario explained above.

var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext("2d");

var image = new Image();
image.src = 'http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg';

// calculates width and height with respect to canvas
var width = (canvas.height * image.width) / image.height;
var height = (canvas.width * image.height) / image.width;

// takes width or height full choosing the larger value and centers the image
if(image.height > image.width){
  ctx.drawImage(image, canvas.width / 2 - width / 2, 0, width, canvas.height);
}else{
  ctx.drawImage(image, 0, canvas.height / 2 - height / 2, canvas.width, height);
}

You can take a look into it : https://jsfiddle.net/q8qodgmn/1/

duwalanise
  • 1,312
  • 1
  • 14
  • 24
  • Had to modify the code slightly to fit my specific project (moving width/height declarations and if/else statements into `image.onload`), but it's working as intended, thank you! – Tier Dec 14 '16 at 15:10