我正在研究如何在移动框时显示指南,就像在 Google Docs Drawing 中一样。在开始编写自己的代码之前,我更喜欢开源代码或任何类型的指南。
- 我不需要跨多个浏览器窗口拖放,所以我不需要 HTML5 拖放。
- 我也在使用 jquery-ui-draggable 作为盒子。
我正在研究如何在移动框时显示指南,就像在 Google Docs Drawing 中一样。在开始编写自己的代码之前,我更喜欢开源代码或任何类型的指南。
jquery ui 已经内置了这个,请看这个演示:http: //jqueryui.com/demos/draggable/#snap-to
如果你坚持指导方针,你可能不得不分叉 jqueryui 或查看源代码,看看你是否可以扩展它。
或者,您可以在 jQuery ui 之上添加自己的捕捉功能,我已经玩过一段时间了,虽然它看起来并不有趣,但至少它似乎也不是很难。
您可以查看 jsfiddle 上的示例:http: //jsfiddle.net/x7uMh/103/ 更新:这可行 ~ 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
<div class="draggable">drag me!</div>
<div class="draggable">you can drag me too, if you like</div>
<div class="draggable">hep hep</div>
<div id="guide-h" class="guide"></div>
<div id="guide-v" class="guide"></div>
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 (e.g. 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 }
];
}
希望对您有所帮助,最好的,汉斯。
我创建了一个简单的示例,在可拖动框旁边只有边框线。当我们拖动盒子时它会显示出来。在此处查看演示
HTML:
<div id="canvas">
<div id="box">
<span class="topline"></span>
<span class="rightline"></span>
<span class="botline"></span>
<span class="leftline"></span>
</div>
</div>
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();
}
});
我从这个问题中得到了答案:Javascript drag/drop - Illustrator style 'smart guides'
我认为这就是正在寻找的东西。我还通过支持同一侧的线路来改进它。这是 JsFiddle:http: //jsfiddle.net/yusrilmaulidanraji/A6CpP/120/
HTML
<div id="parent">
<div class="object1 dropped" style="left:0px;top:300px;background:#a00;"></div>
<div class="object2 dropped"></div>
<div class="object3 dropped" style="left:400px;top:20px;"></div>
<div class="objectx"></div>
<div class="objecty"></div>
</div>
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
});