Drag limiter

Limiting drag handler plugin (not tested much yet)


SVGElement.prototype.getTransformToElement = SVGElement.prototype.getTransformToElement || function(elem) {
        return elem.getScreenCTM().inverse().multiply(this.getScreenCTM());
    };


var s = Snap("#svgout"); 
s.attr({ viewBox: "0 0 100 100" });
(function() {

  Snap.plugin( function( Snap, Element, Paper, global ) {

        Element.prototype.globalToLocal = function( globalPoint ) {
                var globalToLocal = this.node.getTransformToElement( this.paper.node ).inverse();
                globalToLocal.e = globalToLocal.f = 0;
                return globalPoint.matrixTransform( globalToLocal );
        };

        Element.prototype.getCursorPoint = function( x, y ) {
                var pt = this.paper.node.createSVGPoint();      
                pt.x = x; pt.y = y;
                return pt.matrixTransform( this.paper.node.getScreenCTM().inverse()); 
        }

        Element.prototype.limitDrag = function( params ) {
                this.data('dragParams', params );
                return this.drag( limitMoveDrag, limitStartDrag );
        };

        function limitMoveDrag( dx, dy, ax, ay ) {
                var params = this.data('dragParams');
                var cursorPoint = this.getCursorPoint( ax, ay );
                var pt = this.paper.node.createSVGPoint();
                var ibb = this.data('ibb');

                pt.x = cursorPoint.x - this.data('op').x;
                pt.y = cursorPoint.y - this.data('op').y;

                if( ibb.x2 + pt.x > params.maxx ) { pt.x = params.maxx - ibb.x2; }
                if( ibb.y2 + pt.y > params.maxy ) { pt.y = params.maxy - ibb.y2; }
                if( ibb.x + pt.x < params.minx ) { pt.x = params.minx - ibb.x; }
                if( ibb.y + pt.y < params.miny ) { pt.y = params.miny - ibb.y; }
        
                var localPt = this.globalToLocal( pt );

                this.transform( this.data('ot').toTransformString() + "t" + [  localPt.x, localPt.y ] );
        };



        function limitStartDrag( x, y, ev ) {
                this.data('ibb', this.getBBox()); 
                this.data('op', this.getCursorPoint( x, y ));
                this.data('ot', this.transform().localMatrix);
        };
  });
})();


var myCircle2 = s.circle(20,20,20).attr({ fill: 'blue' }).limitDrag({ x: 0, y: 0, minx: 0, miny: 0, maxx: 100, maxy: 100 });
var myRect =   s.rect(0,0,30,30).attr({ fill: 'yellow' })
                .limitDrag({ x: 0, y: 0, minx: 0, miny: 0, maxx: 100, maxy: 100 })
                .transform('r45');

var corner1 = s.circle(0,0,2);
var corner2 = s.circle(100,100,2);

   


        
The actual svg markup looks like this (when you've clicked on run)....