16

Google Docs Drawingのように、ボックスを移動するときにガイドを表示する方法に取り組んでいます。自分で書き始める前に、オープンソースコードまたは任意のタイプのガイドをお勧めします。

  1. 複数のブラウザウィンドウ間でドラッグアンドドロップする必要がないため、HTML5ドラッグアンドドロップは必要ありません。
  2. また、ボックスにjquery-ui-draggableを使用しています。

ここに画像の説明を入力してください

4

4 に答える 4

32

jquery uiにはこれがすでに組み込まれています。次のデモを参照してください:http: //jqueryui.com/demos/draggable/#snap-to

ガイドラインを主張する場合は、jqueryuiをフォークするか、ソースを調べて拡張できるかどうかを確認する必要があります。


あるいは、jQuery uiの上に独自のスナップ関数を追加することもできますが、私はそれを少し試してみましたが、少なくとも面白くはないようですが、それほど難しくはないようです。

jsfiddleで例を見ることができます: http: //jsfiddle.net/x7uMh/103/ 更新:これは動作します〜jQuery 1.9 +jQueryUI1.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 } 
    ]; 
}

​

それが役立つことを願っています、最高の、ハンシ。

于 2012-04-20T13:14:14.383 に答える
11

ドラッグ可能なボックスの横に境界線だけを使用した簡単な例を作成しました。ボックスをドラッグすると表示されます。ここでデモを見る

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');
        }
    });
});
于 2012-09-13T15:56:29.313 に答える
1

まだこれを行う方法を見つけようとしている人のために、私はフィドルを作成します

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/

于 2014-07-09T06:10:34.570 に答える
1

私はこの質問から答えを得ました:Javascriptのドラッグアンドドロップ-イラストレータースタイルの「スマートガイド」

これが探しているものだと思います。また、同じ側のラインをサポートすることで改善しました。これが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
});
于 2016-10-06T14:53:51.627 に答える