Jquery可拖动缩放问题

发布于 2024-09-03 00:15:51 字数 475 浏览 3 评论 0原文

我正在开发一个页面,其所有内容都通过使用缩放进行缩放。 问题是,当我在页面中拖动某些内容时,拖动项目的位置似乎与缩放量相关。

为了解决这个问题,我尝试对可拖动组件的位置进行一些数学计算,但似乎即使在视觉上进行了纠正,“真实”位置也不会重新计算。

这里有一些代码可以更好地解释:

var Zoom = Math.round((parseFloat($("body").css("zoom")) / 100)*10)/10;

var x = $(this).data('draggable').position;
$(this).data('draggable').position.left = Math.round(x.left/zoom);
$(this).data('draggable').position.top = Math.round(x.top/zoom);

任何帮助将不胜感激

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 seems relative to the zoom amount.

To solve this I tried to do some math on the position of the draggable component, but seems that even tho visually its corrected, the "true" position its not recalculated.

here is some code to explain better:

var zoom = Math.round((parseFloat($("body").css("zoom")) / 100)*10)/10;

var x = $(this).data('draggable').position;
$(this).data('draggable').position.left = Math.round(x.left/zoom);
$(this).data('draggable').position.top = Math.round(x.top/zoom);

Any help would be greatly appreciated

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

橘亓 2024-09-10 00:15:51

花了很多时间和精力来解决这个问题,但最终,我找到了一个可行的解决方案。

该解决方案适用于 Firefox 和 IE。 #canvas 是包含可拖动元素的 div。请注意,我们必须手动确保元素保留在画布内。

如果画布的缩放级别与页面其余部分不同,这也适用。

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);
  }
});

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);
  }
});
〆一缕阳光ご 2024-09-10 00:15:51
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);    
        }                 
    });
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);    
        }                 
    });
白昼 2024-09-10 00:15:51

如果专门在 html body 上执行 CSS Zoom,则有一个非常简单的修复方法,但它确实需要您修改源代码。对于某些人来说这是不行的,但无论如何我都会在这里发布解决方案。

因此,jQuery UI 的可拖动功能使用名为 _generatePosition 的方法计算出鼠标位置。问题是它没有考虑缩放(废话),因此我们只需将其结果除以缩放级别即可,一切都会正常

所以把这个:

    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 ) )
        )
    };

    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
    };

这样。我建议将其保存在特定名称下,以便很容易识别它已被修改。例如:jquery-ui.ZOOMFIX.js

我使用了以下包中的jquery-ui.js文件:https://jqueryui.com/resources/download/jquery-ui-1.12.1.zip

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

蝶舞 2024-09-10 00:15:51

您是否考虑了滚动位置、边距和填充?如:

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());

然后根据需要调整缩放值?

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?

不醒的梦 2024-09-10 00:15:51

我为此苦苦挣扎了几个小时。我有一个网格,我开始通过设置字体大小(容器上的 125% 等)来缩放它。这种方法效果很好,直到我遇到无法随网格缩放的图像。

我想我应该使用变焦来代替,效果非常好。然后我意识到draggable/droppable并不能随它缩放,嗯..花了几个小时尝试销毁并重新初始化jqueryUI对象,但没有任何效果。

最后我意识到我可以使用 font-size 的组合来缩放网格和 css-zoom 来缩放图像。现在一切正常,我可以使用同一个 jQueryUI 实例进行拖放。

希望这种方法对其他人有帮助。 :-)

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. :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文