Jquery draggable with zoom problem

后端 未结 5 1218
面向向阳花
面向向阳花 2020-12-05 11:21

I am working on a page in witch all its contents are scaled by using zoom. The problem is that when I drag something in the page the dragging item gets a bad position that s

相关标签:
5条回答
  • 2020-12-05 11:47

    I was struggling with this for some hours. I had a grid where I started of with scaling it by setting the font-size (125% etc on the container). This worked well until I came into images that didn't scale with the grid.

    Thought I'd use zoom instead and it worked brilliantly. Then I relized by draggable/droppable wasn't scaling with it hmm.. Spend several hours trying to destroy and re-init the jqueryUI objects but nothing worked.

    Then finally I realized I could use a combination of font-size for zooming the grid and css-zoom for the images. Now everything works and I can drag/drop with the same instance of jQueryUI.

    Hope this approach helps someone else. :-)

    0 讨论(0)
  • 2020-12-05 11:49

    If CSS Zoom is performed specifically on the html body, there is a very easy fix, but it does require you to modify the source. That's a no-go for some, but I'll post the solution here anyway.

    So the draggable functionality of jQuery UI figures out the mouseposition using a method called _generatePosition. The problem is that it doesn't take zoom into account (duh), so we merely have to divide its outcome by the zoom level and everything will work.

    So turn this:

        return {
            top: (
    
                // The absolute mouse position
                pageY -
    
                // Click offset (relative to the element)
                this.offset.click.top -
    
                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.top -
    
                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.top +
                ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.top :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
            )/ ,
            left: (
    
                // The absolute mouse position
                pageX -
    
                // Click offset (relative to the element)
                this.offset.click.left -
    
                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.left -
    
                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.left +
                ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.left :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
            )
        };
    

    in

        var zoomLevel = parseFloat($('body').css("zoom") || "1.0");
    
        return {
            top: (
    
                // The absolute mouse position
                pageY -
    
                // Click offset (relative to the element)
                this.offset.click.top -
    
                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.top -
    
                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.top +
                ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.top :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
            ) / zoomLevel,
            left: (
    
                // The absolute mouse position
                pageX -
    
                // Click offset (relative to the element)
                this.offset.click.left -
    
                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.left -
    
                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.left +
                ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.left :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
            ) / zoomLevel
        };
    

    That's all. I suggest saving it under a specific name so it's easily recognized that it has been modified. E.g.: jquery-ui.ZOOMFIX.js

    I used the jquery-ui.js file from the following package: https://jqueryui.com/resources/download/jquery-ui-1.12.1.zip

    0 讨论(0)
  • 2020-12-05 11:54

    Took a lot of time and effort to fix this, but finally, I have a solution that works.

    This solution works for both Firefox and IE. #canvas is the div that contains the draggable. Note that we have to make sure the elements stays inside the canvas manually.

    This also works if if canvas has a different zoom level than the rest of the page.

    var pointerX;
    var pointerY;
    $(c).draggable({
      start : function(evt, ui) {
        pointerY = (evt.pageY - $('#canvas').offset().top) / zoom - parseInt($(evt.target).css('top'));
        pointerX = (evt.pageX - $('#canvas').offset().left) / zoom - parseInt($(evt.target).css('left'));
      },
      drag : function(evt, ui) {
        var canvasTop = $('#canvas').offset().top;
        var canvasLeft = $('#canvas').offset().left;
        var canvasHeight = $('#canvas').height();
        var canvasWidth = $('#canvas').width();
    
        // Fix for zoom
        ui.position.top = Math.round((evt.pageY - canvasTop) / zoom - pointerY); 
        ui.position.left = Math.round((evt.pageX - canvasLeft) / zoom - pointerX); 
    
        // Check if element is outside 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();  
    
        // Finally, make sure offset aligns with position
        ui.offset.top = Math.round(ui.position.top + canvasTop);
        ui.offset.left = Math.round(ui.position.left + canvasLeft);
      }
    });
    
    0 讨论(0)
  • 2020-12-05 11:59
    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);    
            }                 
        });
    
    0 讨论(0)
  • 2020-12-05 12:05

    Are you taking the scroll position, margin and padding into account? Such as:

    x.left + 
    parseInt($(this).css('margin-left')) + 
    parseInt($(this).css('padding-left')) + 
    parseInt($(this).parent().scrollLeft());
    
    x.top + 
    parseInt($(this).css('margin-top')) + 
    parseInt($(this).css('padding-top')) + 
    parseInt($(this).parent().scrollTop());
    

    Then adjusting for the zoom value as needed?

    0 讨论(0)
提交回复
热议问题