Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript drag/drop - Illustrator style 'smart guides'

I'm looking for a way to implement Adobe Illustrator style 'smart guides' when dragging/dropping in Javascript. I'm currently using jQuery UI's draggable:

$('.object').draggable({
    containment: 'parent',
    snap: '.other-objects',
    snapTolerance: 5
})

This does 90% of what I want - I can drag .object around within it's parent, and it will snap it's edges to .other-objects when it gets close enough.

What I want, however, is for a line of some kind (or a guide of some kind) to appear, if it's in line with the edge of another object, so I can snap stuff in a row without them being directly next to each other.

Does anybody know if this is possible, or how I'd go about doing it?

like image 593
Ben Avatar asked Dec 04 '22 08:12

Ben


1 Answers

I forked the fiddle above, added support for midlines.

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 ls = Math.abs(l - x2) <= d;
                var rs = Math.abs(r - x1) <= d;
                var ts = Math.abs(t - y2) <= d;
                var bs = Math.abs(b - y1) <= d;
                var hs = Math.abs(hc - xc) <= d;
                var vs = Math.abs(vc - yc) <= d; 
            if(ls) {
                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
                $(".objectx").css({"left":l-d-4,"display":"block"});
            }
            if(rs) {
                ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
                 $(".objectx").css({"left":r-d-4,"display":"block"});
            }

            if(ts) {
                ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
                $(".objecty").css({"top":t-d-4,"display":"block"});
            }
            if(bs) {
                ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
                $(".objecty").css({"top":b-d-4,"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":hc-d-4,"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":vc-d-4,"display":"block"});
            }


        };
    }

This way it would be easier to align elements in a row/column.

Check the fiddle below:
http://jsfiddle.net/elin/A6CpP/

like image 64
Eddie Lin Avatar answered Dec 06 '22 20:12

Eddie Lin