14

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);
Pranav 웃
  • 8,469
  • 6
  • 38
  • 48
user1685529
  • 237
  • 1
  • 3
  • 11
  • yeah I had the same problem and ended up here, it doesn't make sense that if I want to attach a movestart handler I have to redefine the onmove function – David Fregoli Nov 07 '13 at 11:52

6 Answers6

9

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

Ian
  • 13,724
  • 4
  • 52
  • 75
  • Thanks, you answered my question even as I edited my post with an update after seeing the Rahpael.js example. – user1685529 Oct 24 '13 at 09:42
  • 3
    Well, that JSBIN doesn't drag smoothly from the point on the big circle where the user clicks. It... 'snaps' into position (no pun intended). Just to say that there are gotchas in writing a polished move function, and authors shouldn't have to reinvent this wheel when they write their own handlers. Thread to fix this @ https://github.com/adobe-webplatform/Snap.svg/issues/73#issuecomment-27956964 – Ben Nov 07 '13 at 19:33
8

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 );
MJ Vakili
  • 2,798
  • 1
  • 19
  • 25
dhqvinh
  • 337
  • 4
  • 9
2

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 ...

Erel Segal-Halevi
  • 33,955
  • 36
  • 114
  • 183
1

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!

MKarrow
  • 41
  • 4
0

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.

0

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 ); 
Karthikeyan Ganesan
  • 1,901
  • 20
  • 23