jQuery可拖动的约束数组值对于缩放容器。

8
如果有人能帮我解决如何使可拖动元素被包含在一个根据窗口大小改变比例的 div 中,我将非常感激您的指导。
如果我这样做:
element.draggable({ 
    cursor: "move",
    containment: '#container'
});

当我使用 transform: scale(1.5) 时,它会按照容器的普通大小来控制拖动元素的范围。也就是说,会有部分空间不能被可拖动元素所占用。
我也尝试过使用 containment: 'parent',但它会出现很多问题。 编辑 我已经找到如何获取顶部和左侧的限制,但我无法弄清楚如何获取右侧和底部的限制。
var containmentArea = $("#container");

containment:  [containmentArea.offset().left, containmentArea.offset().top, ???, ???]

我已经尝试过从containmentArea[0].getBoundingClientRect()获取宽度高度,但这似乎也不是正确的方法。

这里有一份示例代码的 jsfiddle。


没有仔细查看dragFix函数(可能可以在那里限制值而不是使用containment),但当我测试时,边界本身似乎有效,但需要减去拖动元素的尺寸:var bounds = container.getBoundingClientRect(); var dragrect = $('.draggable')[0].getBoundingClientRect() .... containment: [bounds.x,bounds.y, bounds.right - dragrect.width, bounds.bottom - dragrect.height] (示例:http://jsfiddle.net/z0gqy9w2/4/) - Me.Name
@Me.Name 嗯,右边和底部似乎可以工作,但现在顶部和左边不行了。编辑dragfix可能是一个可行的解决方案。想得真好。 - bryan
哎呀,我用了x和y而不是left和right,因为在Firefox中x和y可以工作,所以没有遇到问题。这在Chrome中也可以工作(还没有测试ie):containment: [bounds.left,bounds.top, bounds.right - dragrect.width, bounds.bottom - dragrect.height](http://jsfiddle.net/z0gqy9w2/5/)(不过,在dragfix中完成工作会更通用,稍后可能会研究一下)。 - Me.Name
@Me.Name 感谢您尝试解决这个问题!如果可拖动容器位于可滚动容器内部,此方法并不能完全奏效。 - bryan
3个回答

6
在拖动事件中重置坐标(因为它们已经被重新计算用于比例变换),而不使用包含。
var percent = 1, containmentArea = $("#container");

function dragFix(event, ui) {
    var contWidth = containmentArea.width(), contHeight = containmentArea.height();
    ui.position.left = Math.max(0, Math.min(ui.position.left / percent , contWidth - ui.helper.width()));
    ui.position.top = Math.max(0, Math.min(ui.position.top  / percent,  contHeight- ui.helper.height()));
}

$(".draggable").draggable({
    cursor: "move",
    drag: dragFix,
});

//scaling here (where the percent variable is set too)

Fiddle

在这个例子中,容器的宽度和高度是在拖动事件中获取的,为了更好的性能,也可以在缩放时将它们存储起来。通过在事件中计算它们,它们仍然可以在重新缩放后工作,尽管百分比变量仍然需要设置。为了真正通用,它也可以在事件中获得(而且可以使用 ui.helper.parent() 代替固定容器)。 由于拖动事件中的偏移量与容器相关(至少对于当前设置是这样),所以我简化了 originalleft + (position - originalposition)/percentposition / percent 开始偏移似乎不再必要,所以在 fiddle 中将其省略,但如果需要可以重新添加。


这几乎是完美的!非常感谢!!一旦允许我,我会立即奖励赏金。 - bryan

0

请看这个:

http://jsfiddle.net/z0gqy9w2/3/

编辑后的代码如下:

    // Matrix regex to take the scale value property of $('#container') element    
    var matrixRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/,
    matches = $('#container').css('transform').match(matrixRegex);
    // Matches have this value : ["matrix(1.5, 0, 0, 1.5, 0, 0)", "1.5", "1.5"] , so we need matches[1] value :
    var scaleValue = matches[1];
    $(".draggable").draggable({
        cursor: "move",
        start: startFix,
        drag: dragFix,
        containment: [containmentArea.offset().left, containmentArea.offset().top, 
                      ( ( containmentArea.offset().left + ( containmentArea.width() * scaleValue ) ) - ( $(".draggable").width() * scaleValue ) ) ,
                      ( ( containmentArea.offset().top + ( containmentArea.height() * scaleValue ) ) - ( $(".draggable").height()  * scaleValue ) ) ]

    });

正如你所看到的,这里有一个技巧:

( ( containmentArea.offset().left + ( containmentArea.width() * scaleValue ) ) - ( $(".draggable").width() * scaleValue ) )

您的右侧最大位置将是:主容器左偏移量 + 容器的真实宽度(带比例)- 项目的真实宽度(使其位于容器内)。

(提示:随意更改“百分比”变量值,以查看结果)

正则表达式参考


哇,@SerCrAsH,谢谢你!你似乎朝着正确的方向前进。由于某种原因,如果容器在可滚动的 div 中,顶部和底部的限制边界似乎会出现故障。 - bryan
请编写代码 console.log(matches),并告诉我是否满足条件 matches[1] == [2] - SerCrAsH
我只是用了 scaleValue = percent,而不是使用匹配(matches)。这样做是不是不太好? - bryan
如果这对你有价值,那就没问题。我原以为百分比将是一个动态值,而你硬编码了它。 :) - SerCrAsH
感谢您的关注。这是一个动态值,但 var percent 会被更新 : )。我认为偏移量对我造成了困扰,因为我的容器在可滚动的 div 中。如果当 .draggable 被拖动时我看不到页面底部,它将没有底部边界。如果我看到底部而不是页面顶部时被拖动,则顶部边界出现在页面的中间位置,如果这有任何意义的话... - bryan
显示剩余2条评论

0

这是我的解决方案:

var _zoom = 1.2,
    $element = $('.draggable-element'),
    $container = $('#container');

var containmentW,
    containmentH,
    objW,
    objH;

$element.draggable({

    start: function(evt, ui) {
        ui.position.left = 0;
        ui.position.top = 0;

        containmentW = $container.width() * _zoom;
        containmentH = $container.height() * _zoom;
        objW = $(this).outerWidth() * _zoom;
        objH = $(this).outerHeight() * _zoom;

    },

    drag: function(evt, ui) {

        var boundReached = false,

            changeLeft = ui.position.left - ui.originalPosition.left,
            newLeft = ui.originalPosition.left + changeLeft / _zoom,

            changeTop = ui.position.top - ui.originalPosition.top,
            newTop = ui.originalPosition.top + changeTop / _zoom;


        // right bound check
        if(ui.position.left > containmentW - objW) {
            newLeft = (containmentW - objW) / _zoom;
            boundReached = true;
        }

        // left bound check
        if(newLeft < 0) {
            newLeft = 0;
            boundReached = true;
        }

        // bottom bound check
        if(ui.position.top > containmentH - objH) {
            newTop = (containmentH - objH) / _zoom;
            boundReached = true;
        }

        // top bound check
        if(newTop < 0) {
            newTop = 0;
            boundReached = true;
        }

        // fix position
        ui.position.left = newLeft;
        ui.position.top = newTop;

        // inside bounds
        if(!boundReached) {

            // do stuff when element is dragged inside bounds

        }

    }
});

链接到fiddle


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接