0

Let me start by saying that I am not a professional developer, but I am managing a development project that has a specific need -- to scale an image placed on an HTML5 canvas from the center point using a slider. The developer has implemented a slider that scales the image from the top-left point, but usability dictates resizing from the center and he has not been able to figure it out. Is this even possible? Please see here for a beta version of the app pre-loaded with an image to test:

http://beta.drumart.com/head-builder?lib-image-url=https://thumbs.dreamstime.com/800thumbs/12617/126170273.jpg

Click the image to select it and use the "Size" slider to resize. I am just looking to find out if this is possible and, if so, point him in the right direction. Many thanks in advance!

Image slider screenshot

Jim
  • 11
  • 2
  • There are some important points to check when dealing with transformations inside canvas here: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations – Anurag Srivastava Apr 11 '20 at 17:05

1 Answers1

2

I reccommend creating a drawCenteredImage() function, give it an image, x, y, width, height and it will draw the image centered on the given x, y. Thus when you increase x and y it will scale about the center of the image.


function drawCenteredImage(img, x, y, width, height) {
    // Assuming globally accessible canvas context variable 'context'
    context.drawImage(img, x - width / 2, y - height / 2, width, height);
}

An example of this in use:

% Updated to scale in realtime %

let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");
let image = new Image();
image.onload = function() {
 drawImg();
};

image.src = "https://thumbs.dreamstime.com/800thumbs/12617/126170273.jpg";

function drawCenteredImage(img, x, y, width, height) {
    // Assuming globally accessible canvas context variable 'context'
    context.drawImage(img, x - width / 2, y - height / 2, width, height);
}

function drawImg() {
 context.fillStyle = "white";
 context.fillRect(0,0,canvas.width,canvas.height);
  let scale = document.getElementById("scl").value;
  drawCenteredImage(image, canvas.width / 2, canvas.height / 2, image.width * scale, image.height * scale);
}

let mousedownID = -1;
function mousedown(event) {
  if(mousedownID==-1)
     mousedownID = setInterval(drawImg, 5);


}
function mouseup(event) {
   if(mousedownID!=-1) {  //Only stop if exists
     clearInterval(mousedownID);
     mousedownID=-1;
   }

}

//Assign events
document.getElementById("scl").addEventListener("mousedown", mousedown);
document.getElementById("scl").addEventListener("mouseup", mouseup);
//Also clear the interval when user leaves the window with mouse
document.addEventListener("mouseout", mouseup);
<input id="scl" type="range" min="0" max="1" value="0.3" step="0.05">
<canvas id="canvas" width="500px" height="400px"></canvas>
GTBebbo
  • 1,198
  • 1
  • 8
  • 17
  • Well, that's an incredible start -- thank you, @GTBebbo! I am glad to know it is possible. That said, is there a way to show the scaling as it is happening the way it does now? Thanks again. – Jim Apr 11 '20 at 17:25
  • Yes, you can change the event handler from `onchange` to a combination of `onmousedown` and `onmouseup` similar to [this](https://stackoverflow.com/questions/15505272/javascript-while-mousedown). Give me a moment and I can update my answer to include this – GTBebbo Apr 11 '20 at 17:27
  • If you're happy this answered your question please mark it as correct, thanks! – GTBebbo Apr 11 '20 at 17:44
  • I am MORE than happy this answered my question. This was a serious usability issue and I am sure this will give the developer all the information he needs to make it work. THANK YOU SO MUCH! – Jim Apr 11 '20 at 18:16