在我的应用程序中,我有一个可以改变CSS缩放的div。
不幸的是,这与坐标空间混淆。当超过可缩放区域1页px!= 1px时:)
当涉及到droppables时,它会完全打破交叉点检测。
我正在寻找有关我应该从哪里开始尝试处理此问题的提示?
我在这里做了一个演示。
小提琴:
HTML:
<div id="dse">
<div id="ds">Drop here!</div>
</div>
<p>
<div id="widget">Drag me!</div>
</p>
CSS:
#dse{
position:relative;
width:640px;
height:360px;
zoom:0.75;
-moz-transform: scale(0.75);
-moz-transform-origin:0 0;
-o-transform: scale(0.75);
-o-transform-origin:0 0;
}
#ds{
position:relative;
zoom:1;
width:640px;
height:360px;
border: solid 1px black;
font-size:2em;
}
#widget{
position:relative;
width:150px;
height:50px;
border: solid 1px black;
}
.droppableActive{
background-color:red;
}
.droppableHover{
background-color:green;
}
JS:
$("#widget").draggable({
opacity : 0.7,
scroll : false,
revert: function(dropped){
var wasDropped = dropped && dropped[0].id == "ds";
if(!wasDropped){$(this).animate({ top: 0, left: 0 }, 'slow');}
return !wasDropped;
}
,
stop: function(evt, ui) {
var canvasLeft = $('#ds').offset().left;
var canvasTop = $('#ds').offset().top;
alert('ui.position.left: ' + (ui.position.left) + ' canvasLeft: ' + canvasLeft);
alert('ui.position.top: ' + (ui.position.top) + ' canvasTop: ' + canvasTop);
}
});
$("#ds").droppable({
activeClass: 'droppableActive',
hoverClass: 'droppableHover',
accept: "#widget",
drop: function(evt, ui){
id = ui.draggable.attr('id');
alert('id: ' + id);
}
});
答案 0 :(得分:0)
我遇到了同样的问题,但仅在我的情况下,这两个问题:可拖放项和可拖动项都在缩放容器中(具有zoom
css属性!)。
可拖动可以轻松地通过“ dragFix”修复程序进行修复:
var zoomScale = parseFloat($('.container').css('zoom'));
$('.drag__item').draggable({
drag: function (event, ui) {
var changeLeft = ui.position.left - ui.originalPosition.left;
var newLeft = ui.originalPosition.left + changeLeft / zoomScale;
var changeTop = ui.position.top - ui.originalPosition.top;
var newTop = ui.originalPosition.top + changeTop / zoomScale;
ui.position.left = newLeft;
ui.position.top = newTop;
}
});
要修复可投放,我们需要编辑jquery-ui代码。考虑到编辑库源代码不是一个好主意,让我们重写intersect
方法。
问题是x1
和y1
坐标(可拖动项目的顶部,左)在先前的“ dragFix”修复后被破坏,因此,交集检测无法按预期进行。
因此,我们需要归一化x1
和y1
坐标。
var intersect = $.ui.intersect = (function () {
function isOverAxis(x, reference, size) {
return (x >= reference) && (x < (reference + size));
}
return function (draggable, droppable, toleranceMode, event) {
if (!droppable.offset) {
return false;
}
var x1 = draggable.offset.left + draggable.position.left - draggable.originalPosition.left + draggable.margins.left,//here is the fix for scaled container
y1 = draggable.offset.top + draggable.position.top - draggable.originalPosition.top + draggable.margins.top,//here is the fix for scaled container
x2 = x1 + draggable.helperProportions.width,
y2 = y1 + draggable.helperProportions.height,
l = droppable.offset.left,
t = droppable.offset.top,
r = l + droppable.proportions().width,
b = t + droppable.proportions().height;
switch (toleranceMode) {
case 'fit':
return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
case 'intersect':
return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
x2 - (draggable.helperProportions.width / 2) < r && // Left Half
t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
y2 - (draggable.helperProportions.height / 2) < b); // Top Half
case 'pointer':
return isOverAxis(event.pageY, t, droppable.proportions().height) &&
isOverAxis(event.pageX, l, droppable.proportions().width);
case 'touch':
return (
(y1 >= t && y1 <= b) || // Top edge touching
(y2 >= t && y2 <= b) || // Bottom edge touching
(y1 < t && y2 > b) // Surrounded vertically
) && (
(x1 >= l && x1 <= r) || // Left edge touching
(x2 >= l && x2 <= r) || // Right edge touching
(x1 < l && x2 > r) // Surrounded horizontally
);
default:
return false;
}
};
})();
从jquery 1.12 $ .ui.intersect函数开始,它的作用域是一定范围的,因此以后不能直接对其进行修改。它在$ .ui.ddmanager中被称为局部变量,因此即使您修改$ .ui.intersect,也不会使用它。对其进行自定义要复杂一些。您可以通过这种方式进行操作,基本上是先检查相交,然后在$ .ui.ddmanager上重新定义拖放方法,以便它调用修改后的相交:
$.ui.ddmanager.drag = function (draggable, event) {
// If you have a highly dynamic page, you might try this option. It renders positions
// every time you move the mouse.
if (draggable.options.refreshPositions) {
$.ui.ddmanager.prepareOffsets(draggable, event);
}
// Run through all droppables and check their positions based on specific tolerance options
$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function () {
if (this.options.disabled || this.greedyChild || !this.visible) {
return;
}
var parentInstance, scope, parent,
intersects = intersect(draggable, this, this.options.tolerance, event),
c = !intersects && this.isover ?
'isout' :
(intersects && !this.isover ? 'isover' : null);
if (!c) {
return;
}
if (this.options.greedy) {
// find droppable parents with same scope
scope = this.options.scope;
parent = this.element.parents(':data(ui-droppable)').filter(function () {
return $(this).droppable('instance').options.scope === scope;
});
if (parent.length) {
parentInstance = $(parent[0]).droppable('instance');
parentInstance.greedyChild = (c === 'isover');
}
}
// We just moved into a greedy child
if (parentInstance && c === 'isover') {
parentInstance.isover = false;
parentInstance.isout = true;
parentInstance._out.call(parentInstance, event);
}
this[c] = true;
this[c === 'isout' ? 'isover' : 'isout'] = false;
this[c === 'isover' ? '_over' : '_out'].call(this, event);
// We just moved out of a greedy child
if (parentInstance && c === 'isout') {
parentInstance.isout = false;
parentInstance.isover = true;
parentInstance._over.call(parentInstance, event);
}
});
}
$.ui.ddmanager.drop = function (draggable, event) {
var dropped = false;
// Create a copy of the droppables in case the list changes during the drop (#9116)
$.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function () {
if (!this.options) {
return;
}
if (!this.options.disabled && this.visible &&
intersect(draggable, this, this.options.tolerance, event)) {
dropped = this._drop.call(this, event) || dropped;
}
if (!this.options.disabled && this.visible && this.accept.call(this.element[0],
(draggable.currentItem || draggable.element))) {
this.isout = true;
this.isover = false;
this._deactivate.call(this, event);
}
});
return dropped;
}