【发布时间】:2012-04-30 01:24:51
【问题描述】:
我正在应用 CSS 转换(以及特定于浏览器的 -webkit、-o 等):
变换:matrix(0.5 , 0 , 0, 0.5, 0 , 0);
到一个 div,然后在该 div 的子级上使用 jQuery 的 draggable() 和 resizable() 插件。
我遇到的问题是,当拖动或调整子元素的大小时,jQuery 所做的更改与鼠标“同步”的因子等于所应用的比例。
我在 stackoverflow 上找到了一个解决方案(尽管我愚蠢地没有为它添加书签,现在找不到它....),它建议修补插件,并且效果很好。它沿着这条线走:
function monkeyPatch_mouseStart() {
// don't really need this, but in case I did, I could store it and chain
// var oldFn = $.ui.draggable.prototype._mouseStart ;
$.ui.draggable.prototype._mouseStart = function(event) {
var o = this.options;
//Create and append the visible helper
this.helper = this._createHelper(event);
//Cache the helper size
this._cacheHelperProportions();
//If ddmanager is used for droppables, set the global draggable
if($.ui.ddmanager)
$.ui.ddmanager.current = this;
/*
* - Position generation -
* This block generates everything position related - it's the core of draggables.
*/
//Cache the margins of the original element
this._cacheMargins();
//Store the helper's css position
this.cssPosition = this.helper.css("position");
this.scrollParent = this.helper.scrollParent();
//The element's absolute position on the page minus margins
//PATCH CODE
this.offset = this.positionAbs = getViewOffset(this.element[0]);
//END
this.offset = {
top: this.offset.top - this.margins.top,
left: this.offset.left - this.margins.left
};
$.extend(this.offset, {
click: { //Where the click happened, relative to the element
left: event.pageX - this.offset.left,
top: event.pageY - this.offset.top
},
parent: this._getParentOffset(),
relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
});
//Generate the original position
this.originalPosition = this.position = this._generatePosition(event);
this.originalPageX = event.pageX;
this.originalPageY = event.pageY;
//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
if(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)){
}
//Set a containment if given in the options
if(o.containment)
this._setContainment();
//Trigger event + callbacks
if(this._trigger("start", event) === false) {
this._clear();
return false;
}
//Recache the helper size
this._cacheHelperProportions();
//Prepare the droppable offsets
if ($.ui.ddmanager && !o.dropBehaviour)
$.ui.ddmanager.prepareOffsets(this, event);
this.helper.addClass("ui-draggable-dragging");
this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
if ( $.ui.ddmanager && $.ui.ddmanager.dragStart) $.ui.ddmanager.dragStart(this, event);
return true;
}
}
function getViewOffset(node) {
var x = 0, y = 0, win = node.ownerDocument.defaultView || window;
if (node) addOffset(node);
return { left: x, top: y };
function getStyle(node) {
return node.currentStyle || // IE
win.getComputedStyle(node, '');
}
function addOffset(node) {
var p = node.offsetParent, style, X, Y;
x += parseInt(node.offsetLeft, 10) || 0;
y += parseInt(node.offsetTop, 10) || 0;
if (p) {
x -= parseInt(p.scrollLeft, 10) || 0;
y -= parseInt(p.scrollTop, 10) || 0;
if (p.nodeType == 1) {
var parentStyle = getStyle(p)
, localName = p.localName
, parent = node.parentNode;
if (parentStyle.position != 'static') {
x += parseInt(parentStyle.borderLeftWidth, 10) || 0;
y += parseInt(parentStyle.borderTopWidth, 10) || 0;
if (localName == 'TABLE') {
x += parseInt(parentStyle.paddingLeft, 10) || 0;
y += parseInt(parentStyle.paddingTop, 10) || 0;
}
else if (localName == 'BODY') {
style = getStyle(node);
x += parseInt(style.marginLeft, 10) || 0;
y += parseInt(style.marginTop, 10) || 0;
}
}
else if (localName == 'BODY') {
x += parseInt(parentStyle.borderLeftWidth, 10) || 0;
y += parseInt(parentStyle.borderTopWidth, 10) || 0;
}
while (p != parent) {
x -= parseInt(parent.scrollLeft, 10) || 0;
y -= parseInt(parent.scrollTop, 10) || 0;
parent = parent.parentNode;
}
addOffset(p);
}
}
else {
if (node.localName == 'BODY') {
style = getStyle(node);
x += parseInt(style.borderLeftWidth, 10) || 0;
y += parseInt(style.borderTopWidth, 10) || 0;
var htmlStyle = getStyle(node.parentNode);
x -= parseInt(htmlStyle.paddingLeft, 10) || 0;
y -= parseInt(htmlStyle.paddingTop, 10) || 0;
}
if ((X = node.scrollLeft)) x += parseInt(X, 10) || 0;
if ((Y = node.scrollTop)) y += parseInt(Y, 10) || 0;
}
}
}
var isNumber = function(value) {
return !isNaN(parseInt(value, 10));
};
我进行了自己的更改,例如(您可以在 6-7 行看到运动乘以“比例因子”):
$.ui.draggable.prototype._generatePosition = function(event) {
var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
var pageX = event.pageX;
var pageY = event.pageY;
//PATCH CODE
if($(this.element[0]).hasClass('item')){
pageY = this.originalPageY + ((pageY - this.originalPageY)*(1/$.viewbox.foreground.scale));
pageX = this.originalPageX + ((pageX - this.originalPageX)*(1/$.viewbox.foreground.scale));
}
//END
/*
* - Position constraining -
* Constrain the position to a mix of grid, containment.
*/
if(this.originalPosition) { //If we are not dragging yet, we won't check for options
if(this.containment) {
if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
}
if(o.grid) {
var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
}
}
return {
top: (
pageY // The absolute mouse position
- this.offset.click.top // Click offset (relative to the element)
- this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
- this.offset.parent.top // The offsetParent's offset without borders (offset + border)
+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
),
left: (
pageX // The absolute mouse position
- this.offset.click.left // Click offset (relative to the element)
- this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
- this.offset.parent.left // The offsetParent's offset without borders (offset + border)
+ ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
)
};
}
非常感谢提出这个建议的人。
所以,我的问题!有没有人遇到过一种在不需要修补 jQuery 的缩放元素中具有可拖动/可调整大小事件的好方法?我用谷歌搜索过,这是我能找到的最好的解决方案。有谁知道可能在这些条件下使用 CSS 转换的 jquery 替代方案?
非常感谢您的任何回复。
【问题讨论】:
-
我不确定它是否 100% 相关,但自从你发布了这个问题,我回答了一些不完全不同的 here。当时的解决方案是提供一个
drag回调来强制自定义容器来代替可拖动的本机容器行为,该行为被容器的动态调整大小所破坏。 -
我明白你的意思,这是一个类似的情况,父/包含元素正在以一种方式被操纵 jquery 不检查(正如你所不希望的那样)。回调是个好主意,下次我会记住这一点。最后,我编写了一个专门针对我正在做的事情的 jquery ui 小部件工厂扩展。如果我有时间,我会清理掉我的客户代码并将其放在这里。
-
Imdad,这不是一个错误,它缺少绝大多数开发人员不需要的功能,实施它对许多人来说会浪费性能。无论如何,我没有完整的解决方案,但我有一个事件脚本,欢迎您调整(可能对您来说更容易):extraordinarythoughts.com/2012/02/13/…
-
@Shawn 该脚本看起来很有用,可能会像您所说的那样适应。谢谢
标签: javascript jquery css jquery-ui css-transforms