jQuery-UI resizable/draggable with transform: scale() set.

I ran into a (well known, see this: http://bugs.jqueryui.com/ticket/6844) problem with jquery-ui draggable/resizable, which occurs when applying a transform: scale() setting to elements on your page.

The problem:

All the fuzz about this arises from the fact that browsers do not translate the actual sizes to the new scaled size, so if you start dragging or resizing objects, the scaled size will not match the calculated one and your elements will in-/decrease in size proportionally to the change you hinted at with your mousemovement.

There have been several solutions for this around, but all of them (at least the ones i found) required you to change the sourcecode of jquery-ui, which is a definite no-go for me.

One of the old solutions

The fix:

The fix is pretty (and) simple. You supply callbacks to the resize/drag events which will adjust the change in size/position of your element by the amount of scaling currently set.

The code:

First we scale our element. We will use jquery.transform.js to anmiate changes to CSS tranform attributes

var zoomScale = 1.75;

// scale our element
$(this).animate({
    transform: 'scale(' + zoomScale + ')'
});

fix for resizable:

Since the resizable will grow proportionally to the amount of mousemovement, the border you wanted to drag starts to be a long and increasingly longer way away fromy our actual mouse position. Let’s fix this:

function resizeFix(event, ui) {
    var changeWidth = ui.size.width - ui.originalSize.width; // find change in width
    var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale

    var changeHeight = ui.size.height - ui.originalSize.height; // find change in height
    var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale

    ui.size.width = newWidth;
    ui.size.height = newHeight;
}

$(this).resizable({
    minWidth: -(contentElem.width()) * 10,  // these need to be large and negative
    minHeight: -(contentElem.height()) * 10, // so we can shrink our resizable while scaled
    resize: resizeFix
});

fix for draggable:

Draggable is a bit trickier since it requires us to make changes at 2 points of the process. First off, if you start dragging the draggable will “hop” away from your mousepointer and secondly when attempting to drag the element, it will hurl away as if being chased by something considered scary to a DOM element. (perhaps Internet Explorer?). But never to worry! Our 2 callbacks end both of these problems too:

function startFix(event, ui) {
    ui.position.left = 0;
    ui.position.top = 0;
}

function dragFix(event, ui) {
    var changeLeft = ui.position.left - ui.originalPosition.left; // find change in left
    var newLeft = ui.originalPosition.left + changeLeft / zoomScale; // adjust new left by our zoomScale

    var changeTop = ui.position.top - ui.originalPosition.top; // find change in top
    var newTop = ui.originalPosition.top + changeTop / zoomScale; // adjust new top by our zoomScale

    ui.position.left = newLeft;
    ui.position.top = newTop;
}

$(this).draggable({
    start: startFix,
    drag: dragFix
});
About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: