How can I make a palette behaviour (elements being dragged and dropped from a 'palette' to a 'canvas') in raphaelJS?
-
1I would like to see someone comment why the -1... – talabes Nov 05 '12 at 23:16
-
i suppose advertising your blog and disguising it as posts is not very welcomed here.. – Eliran Malka Jan 21 '13 at 09:25
-
Answering my own question is a good practice. The post is too long to copy/paste it here. Is just another way of sharing knowledge... – talabes Jan 21 '13 at 19:50
-
i didn't mention it. answering your own question is acceptable indeed. however it is not very helpful to simply post a link to your blog as an answer (what if your blog is down for some reason?). encompass the highlights of the solution in the answer, to create a [Short, Self Contained, Correct (Compilable), Example](http://sscce.org/). – Eliran Malka Jan 21 '13 at 21:04
-
There, better solution right? You were right about the link or the existence of the blog. I couldn't leave the question with a -1 so easily, I hope this question now gets more +1 now :) – talabes Jan 22 '13 at 13:11
1 Answers
You'll have to add to every palette element this startFunction:
//DragFunctions is the object that has all the 3 d&d methods, clearer in the complete file
paletteStart: function () {
// keep the relative coords at the start of the drag
this.ox = 0;
this.oy = 0;
// as we are dragging the palette element, we clone it to leave one in his place.
var newPaletteObj = this.clone();
//we give the new palette element the behaviour of a palette element
DragFunctions.addDragAndDropCapabilityToPaletteOption(newPaletteObj);
//nice animation
this.animate({
"opacity": 0.5
}, 500);
}
Now we need the function while the element is being dragged:
move: function (dx, dy) {
// calculate translation coords
var new_x = dx - this.ox;
var new_y = dy - this.oy;
// transforming coordinates
this.transform('...T' + new_x + ',' + new_y);
// save the new values for future drags
this.ox = dx;
this.oy = dy;
}
And finally, the function executed at finish dropping:
paletteUp: function () {
if (!DragFunctions.isInsideCanvas(this)) {
this.remove();
//notify the user as you want!
} else {
//Giving the new D&D behaviour
this.undrag();
//give the element the new d&d functionality!
this.animate({
"opacity": 1
}, 500);
}
}
2 things to comment here, when the element is dropped, you will have to remove the palette behaviour and give it another one (a plain d&d functionality), if not, it will continue cloning elements all around. Here I give you some nice behaviour to give them:
start: function () {
// keep the relative coords at the start of the drag
this.ox = 0;
this.oy = 0;
// animate attributes to a "being dragged" state
this.animate({
"opacity": 0.5
}, 500);
},
//same move function
up: function () {
if (!DragFunctions.isInsideCanvas(this)) {
this.animate({
transform: '...T' + (-this.ox) + ',' + (-this.oy)
}, 1000, "bounce");
}
this.animate({
"opacity": 1
}, 500);
},
//and the method that gives the behaviour
addDragAndDropCapabilityToSet: function (compSet) {
compSet.drag(this.move, this.start, this.up, compSet, compSet, compSet);
}
And as you may also see, we have a validator that sees if the element is inside the canvas, it is a very useful function, here:
isInsideCanvas: function (obj) {
var canvasBBox = //get your 'canvas'
var objectBBox = obj.getBBox();
var objectPartiallyOutside = !Raphael.isPointInsideBBox(canvasBBox, objectBBox.x, objectBBox.y) || !Raphael.isPointInsideBBox(canvasBBox, objectBBox.x, objectBBox.y2) || !Raphael.isPointInsideBBox(canvasBBox, objectBBox.x2, objectBBox.y) || !Raphael.isPointInsideBBox(canvasBBox, objectBBox.x2, objectBBox.y2);
return !(objectPartiallyOutside);
} Finally,
the place to call to give the element all this behaviour:
//this works for elements and sets
addDragAndDropCapabilityToPaletteOption: function (compSet) {
compSet.drag(this.move, this.paletteStart, this.paletteUp, compSet, compSet, compSet);
}
A demo of this is in a website I created to play with raphael, called comoformamos.com The hole code is in a github gist or hosted on github so if you want to get a little deeper in the code feel free to do it.
Explained more beautifully at this blog entry: devhike, I'm the author.

- 15,821
- 6
- 77
- 100

- 5,344
- 2
- 22
- 27