jquery перетаскиваемые значения массива содержимого для масштабируемого контейнера

Если бы кто-нибудь мог помочь мне понять, как сделать перетаскиваемые элементы, содержащиеся в 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 некоторого примера кода.

3 ответа

Решение

Версия со сбросом координат в событии перетаскивания (поскольку они уже были пересчитаны для преобразований масштаба), без использования содержимого:

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)

скрипка

В примере ширина и высота контейнера получены внутри drag event, вы также можете хранить их при масштабировании для повышения производительности. Подсчитав их внутри события, они все еще работают после масштабирования, хотя переменная процента все еще должна быть установлена. Чтобы быть действительно общим, его можно получить и внутри события (и вместо фиксированного контейнера можно использовать ui.helper.parent()), поскольку смещение внутри drag event связано (0,0) с контейнером (по крайней мере, для текущей настройки), позволил себе упростить originalleft + (position - originalposition)/percent в position / percentНачальное смещение больше не требуется, поэтому оставьте его в скрипке, но при необходимости его можно добавить заново.

Вот мое решение:

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

        }

    }
});

Ссылка на скрипку

Посмотрите на это:

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

Ваша максимальная правая позиция будет такой: Смещение основного контейнера влево + истинная ширина контейнера (с масштабом) - истинная ширина элемента (чтобы он был внутри контейнера).

(Совет: будьте свободны изменять значение процента " var", если хотите, чтобы результаты тоже были видны).

регулярное выражение

Другие вопросы по тегам