Guides when moving jquery-ui-draggable boxes

前端 未结 4 818
不知归路
不知归路 2020-12-12 19:57

I am working on how to show guides when moving boxes like it is in Google Docs Drawing. I would prefer an open-source code or any type of guide before starting writing my ow

4条回答
  •  生来不讨喜
    2020-12-12 20:24

    jquery ui has this already built in, see this demo: http://jqueryui.com/demos/draggable/#snap-to

    if you insist on the guidlines you would maybe have to fork jqueryui or look at the source and see if you can extend it.


    alternatively you could just add your own snapping-functions on top of jQuery ui, i've played with it for a bit, and while it doesn't seem like fun at least it also doesn't seem to be very hard.

    you can view the example on jsfiddle: http://jsfiddle.net/x7uMh/103/ update: this works ~ jQuery 1.9 + jQueryUI 1.9. it breaks in newest jquery+ui. couldn't be bothered to see what exactly the problem is, typically its only minor problems though. just in case that site ever goes down, here's the code:

    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 (make sure to include 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 } 
        ]; 
    }
    
    ​
    

    hope that helps, best, hansi.

提交回复
热议问题