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()
но, похоже, это тоже не правильный ход.
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", если хотите, чтобы результаты тоже были видны).