n4rzul
n4rzul

Reputation: 4078

Raphael issue with drag and drop and translation

I am trying to get one of my components to sort of dock to the other one but something seems to get lost after the drag behaviour ends. Go to the JSFiddle below, place the svg cursor somewhere closer to the top and click the component on the left. Now place the svg cursor a little further down and create another component. Now drag the bottom one onto the top one (from below, the code doesn't cater for from above yet) and drop it. It seems in the "up" drag handler my code as it currently stands applies the translation relative to where the component was created instead of relative to where it was dropped. I don't understand why :( Please help.

Open the console to see what I mean, I print some usefull info and object co-ordinates there.

Here is the JSFiddle: http://jsfiddle.net/n4rzul/trqrknqj/

And here is the entire drag function that is passed to the raphael svg object:

this.drag = function() {
            return {

                start:function () {
                    this.position = 0;
                    this.toFront();
                    this.lastdx ? this.odx += this.lastdx : this.odx = 0;
                    this.lastdy ? this.ody += this.lastdy : this.ody = 0;
                    this.animate({"fill-opacity": 0.5}, 500);
                    this.previousStroke = this.attr('stroke');
                }, 

                move:function (dx, dy) {
                    var draggedShape = this;
                    this.transform("t"+(dx+this.odx)+","+(dy+this.ody));
                    this.lastdx = dx;
                    this.lastdy = dy;
                },

                up: function(){
                    this.animate({"fill-opacity": 1}, 500);
                    var target;
                    for(i = 0; i < shapes.length; i++) {
                        if(shapes[i] != this) {
                            target = shapes[i];
                            console.log("found");
                            break;
                        }
                    }
                    console.log("targetXY: " + target.getBBox().x + ", " + target.getBBox().y);
                    console.log("draggedXY: " + this.getBBox().x + ", " + this.getBBox().y);
                    var tX = target.getBBox().x - this.getBBox().x;
                    var tY = target.getBBox().y - this.getBBox().y;
                    console.log("translate XY to get from dragged to target: " + tX + ", " + tY);
                    this.transform("t"+(tX)+","+(tY));

                    console.log("but it moves relative to its original XY. Why??: " + this.getBBox().x + ", " +this.getBBox().y);
                }

         };
        }

Upvotes: 1

Views: 221

Answers (1)

Ian
Ian

Reputation: 13842

The main issue with the original code, is that the objects dragged transform isn't taken into account when placing the final transform (on mouse up).

The simplest quick fix would probably be to do something like add 3 dots '...' to the transform, like

this.transform("...t"+(tX)+","+(tY +30));

This would mean translate taking into account previous transformation.

Here's a fiddle showing this running.

However, the general code feels like it could be simplified as well, like in the fiddle here.

The logic seems to be that the object is dragged, then both positions of objects calculated and dragged difference calculated. However, if you already know the object you want it to join, you know its transform, it doesn't actually matter where the dragged object is. It will always end up next to the target object, so no calculations really are needed. This may not quite be correct if this is just part of a larger problem where the original code needs to be in place.

I personally would stick to one path essentially cloned or identical (so all have the same starting x,y), however this is a bit of a personal taste thing, and depends on what other problems you may face later. It may be less optimal to have transforms, and flatten the transforms just into the path itself.

There's a few bits out there on transforms in general, which I would read up on first, and then once SVG transforms understood (if not already), then look towards Raphael transform strings.

The main Raphael transform string info can be found here

Upvotes: 1

Related Questions