11

This is my code:

http://jsfiddle.net/652nk/

HTML

<div id="canvas">
    <div id="dragme"></div>
</div>

CSS

#canvas {
    width:500px;
    height:250px;
    border:1px solid #444;
    zoom:0.7;
}
#dragme {
    width:100px;
    height:50px;
    background:#f30;
}

JS

$(function(){
    $('#dragme').draggable({containment:'parent'})
})

I have a major issue when using css zoom property. Position of target draggable div is not coordinated with cursor position.

Is there any clean and simple solution? I should be able to change zoom dynamically.

enloz
  • 5,704
  • 9
  • 37
  • 56
  • I've viewed this: http://stackoverflow.com/questions/2930092/jquery-draggable-with-zoom-problem ...not much of help. – enloz Dec 22 '11 at 14:42
  • Why isn't it much help? It seems to be exactly your problem. – Janus Troelsen Dec 22 '11 at 14:52
  • @TimBJames I need to scale (make it smaller) a div containing other div's that are draggable. – enloz Dec 22 '11 at 15:38
  • @user309483 I could't get that solution/answer up and running. – enloz Dec 22 '11 at 15:39
  • The issue is down to javascript not being able to calculate the width/height of the `divs` when they have the style `zoom`. If you look at the position of the draggable div when it reaches the "edge" of the containing `div`, then it is correct if the `div` was actually the width/height specified – Tim B James Dec 22 '11 at 16:45
  • Check this out to see what I mean. http://jsfiddle.net/652nk/28/ the jQuery is using what it thinks are the actual widths/heights/positions of the elements. – Tim B James Dec 22 '11 at 16:58

3 Answers3

23

You don't need to set zoom property. I just added the difference to draggable's position which occurs due to the zoom property. Hope it helps.

Fiddle

http://jsfiddle.net/TqUeS/

JS

var zoom = $('#canvas').css('zoom');
var canvasHeight = $('#canvas').height();
var canvasWidth = $('#canvas').width();

$('#dragme').draggable({
    drag: function(evt,ui)
    {
        // zoom fix
        ui.position.top = Math.round(ui.position.top / zoom);
        ui.position.left = Math.round(ui.position.left / zoom);

        // don't let draggable get outside the canvas
        if (ui.position.left < 0) 
            ui.position.left = 0;
        if (ui.position.left + $(this).width() > canvasWidth)
            ui.position.left = canvasWidth - $(this).width();  
        if (ui.position.top < 0)
            ui.position.top = 0;
        if (ui.position.top + $(this).height() > canvasHeight)
            ui.position.top = canvasHeight - $(this).height();  

    }                 
});
Ivan
  • 34,531
  • 8
  • 55
  • 100
tuze
  • 1,978
  • 2
  • 15
  • 19
  • 1
    Hm...Thanks for a answer, but it's not working. If I set e.g. `zoom:0.4` ... http://jsfiddle.net/jtnQU/1/ – enloz Dec 22 '11 at 17:54
11

The solution above did not work out for me. So I found my own. I wanted to share it if someone else also has the same issue.

var zoom = $('#canvas').css('zoom');    
$('#dragme').draggable({
    drag: function(evt,ui)
    {
         var factor = (1 / zoom) - 1

         ui.position.top += Math.round((ui.position.top - ui.originalPosition.top) * factor)
         ui.position.left += Math.round((ui.position.left - ui.originalPosition.left) * factor)   
    }                 
});
Michael J. Calkins
  • 32,082
  • 15
  • 62
  • 91
Yusuf Demirag
  • 773
  • 7
  • 10
2

I used both tuze's and Yusuf Demirag's solutions and added a little something for dragging on a grid:

var gridSize = 20;
$('#dragme').draggable({
    grid: [ gridSize , gridSize ],
    snap: true,
    snapTolerance: gridSize/2,

    drag: function(event,ui){
         var factor = (1 / zoom) -1;

         ui.position.top += Math.round((ui.position.top - ui.originalPosition.top) * factor);
         ui.position.top -= ui.position.top % gridSize;
         ui.position.left += Math.round((ui.position.left- ui.originalPosition.left) * factor);
         ui.position.left -= ui.position.left % gridSize;


         if (ui.position.left < 0) 
             ui.position.left = 0;
         if (ui.position.left + $(this).width() > canvasWidth)
             ui.position.left = canvasWidth - $(this).width();  
         if (ui.position.top < 0)
             ui.position.top = 0;
         if (ui.position.top + $(this).height() > canvasHeight)
             ui.position.top = canvasHeight - $(this).height();
    }
});

It has a minor bug (it can't sometimes get to an exact value eg: 160px) but it worked for what I needed.

Hope it helps.

kriskate
  • 177
  • 2
  • 2