Question

Question is about the onstart event handler for Element.drag in the newly announced Snap.svg.

The intention of the code below is to register event handlers for the start and stop of a drag (onstart/onstop) on an svg object.

        var s = Snap(800,600);

        var bigCircle = s.circle(300,150,100);

        bigCircle.drag(null,
                function(){
                    console.log("Move started");
                },
                function(){
                    console.log("Move stopped");
                }
        );

The console messages work fine on drag start and stop, but the null overrides the default onmove function - resulting in no actual drag happening. How do I pass something that says "I don't want to mess with the default onmove"?

(Note: I'd prefer to register an event handler by means of assignment, like the familiar onClick, but that's a different matter.)


Note added after few hours: The Raphael.js documentation and examples provide some clues. At least now I know how to pass in a proper function for onmove that provides the default move behavior:

        var s = Snap(800,600);

        var bigCircle = s.circle(300,150,100);

        start = function() {
            this.ox = parseInt(this.attr("cx"));
            this.oy = parseInt(this.attr("cy"));
            console.log("Start move, ox=" + this.ox + ", oy=" + this.oy);
        }

        move = function(dx, dy) {
            this.attr({"cx": this.ox + dx, "cy": this.oy + dy});
        }

        stop = function() {
            this.ox = parseInt(this.attr("cx"));
            this.oy = parseInt(this.attr("cy"));
            console.log("Stop move, ox=" + this.ox + ", oy=" + this.oy);
        }

        bigCircle.drag(move, start, stop);
Was it helpful?

Solution

I'm not sure if I'm misunderstanding what you exactly want...don't you want to implement the drag ?

So for example...

var s = Snap(400,400);
var bigCircle = s.circle(150, 150, 100);

var moveFunc = function (dx, dy, posx, posy) {
    this.attr( { cx: posx , cy: posy } ); // basic drag, you would want to adjust to take care of where you grab etc.
};

bigCircle.drag( moveFunc,
            function(){
                console.log("Move started");
            },
            function(){
                console.log("Move stopped");
            }
    );

JSBin here http://jsbin.com/akoCAkA/1/edit?html,js,output

OTHER TIPS

There is an example how to drag with SnapSVG here: http://svg.dabbles.info/snaptut-drag.html

var s = Snap("#svgout");

var rect = s.rect(20,20,40,40);
var circle = s.circle(60,150,50);

var move = function(dx,dy) {
        this.attr({
                    transform: this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]
                });
}

var start = function() {
        this.data('origTransform', this.transform().local );
}
var stop = function() {
        console.log('finished dragging');
}

rect.drag(move, start, stop );
circle.drag(move, start, stop );

After struggling for some hours to do this with snap.js, I finally discovered svg.js and its draggable plugin, with which it is so much easier:

var draw = SVG('svg');
var circle = draw.circle(10).attr({cx:30,cy:30,fill:'#f06'});
circle.dragend = function(delta, event) {
    alert(this.attr('cx'))
}
circle.draggable();

So, I switched to svg.js ...

The eve.on method wasn't working for me, so I did some poking around and managed to recreate the onmove function. The other two (onstart and onend) require no specific code to work apparently:

var S = Snap(300,300);

var bigCircle = S.circle(150, 150, 100);

bigCircle.drag(onDragMove, onDragStart, onDragEnd);

var ddx = 0;
var ddy = 0;
var dxDone = 0;
var dyDone = 0;

function onDragMove (dx, dy, posx, posy) {
    dx = dx + dxDone;    // dx and dy reset to 0 for some reason when this function begins
    dy = dy + dyDone;    // retain the last move's position as the starting point
    this.attr( { transform: 't'+dx+','+dy } );
    ddx = dx;
    ddy = dy;
    console.log('moving...');
};

function onDragStart(x,y,e) {
    console.log('start!');
};

function onDragEnd(e) {
    dxDone = ddx;
    dyDone = ddy;
    console.log('end!');
};

Please note however that this should only be used for one dragged object at a time. If you need a custom drag for another object, you'll have to rename the functions (ie onDragStart2) and the four variables declared outside of them (ie ddx2) after duplicating it.

Also, the 'transform' string format I passed (tx,y) came from what I found after doing console.log( this.attr('transform') ). I'm not familiar with matrix() just yet, so this way seemed easier.

Hope this helps!

I can't drag group elements with custom handlers, s.drag() makes it possible. So i searched further found its possible.

Documentation:

Additionaly following drag events are triggered: drag.start. on start, drag.end. on > end and drag.move. on every move. When element is dragged over another element > drag.over. fires as well.

Solution:

    s.drag();
    eve.on("snap.drag.start." + s.id, function () {
        console.log('cool');
    });

    eve.on("snap.drag.move." + s.id, function () {
        console.log('cooler');
    });

    eve.on("snap.drag.end." + s.id, function () {
        console.log('way cool');
    });

eve is not documented on snapsvg it is available on raphael. i don't know this is proper way or hack.

Try this

var paper = Snap("#main"); 

var object  = paper.circle(300,150,100)
object .attr({
  stroke: "#000",
  strokeWidth: 10,
  strokeLinecap:"round"
}); 

var move1 = function(dx,dy, posx, posy) { 
this.transform(this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]) 
};

var start = function() {
        this.data('origTransform', this.transform().local );
}
var stop = function() {
        console.log('dragging done');
}

object.drag(move1, start, stop ); 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top