Question

Imagine I have the below element appended to the document :

<html>
  <head>
    <style>
      #resizable {
       position: absolute;
       top: 30px;
       left: 30px;
       background: url(http://www.some243x350image.jpg) no-repeat;
       height: 243px;
       width: 350px;
       background-size: contain;
      }
    </style> 
  </head>
  <body>
    <div id="resizable"></div>
  </body>
</html>

I'd like to be able to resize the above div proportionally, without any max/min height/width limits.

Below is the code I've written (Working Example : http://jsfiddle.net/7wYAh/) but it has two main bugs :

1. The div's height and width do not change proportionally all the time (even though the image obviously does, given that I'm using background-size: contain;.

2. There are sudden increases/decreases in the height/width of the element the moment the element is "grabbed".

I'm not using an aspect ratio variable. What I'm doing is that I choose randomly whether to resize based on height or width every time. So if the height changes then I'll resize the width based on the height increase. And vice versa. Isn't that proportional as well? Meaning that if the height increases by 2px, I'll increase the width by 2px as well and vice versa.

Looking for an answer to my problem I found this post but I don't want to use width/height limits and I don't understand the use of the ratio.

So can you spot anything wrong with this code (assume that the elementCanBeResized is set to true whenever the mouse grabs the bottom right corner of the div) :

Working Example : http://jsfiddle.net/7wYAh/

var $element = $('#resizable');
var previousResizeX, previousResizeY, resizeDistanceX, resizeDistanceY;
$(window).mousemove(function (mouseCoordinates)
{
  if (!elementCanBeResized)
  {
    return;
  }
  if (typeof previousResizeX === 'undefined')
  {
    previousResizeX = mouseCoordinates.pageX;
    previousResizeX = mouseCoordinates.pageY;
  }
  else
  {
    var newResizeX = mouseCoordinates.pageX;
    var newResizeY = mouseCoordinates.pageY;

    // resizing proportionally based on width change
    if (newResizeX !== previousResizeX)
    {
      resizeDistanceX = newResizeX - previousResizeX;
      previousResizeX = newResizeX;
      previousResizeY += resizeDistanceX;
      newWidth = $element.width() + resizeDistanceX;
      newHeight = $element.height() + resizeDistanceX;
    }

    // resizing proportionally based on height change
    else if (newResizeY !== previousResizeY)
    {
      resizeDistanceY = newResizeY - previousResizeY;
      previousResizeY = newResizeY;
      previousResizeX += resizeDistanceY;
      newHeight = $element.height() + resizeDistanceY;
      newWidth = $element.width() + resizeDistanceY;
    }

    $element.css({
     height: newHeight,
     width: newWidth
    });
  }
});   
Was it helpful?

Solution

I assume that you want to resize by clicking at some point and then 'dragging' de mouse. Okay.

To question 2: You are storing the point where you click in previousResizeX. But I don't see you cleaning its value after the release of the button. If you don't set previousResizeX to 'undefined' again, next time you click there will be a 'sudden change' of width/height because newResizeX will be the distance between the place where you pressed the mouse the first time and its current position. To question 1: You are increasing the width/height the same number of pixels every time, that's why your div doesn't resize proportionally. I explain: if you start with a div that's 200 x 100, its width is the double of the height. When you duplicate its width, to be proportional you have to duplicate the height. But if you drag your mouse 100px, you'll end with a (200+100) x (100 + 100) div, which is 300 x 200. The image's width is no longer the double of its height. You need to calculate the ratio between width and height at the beginning:

var ratio = $element.height() / $element.width();
...
resizeDistanceX = newResizeX - previousResizeX;
resizeDistanceY = resizeDistanceX * ratio;
previousResizeX = newResizeX;
previousResizeY += resizeDistanceY;
newWidth = $element.width() + resizeDistanceX;
newHeight = $element.height() + resizeDistanceY;
...
//For Y
resizeDistanceY = newResizeY - previousResizeY;
resizeDistanceX = resizeDistanceY / ratio;
previousResizeY = newResizeY;
previousResizeX += resizeDistanceX;
newHeight = $element.height() + resizeDistanceY;
newWidth = $element.width() + resizeDistanceX;

And remember to set resizeDistanceX and resizeDistanceY once the mouse is released. Hope this helps you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top