ПРОБЛЕМА
У меня есть небольшая проблема перетаскивания элементов в расширяемый контейнер div.
Как только элемент фактически находится в контейнере, элементы перетаскиваются в тон и работают так, как они должны.
Более крупные элементы, которые перетаскиваются на масштабируемый контейнер, не имеют слишком большой проблемы.
Но когда перетаскиваются меньшие элементы, вы можете видеть, что мышь больше не привязана к указанному элементу, а когда она отбрасывается, она немного опускается, где она должна упасть.
Я пытаюсь найти решение, которое моя мышь остается на элементе, и он падает там, где он должен упасть.
Я решил проблемы пополам, и вы можете видеть ниже, но это последний фрагмент головоломки, которая сводит меня с ума. Если у кого есть время, чтобы протянуть руку, мы будем очень благодарны.
Вот код-щелчок и перетащите два синих элемента на белый контейнер, чтобы попробовать его
Codepen
Полноэкранный просмотр
Короткое GIF в действии
Этот wil поможет убедиться, что область сбрасывается с масштабированным контейнером.
$.ui.ddmanager.prepareOffsets = function(t, event) {
var i, j, m = $.ui.ddmanager.droppables[t.options.scope] || [],
type = event ? event.type : null,
list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
droppablesLoop: for (i = 0; i < m.length; i++) {
if (m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0], (t.currentItem || t.element)))) {
continue;
}
for (j = 0; j < list.length; j++) {
if (list[j] === m[i].element[0]) {
m[i].proportions().height = 0;
continue droppablesLoop;
}
}
m[i].visible = m[i].element.css("display") !== "none";
if (!m[i].visible) {
continue;
}
if (type === "mousedown") {
m[i]._activate.call(m[i], event);
}
m[i].offset = m[i].element.offset();
m[i].proportions({
width: m[i].element[0].offsetWidth * percent,
height: m[i].element[0].offsetHeight * percent
});
}
};
Разрешить изменение размера элемента в масштабированном контейнере
function resizeFix(event, ui) {
var changeWidth = ui.size.width - ui.originalSize.width,
newWidth = ui.originalSize.width + changeWidth / percent,
changeHeight = ui.size.height - ui.originalSize.height,
newHeight = ui.originalSize.height + changeHeight / percent;
ui.size.width = newWidth;
ui.size.height = newHeight;
}
Делает так, чтобы перетаскивание выполнялось на масштабированном контейнере
function dragFix(event, ui) {
var containmentArea = $("#documentPage_"+ui.helper.parent().parent().attr('id').replace(/^(\w+)_/, "")),
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()));
}
Создание перетаскиваемого элемента, который можно перетащить в поле.
.directive('draggableTypes', function() {
return {
restrict:'A',
link: function(scope, element, attrs) {
element.draggable({
zIndex:3000,
appendTo: 'body',
helper: function(e, ui){
var formBox = angular.element($("#formBox"));
percent = formBox.width() / scope.templateData.pdf_width;
if(element.attr('id') == 'textbox_item')
return $('<div class="text" style="text-align:left;font-size:14px;width:200px;height:20px;line-height:20px;">New Text Box.</div>').css({ 'transform': 'scale(' + percent + ')', '-moz-transform': 'scale(' + percent + ')', '-webkit-transform': 'scale(' + percent + ')', '-ms-transform': 'scale(' + percent + ')'});
if(element.attr('id') == 'sm_textbox_item')
return $('<div class="text" style="text-align:left;font-size:14px;width:5px;height:5px;line-height:20px;"></div>').css({ 'transform': 'scale(' + percent + ')', '-moz-transform': 'scale(' + percent + ')', '-webkit-transform': 'scale(' + percent + ')', '-ms-transform': 'scale(' + percent + ')'});
}
});
}
};
})
Создайте перетаскиваемые/изменяемые размеры элементы, которые уже могут быть в поле, и применяя исправление перетаскивания/изменения размера к этим
.directive('textboxDraggable', function() {
return {
restrict:'A',
link: function(scope, element, attrs) {
element.draggable({
cursor: "move",
drag: dragFix,
start: function(event, ui) {
var activeId = element.attr('id');
scope.activeElement.id = activeId;
scope.activeElement.name = scope.templateItems[activeId].info.name;
scope.$apply();
}
});
element.resizable({
minWidth: 25,
minHeight: 25,
resize: resizeFix,
stop: function( event, ui ) {
var activeId = element.attr('id');
scope.activeElement.duplicateName = false;
scope.activeElement.id = activeId;
scope.activeElement.name = scope.templateItems[activeId].info.name;
scope.templateItems[activeId]['style']['width'] = element.css('width');
scope.templateItems[activeId]['style']['height'] = element.css('height');
scope.$apply();
}
})
}
};
})
Что происходит при отбрасывании элемента
.directive('droppable', function($compile) {
return {
restrict: 'A',
link: function(scope,element,attrs){
element.droppable({
drop:function(event,ui) {
var draggable = angular.element(ui.draggable),
draggable_parent = draggable.parent().parent(),
drag_type = draggable.attr('id'),
documentBg = element,
x = ui.offset.left,
y = ui.offset.top,
element_top = (y - documentBg.offset().top - draggable.height() * (percent - 1) / 2) / percent,
element_left = (x - documentBg.offset().left - draggable.width() * (percent - 1) / 2) / percent,
timestamp = new Date().getTime();
//just get the document page of where the mouse is if its a new element
if(draggable_parent.attr('id') == 'template_builder_box_container' || draggable_parent.attr('id') == 'template_builder_container')
var documentPage = documentBg.parent().parent().attr('id').replace(/^(\w+)_/, "");
//if you are dragging an element that was already on the page, get parent of draggable and not parent of where mouse is
else var documentPage = draggable_parent.parent().parent().attr('id').replace(/^(\w+)_/, "");
if(drag_type == "textbox_item")
{
scope.activeElement.id = scope.templateItems.push({
info: {'page': documentPage,'name': 'textbox_'+timestamp, 'type': 'text'},
style: {'text-align':'left','font-size':'14px','top':element_top+'px','left':element_left+'px', 'width':'200px', 'height':'20px'}
}) - 1;
scope.activeElement.name = 'textbox_'+timestamp;
}
else if(drag_type == "sm_textbox_item")
{
scope.activeElement.id = scope.templateItems.push({
info: {'page': documentPage,'name': '', 'type': 'text'},
style: {'text-align':'left','font-size':'14px','top':element_top+'px','left':element_left+'px', 'width':'5px', 'height':'5px'}
}) - 1;
scope.activeElement.name = 'textbox_'+timestamp;
}
else {
scope.templateItems[scope.activeElement.id]['style']['top'] = draggable.css('top');
scope.templateItems[scope.activeElement.id]['style']['left'] = draggable.css('left');
}
scope.$apply();
}
});
}
};
})
последнее, но не менее важное: мой контроллер
.controller('testing', function($scope, $rootScope, $state, $stateParams) {
$scope.templateItems = [];
$scope.activeElement = { id: undefined, name: undefined };
$scope.templateData = {"id":"12345", "max_pages":1,"pdf_width":385,"pdf_height":800};
$scope.clickElement = function(index) { $scope.activeElement = { id: index, name: $scope.templateItems[index].info.name } }
});
Вот основа моего html
<div id="formBox" ng-style="formbox(templateData.pdf_width)" zoom>
<div class="trimSpace" ng-style="trimSpace(templateData.pdf_width)" zoom>
<div id="formScale" ng-style="formScale(templateData.pdf_width)" zoom>
<form action="#" id="{{ templateData.id }}_form">
<div ng-repeat="key in [] | range:templateData.max_pages">
<div class="formContainer" id="{{ templateData.id + '_' + (key+1) }}" ng-style="{width: templateData.pdf_width+'px', height: templateData.pdf_height+'px'}">
<div class="formContent">
<div class="formBackground" id="documentPage_{{ (key+1) }}" droppable>
<div ng-hide="preview" ng-repeat="item in templateItems">
<div ng-if="item.info.page == (key+1) && item.info.type == 'text'" id="{{ $index }}" data-type="{{ item.info.type }}" ng-click="clickElement($index)" class="text" ng-style="item.style" textbox-draggable>{{ item.info.name }}</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>