I'm scaling a JQuery sortable element with CSS transform. Both the sortable items start positions and offsets while dragging are wrong beacuse JQuery doesn't take CSS scales into consideration. I solved it partially with code found here:
jQuery Drag/Resize with CSS Transform Scale
But the thing I cannot solve is the sortable item position at drag starts. It jumps up and right a bit. I can't figure out what to put into the start event handler:
start: function(e, ui)
{
// something is needed here to fix the initial offset
}
This Fiddle shows the problem: http://jsfiddle.net/adrianrosca/zbvLp/4/
The scale() CSS function defines a transformation that resizes an element on the 2D plane. Because the amount of scaling is defined by a vector, it can resize the horizontal and vertical dimensions at different scales. Its result is a <transform-function> data type.
jQueryUI provides sortable() method to reorder elements in list or grid using the mouse. This method performs sortability action based upon an operation string passed as the first parameter.
jQueryUI sortable() method is used to re-order elements in the list or grid form, by using the mouse. The sorting ability of this method is based on an operation string passed as the first parameter.
One difference with draggable is that the transform is not on the elements themselves, but on the parent. So it changes a bit the logic.
Here's a solution for this specific case, but you'll see that depending on the situation it may change. For example, if you change transform-origin, or if you have an horizontal sortable, it'll have to be adapted. But the logic stays the same:
var zoomScale = 0.5;
$(".container")
.sortable({
sort: function(e, ui) {
console.log(ui.position.left)
var changeLeft = ui.position.left - ui.originalPosition.left;
// For left position, the problem here is not only the scaling,
// but the transform origin. Since the position is dynamic
// the left coordinate you get from ui.position is not the one
// used by transform origin. You need to adjust so that
// it stays "0", this way the transform will replace it properly
var newLeft = ui.originalPosition.left + changeLeft / zoomScale - ui.item.parent().offset().left;
// For top, it's simpler. Since origin is top,
// no need to adjust the offset. Simply undo the correction
// on the position that transform is doing so that
// it stays with the mouse position
var newTop = ui.position.top / zoomScale;
ui.helper.css({
left: newLeft,
top: newTop
});
}
});
http://jsfiddle.net/aL4ntzsh/5/
EDIT:
Previous answer will work for positioning, but as pointed by Decent Dabbler, there is a flaw with the intersection function that validates when a sorting should occur. Basically, positions are correctly calculated, but the items keep width and height values that are not transformed, which is causing the problem. You can adjust these values by modifying them on start event to take scale factor into account. Like this for example:
start: function(e, ui) {
var items = $(this).data()['ui-sortable'].items;
items.forEach(function(item) {
item.height *= zoomScale;
item.width *= zoomScale;
});
}
http://jsfiddle.net/rgxnup4v/2/
There are two things in your problem:
position:relative;
for container.ui.position
and ui.originalPosition
so you have to "apply" zoomScale
to both of them.CSS
.container
{
position: relative;
transform: scale(0.5);
transform-origin: center top;
}
Script
var changeLeft = ui.position.left - ui.originalPosition.left;
var newLeft = (ui.originalPosition.left + changeLeft) / zoomScale;
var changeTop = ui.position.top - ui.originalPosition.top;
var newTop = (ui.originalPosition.top + changeTop) / zoomScale;
This is update code: http://jsfiddle.net/zbvLp/9/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With