我正在应用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?
非常感谢您的任何答复。
自问这个问题已经有一段时间了。我已经找到(实际创建了)答案。它所需要的只是设置回调处理程序。无需编辑jquery-ui!
注意:此示例中的zoomScale是全局变量,并且使用animate(由jquery.transform.js辅助)设置转换,如下所示:
target.animate({ transform: 'scale(' + zoomScale + ')' });
看看这个:
转换scale()修复以调整大小:
$(this).resizable({ minWidth: -(contentElem.width()) * 10, // these need to be large and negative minHeight: -(contentElem.height()) * 10, // so we can shrink our resizable while scaled resize: function(event, ui) { var changeWidth = ui.size.width - ui.originalSize.width; // find change in width var newWidth = ui.originalSize.width + changeWidth / zoomScale; // adjust new width by our zoomScale var changeHeight = ui.size.height - ui.originalSize.height; // find change in height var newHeight = ui.originalSize.height + changeHeight / zoomScale; // adjust new height by our zoomScale ui.size.width = newWidth; ui.size.height = newHeight; } });
转换scale()修复可拖动对象:
$(this).draggable({ handle: '.drag-handle', start: function(event, ui) { ui.position.left = 0; ui.position.top = 0; }, drag: function(event, ui) { var changeLeft = ui.position.left - ui.originalPosition.left; // find change in left var newLeft = ui.originalPosition.left + changeLeft / (( zoomScale)); // adjust new left by our zoomScale var changeTop = ui.position.top - ui.originalPosition.top; // find change in top var newTop = ui.originalPosition.top + changeTop / zoomScale; // adjust new top by our zoomScale ui.position.left = newLeft; ui.position.top = newTop; } });
如果您发现任何问题或对此有进一步的改进,请告诉我。:)