Adding custom remove method to Raphael JS Graffle Connection
I'm using the custom connection method (Raphael.fn.connection) added in the example found at: raphaeljs.com/graffle.html
My example is here: http://jsfiddle.net/WwT2L/ (scroll in the display window to see the effect)
Essentially, I've linked the graffle connection to the bubble so it stays with it as it scales. I'm hoping that I can have the connection switch to the next bubble as the user scrolls past a certain point.
To do this, I was thinking I would remove the connection and add another one, but as the connection method is not a native Raphael element, it doesn't have the built in remove method, and I'm having trouble adding the remove method to the prototype.
I've found some开发者_运维百科 info about adding custom methods at this google group discussion and I've tried:
this.connections[0] = this.r.connection(this.bubbles[0], this.unitConnector, "#fff", "#fff").__proto__.
remove = function() {alert('working custom method');};
which seems to add a method to this instance of connection but I'm not sure what to have the method do and it seems like there should be a better way.
To recap... when we create a connection, we often use the following:
connections.push(
r.connection(r.getById(firstObjectId), r.getById(secondObjectId), '#fff')
);
What we're doing here is pushing (adding) a Raphael.connections
object into a connections[]
array, based on their Raphael
object id's
To add a method/function to Raphael
, one might use:
Raphael.fn.fnName = function (){ /* Your code here */ }
This creates a function in our Raphael
namespace for use with our Raphael
objects.
Below is the code i've created which does exactly what you require. I couldn't find a good resource out there for Raphael
, but will surely be creating one soon, as I have done a lot of development with it.
Raphael.fn.removeConnection = function (firstObjectId, secondObjectId) {
for (var i = 0; i < connections.length; i++) {
if (connections[i].from.id == firstObjectId) {
if (connections[i].to.id == secondObjectId) {
connections[i].line.remove();
connections.splice(i, 1);
}
}
else if (connections[i].from.id == secondObjectId) {
if (connections[i].to.id == firstObjectId) {
connections[i].line.remove();
connections.splice(i, 1);
}
}
}
};
Just like in the create connections, two id's are provided. We must find these ID's in the array of connections we've pushed each connection set to. If you only have one connection, there is no need for array traversing, though this is a case less encountered.
We have two possible scenarios here - excluding the case of having found no connection for simplicity sake. It either finds that:
- the connection objects
from.id
corresponds to the first provided paramenterfirstObjectId
. Then, theto
corresponds to the second provided paramentersecondObjectId
. - the connection objects
from.id
corresponds to the first provided paramentersecondObjectId
. Then, theto
corresponds to the second provided paramenterfirstObjectId
.
This method of checking covers all our bases, so no matter how the connection is interacted with (in my case the user clicks two objects to connect them, and delete their connection)
Once we've confirmed we have the two correct objects, we then remove the line from the DOM, using connections[i].line.remove();
as just removing the connection object from the array will leave it on the map.
Finally, we remove the specified connection object from the array, and the splice method leave us with an un-holy array (no holes in our array, that is ;) ) using connections.splice(i, 1);
Then,
this is what i am using to remove connections from connections array used with graffle example and so far i am having no issue with it. the question may be old but i stumbled upon on it searching the related solution, so when i had no luck i created mine and want to share with rest of the world.
//checks if the current object has any relation with any other object
//then remove all the to and from connections related to current object
for(var i =0 ; i<connections.length; i++){
if(connections[i].from.id == objectId || connections[i].to.id ==objectId ){
connections[i].line.remove();
}
}
//finds out which connections to remove from array and updates connections array
connections = $.grep(connections, function(el){
return el.line.paper != null;
})
the splice method was having issues with my case as if object has more than one connections (to, from) with multiple objects and every time i was using splice the main connections array length was changing as well as value of i was increasing, so i used jQuery grep method to update array based on removed lines. i hope this will help others too.
function removeShape(shape) {
//CONNECTIONS is my global structure.
var connections = [];
while (CONNECTIONS.length) {
var connection = CONNECTIONS.pop();
if (connection.from.id == shape.id || connection.to.id == shape.id)
connection.line.remove();
else
connections.push(connection);
}
shape.remove();
CONNECTIONS = connections;
}
精彩评论