移动jquery-ui-draggable盒子时的指南

我正在研究如何在像Google Docs Drawing中那样移动框时显示指南。 在开始编写自己的代码之前,我更喜欢开源代码或任何类型的指南。

  1. 我不需要跨多个浏览器窗口拖放,所以我不需要HTML5 Drag-n-Drop。
  2. 我也使用jquery-ui-draggable for boxes。

在此处输入图像描述

jquery ui已经内置了这个,请看这个演示: http : //jqueryui.com/demos/draggable/#snap-to

如果你坚持使用guidlines,你可能需要分叉jqueryui或查看源代码,看看你是否可以扩展它。


或者你可以在jQuery ui之上添加你自己的捕捉function,我已经玩过一段时间了,虽然它看起来并不好玩至少它似乎也不是很难。

你可以在jsfiddle上查看这个例子: http : //jsfiddle.net/x7uMh/103/ update:这个工作~jQuery 1.9 + jQueryUI 1.9。 它打破了最新的jquery + ui。 我不知道究竟是什么问题,通常是它唯一的小问题。 为了防止网站出现故障,这里是代码:

CSS

body{ font-family: courier new, courier; font-size: 12px; } .draggable{ border: 1px solid #ccc; display: inline-block; cursor: move; position: absolute; } .guide{ display: none; position: absolute; left: 0; top: 0; } #guide-h{ border-top: 1px dashed #55f; width: 100%; } #guide-v{ border-left: 1px dashed #55f; height: 100%; } ​ 

HTML

 
drag me!
you can drag me too, if you like
hep hep

javascript(确保包含jquery + jquery ui)

 var MIN_DISTANCE = 10; // minimum distance to "snap" to a guide var guides = []; // no guides available ... var innerOffsetX, innerOffsetY; // we'll use those during drag ... $( ".draggable" ).draggable({ start: function( event, ui ) { guides = $.map( $( ".draggable" ).not( this ), computeGuidesForElement ); innerOffsetX = event.originalEvent.offsetX; innerOffsetY = event.originalEvent.offsetY; }, drag: function( event, ui ){ // iterate all guides, remember the closest h and v guides var guideV, guideH, distV = MIN_DISTANCE+1, distH = MIN_DISTANCE+1, offsetV, offsetH; var chosenGuides = { top: { dist: MIN_DISTANCE+1 }, left: { dist: MIN_DISTANCE+1 } }; var $t = $(this); var pos = { top: event.originalEvent.pageY - innerOffsetY, left: event.originalEvent.pageX - innerOffsetX }; var w = $t.outerWidth() - 1; var h = $t.outerHeight() - 1; var elemGuides = computeGuidesForElement( null, pos, w, h ); $.each( guides, function( i, guide ){ $.each( elemGuides, function( i, elemGuide ){ if( guide.type == elemGuide.type ){ var prop = guide.type == "h"? "top":"left"; var d = Math.abs( elemGuide[prop] - guide[prop] ); if( d < chosenGuides[prop].dist ){ chosenGuides[prop].dist = d; chosenGuides[prop].offset = elemGuide[prop] - pos[prop]; chosenGuides[prop].guide = guide; } } } ); } ); if( chosenGuides.top.dist <= MIN_DISTANCE ){ $( "#guide-h" ).css( "top", chosenGuides.top.guide.top ).show(); ui.position.top = chosenGuides.top.guide.top - chosenGuides.top.offset; } else{ $( "#guide-h" ).hide(); ui.position.top = pos.top; } if( chosenGuides.left.dist <= MIN_DISTANCE ){ $( "#guide-v" ).css( "left", chosenGuides.left.guide.left ).show(); ui.position.left = chosenGuides.left.guide.left - chosenGuides.left.offset; } else{ $( "#guide-v" ).hide(); ui.position.left = pos.left; } }, stop: function( event, ui ){ $( "#guide-v, #guide-h" ).hide(); } }); function computeGuidesForElement( elem, pos, w, h ){ if( elem != null ){ var $t = $(elem); pos = $t.offset(); w = $t.outerWidth() - 1; h = $t.outerHeight() - 1; } return [ { type: "h", left: pos.left, top: pos.top }, { type: "h", left: pos.left, top: pos.top + h }, { type: "v", left: pos.left, top: pos.top }, { type: "v", left: pos.left + w, top: pos.top }, // you can add _any_ other guides here as well (eg a guide 10 pixels to the left of an element) { type: "h", left: pos.left, top: pos.top + h/2 }, { type: "v", left: pos.left + w/2, top: pos.top } ]; }​ 

希望有帮助,最好的,hansi。

我创建了一个简单的例子,在可拖动框旁边只有边框线。 它在我们拖动框时显示出来。 在这里查看演示

HTML:

 

CSS:

 #canvas {width: 1000px;height: 800px;} .topline{ position:absolute; width: 1000%; border-top:1px red dotted; display:none; vertical-align::middle; margin-top:-7px; margin-left:-250%; } .botline{ position:absolute; width: 1000%; bottom:-2px; border-bottom:1px red dotted; display:none; vertical-align::middle; margin-top:500px; margin-left:-250%; } .leftline{ position:absolute; height: 1000%; left:-2px; border-left:1px red dotted; display:none; vertical-align::middle; margin-top:-250%; } .rightline{ position:absolute; height: 1000%; right:-2px; border-right:1px red dotted; display:none; vertical-align::middle; margin-top:-250%; } #box { cursor: move; border:1px solid black; width:150px; height:100px; min-width:80px; min-height:80px; padding:5px; background-color:#1196c1; } 

JavaScript的:

 $(function() { $("#box").draggable({ containment: "#canvas", drag: function() { $(this).find($('.topline')).css('display', 'block'); $(this).find($('.rightline')).css('display', 'block'); $(this).find($('.botline')).css('display', 'block'); $(this).find($('.leftline')).css('display', 'block'); }, start: function() { $(this).find($('.topline')).css('display', 'block'); $(this).find($('.rightline')).css('display', 'block'); $(this).find($('.botline')).css('display', 'block'); $(this).find($('.leftline')).css('display', 'block'); }, stop: function() { $(this).find($('.topline')).css('display', 'none'); $(this).find($('.rightline')).css('display', 'none'); $(this).find($('.botline')).css('display', 'none'); $(this).find($('.leftline')).css('display', 'none'); } }); }); 

对于那些仍在尝试寻找方法的人,我创造了一个小提琴

我使用了snap和$(this).data(’draggable’)。snapElements;

 drag: function(event, ui) { //var snapped = $(this).data('ui-draggable').snapElements; //## for new version of jquery UI var snapped = $(this).data('draggable').snapElements; /* Pull out only the snap targets that are "snapping": */ var snappedTo = $.map(snapped, function(element) { //return element.snapping ? element.item : null; return element.snapping ? element : null; }); if((snappedTo[0].left + snappedTo[0].width) == $(this).offset().left) { console.log('right of snapped item'); $('#guide-v').css({'left': $(this).offset().left}).show(); }else if((snappedTo[0].left) == $(this).offset().left) { console.log('left of snapped item'); $('#guide-v').css({'left': $(this).offset().left}).show(); }else $('#guide-v').hide(); if((snappedTo[0].top) == $(this).offset().top) { console.log('top of snapped item'); $('#guide-h').css({'top': $(this).offset().top}).show(); }else if((snappedTo[0].top + snappedTo[0].height) == $(this).offset().top) { console.log('bottom of snapped item'); $('#guide-h').css({'top': $(this).offset().top}).show(); }else $('#guide-h').hide(); } }); 

http://jsfiddle.net/j6zqN/1/

我从这个问题得到了答案: Javascript拖放 – 插画风格’智能指南’

我认为这正是寻找的东西。 我也通过支持同一侧的线来改进它。 这是JsFiddle: http : //jsfiddle.net/yusrilmaulidanraji/A6CpP/120/

HTML

 

CSS:

 #parent{ width:600px; height:500px; border:1px solid #000; position:relative; } .object1{ background:#aaa; width:100px; height:100px; display:block; position:absolute; left:140px; top:50px; } .object2{ background:#aaa; width:100px; height:150px; display:block; position:absolute; left:140px; top:50px; } .object3{ background:#aaa; width:150px; height:100px; display:block; position:absolute; left:140px; top:50px; } .objectx{ display:none; //background:#fff; width:0px; height:100%; position:absolute; top:0px; left:10px; border-left: 1px solid yellow; } .objecty{ display:none; //background:#fff; width:100%; height:0px; position:absolute; top:10px; left:0px; border-bottom: 1px solid yellow; } 

JS:

 $.ui.plugin.add("draggable", "smartguides", { start: function(event, ui) { var i = $(this).data("draggable"), o = i.options; i.elements = []; $(o.smartguides.constructor != String ? ( o.smartguides.items || ':data(draggable)' ) : o.smartguides).each(function() { var $t = $(this); var $o = $t.offset(); if(this != i.element[0]) i.elements.push({ item: this, width: $t.outerWidth(), height: $t.outerHeight(), top: $o.top, left: $o.left }); }); }, stop: function(event, ui) { $(".objectx").css({"display":"none"}); $(".objecty").css({"display":"none"}); }, drag: function(event, ui) { var inst = $(this).data("draggable"), o = inst.options; var d = o.tolerance; $(".objectx").css({"display":"none"}); $(".objecty").css({"display":"none"}); var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height, xc = (x1 + x2) / 2, yc = (y1 + y2) / 2; for (var i = inst.elements.length - 1; i >= 0; i--){ var l = inst.elements[i].left, r = l + inst.elements[i].width, t = inst.elements[i].top, b = t + inst.elements[i].height, hc = (l + r) / 2, vc = (t + b) / 2; var lss = Math.abs(l - x1) <= d; var ls = Math.abs(l - x2) <= d; var rss = Math.abs(r - x2) <= d; var rs = Math.abs(r - x1) <= d; var tss = Math.abs(t - y1) <= d; var ts = Math.abs(t - y2) <= d; var bss = Math.abs(b - y2) <= d; var bs = Math.abs(b - y1) <= d; var hs = Math.abs(hc - xc) <= d; var vs = Math.abs(vc - yc) <= d; if(lss) { ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; $(".objectx").css({"left":ui.position.left,"display":"block"}); } if(rss) { ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; $(".objectx").css({"left":ui.position.left + ui.helper.width(),"display":"block"}); } if(ls) { ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; $(".objectx").css({"left":ui.position.left + ui.helper.width(),"display":"block"}); } if(rs) { ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; $(".objectx").css({"left":ui.position.left,"display":"block"}); } if(tss) { ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; $(".objecty").css({"top":ui.position.top,"display":"block"}); } if(ts) { ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; $(".objecty").css({"top":ui.position.top + ui.helper.height(),"display":"block"}); } if(bss) { ui.position.top = inst._convertPositionTo("relative", { top: b-inst.helperProportions.height, left: 0 }).top - inst.margins.top; $(".objecty").css({"top":ui.position.top + ui.helper.height(),"display":"block"}); } if(bs) { ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; $(".objecty").css({"top":ui.position.top,"display":"block"}); } if(hs) { ui.position.left = inst._convertPositionTo("relative", { top: 0, left: hc - inst.helperProportions.width/2 }).left - inst.margins.left; $(".objectx").css({"left":ui.position.left + (ui.helper.width()/2),"display":"block"}); } if(vs) { ui.position.top = inst._convertPositionTo("relative", { top: vc - inst.helperProportions.height/2, left: 0 }).top - inst.margins.top; $(".objecty").css({"top":ui.position.top + (ui.helper.height()/2),"display":"block"}); } }; } }); $('.dropped').draggable({ containment: 'parent', smartguides:".dropped", tolerance:5 });