Selecting a node in Raphael/JavaScript - javascript

The following code mostly works (thanks to a good answer a couple of days ago!) all except for the last little bit:
things.square[1].node.setAttribute("id","clicker");
$("#clicker").click(function(){
$("#canvas_things1").fadeOut();
$("#canvas_things2").fadeIn();
});
I think the problem is this line:
things.square[1].node.setAttribute("id","clicker");
I would have thought that square[1].node would work, but it seems not. Can someone spot what's wrong?
<script type="text/javascript" charset="utf-8">
$("document").ready(function() {
var RM = Raphael("canvas", 1000, 500);
var attr = { // for the visible shapes
fill: "#bbb", "fill-opacity": 1,
stroke: "#222", "stroke-width": 0.3,
};
var attr2 = { // for the invisible hovering areas
fill: "green", "fill-opacity": 0.0,
stroke: "red", "stroke-width": 0,
};
var things = {};
/* Square */ things.square = [ RM.path("m 154.21525,71.431259 74.32805,0 0,70.496711 -74.32805,0 0,-70.496711 z").attr(attr),
RM.path("m 271.25132,77.933263 58.07304,0 0,56.409037 -58.07304,0 0,-56.409037 z").attr(attr2) ];
/* Triangle */ things.triangle = [ RM.path("m 154.02932,222.44063 36.78089,-58.23641 34.48208,58.2364 -71.26297,1e-5").attr(attr),
RM.path("m 271.25132,165.71032 58.07304,0 0,56.40903 -58.07304,0 0,-56.40903 z").attr(attr2) ];
for (var shape in things) {
shape[0].color = Raphael.getColor();
(function (shape, sh) {
shape[1][0].onmouseover = function () {
shape[0].animate({fill:shape[0].color, stroke:"#ccc"}, 500);
document.getElementById(sh)[0].style.display = "block";
shape[0].toFront(); R.safari();
};
shape[1][0].onmouseout = function () {
shape[0].animate({fill:"#bbb", stroke:"#222"}, 500);
document.getElementById(sh)[0].style.display = "none";
shape[0].toFront(); R.safari();
};
})(things[sh], sh);
} // end for every member of things
things.square[1].node.setAttribute("id","clicker");
$("#clicker").click(function(){
$("#canvas_things1").fadeOut();
$("#canvas_things2").fadeIn();
});
}); // end the document ready function
</script>

The id attribute is set properly.
Try it out with this jQuery (click on the 1st red square)
Notice, that I had to rip out your for loop. This is because the self executing anonymous function was causing a runtime error due to being called with undefined variables.
sh is never defined, but it is used here:
})(things[sh], sh); // sh is never defined!
} // end for every member of things
I would have replaced the for loop but I don't understand what you're trying to do.
At any rate, I would suggest using the Raphael custom event handler .hover().
PS: Watch your unnecessary comas (you have 4):
stroke: "#222", "stroke-width": 0.3, // <== Trailing comma
};

I think it's because things.square doesn't map to a single element in your SVG when you have multiple paths. There's two approaches that should work:
Loop through each of the path elements in things.square and apply the click function to each of them (won't be able to use the id attribute then).
Use a group add-on to put all your paths inside a <g> element in the SVG, then apply your function to that instead.

Related

SVG Snap select a group by it's ID

I'm trying to get an SVG Snap element by it's id. First I create a canvas:
var s = Snap("#svgout"), //creates the canvas
Then I cerate a group:
var rect = s.rect(posx, posy, 40, 40, 6).attr({
fill: "none",
stroke: "#F44336",
strokeWidth: 3,
});
var group = s.group(rect).attr({
cursor: "move",
});
and next I get the id of the group that is defaulted by SVG Snap
var currGroupId = group.id;
Now, when I try to reference my group later in my code and get it by it's id,
s.select(currGroupId);
I get null. How do I properly select an element by it's id?
select will use a cssSelector, as in container.queryAll.
So I don't think Snap sets an id as an svg attribute (do correct me if I'm wrong). Which means if you want to use select, you may have to manually set it.
Also I susect s.select(id) wouldn't work, I think it would have to be s.select('#'.id) but I may be wrong. If you can get a fiddle up, it will be easier to test.
SnapSVG doesn't automatically set the ID attribute of the group. Instead it adds a field to the object itself. One way of getting around this limitation is to do the following.
var s = Snap("#svgout");
var rect = s.rect(posx, posy, 40, 40, 6).attr({
fill: "none",
stroke: "#F44336",
strokeWidth: 3,
});
var group = s.group(rect).attr({
cursor: "move",
});
Explicitly set the ID.
group.attr({
id: group.id
});
var currGroupId = group.id;
select uses CSS selectors. So we must add a '#' to the start of the ID.
s.select("#" + currGroupId);
Note: This method has been tested by me using SnapSVG V0.4.1
If this does not work and you are using jQuery. try:
$("#"+currGroupId);

Reusing SVG.js code for various SVG's

I'm getting to grips with SVG.js
I have a pattern effect that I've created and would like to use in a number of SVG's.
I can create it in one SVG with the following code...
$( document ).ready(function() {
var draw = SVG('geo').size(1200, 1700);
// 100 lines of js creating geometric pattern, effectively this...
var rect = draw.polygon(coordinates).fill('#fff').stroke({ width: 1, color:'#fff'}).opacity(0)
});
This creates an SVG with ID geo. But I'd like to use this code again to generate various SVG's, ideally with different options (colour etc).
SVG('geo') refers to a particular SVG, how do I make it so I can apply this to any SVG I want on the page?
Hope that made sense
You can define a function that does this repeatedly. Something like the following:
function create_svg(dom_id, width, height, coord) {
var draw = SVG(dom_id).size(width, height);
var rect = draw.polygon(coord)
.fill('#fff')
.stroke({
width: 1,
color: '#fff'
})
.opacity(0);
}
$(function() {
create_svg('geo', 1200, 1700, coordinates);
create_svg('geo2', 1000, 1500, other_coordinates);
)};
If you need to use the created SVGs further, later on in the code, you could make the create_svg function return the created SVG object to a variable in your document.ready function.

How to I scale the Raphael map in Rob Flaherty's US map example?

I'm trying to implement this awesome map, but I can't figure out how to scale it. Changing the size of the container div or the height/width values just crops the underlying map. I think I need paper.scaleAll(.5) in here somewhere, but can't figure it out. Thanks!
<script>
window.onload = function () {
var R = Raphael("container", 1000, 900),
attr = {
"fill": "#d3d3d3",
"stroke": "#fff",
"stroke-opacity": "1",
"stroke-linejoin": "round",
"stroke-miterlimit": "4",
"stroke-width": "0.75",
"stroke-dasharray": "none"
},
usRaphael = {};
//Draw Map and store Raphael paths
for (var state in usMap) {
usRaphael[state] = R.path(usMap[state]).attr(attr);
}
//Do Work on Map
for (var state in usRaphael) {
usRaphael[state].color = Raphael.getColor();
(function (st, state) {
st[0].style.cursor = "pointer";
st[0].onmouseover = function () {
st.animate({fill: st.color}, 500);
st.toFront();
R.safari();
};
st[0].onmouseout = function () {
st.animate({fill: "#d3d3d3"}, 500);
st.toFront();
R.safari();
};
})(usRaphael[state], state);
}
};
</script>
The other answer is almost correct, but you have to set the anchor point of the scale command to 0,0 so that each state is scaled from the same point:
element.transform("s2,2 0,0");
While you're at it, I'd make an R.set() element and add each state to it, so that you can apply the scale just to the states in the event that you add other objects, like a legend, that you do not want to scale:
usRaphael = {},
states = R.set();
//Draw Map and store Raphael paths
for (var state in usMap) {
usRaphael[state] = R.path(usMap[state]).attr(attr);
states.push(usRaphael[state]);
}
Then at the end:
states.transform("s2,2 0,0");
jsFiddle
After you draw the map (outside of your for loops) try the following:
R.forEach(function(element) {
element.transform("s2");
});
I'm not sure what version of Raphael you are using, but my code is assuming the latest. What this does is it iterates over every path on the paper and sets the transform to "scale 2". This will scale all of the paths by 2.

Click Event to Animate Raphael Path Broken in IE

I have created a Raphael document and am storing the locations like so:
var R = Raphael("paper", 600, 500);
var attr = {
fill: "#fff",
stroke: "#fff",
"stroke-width": 1,
"stroke-linejoin": "round"
};
-- get coords from db assigned to object 'ausData' and create a object 'aus' --
$.each(ausData,function(i,obj) {
attr.fill = myData[i].color;
aus[i] = R.path(obj).attr(attr);
aus[i].id = myData[i].id;
mapIdObj[stateData[i].id] = R.getById(stateData[i].id);//aus[i].id;
});
so the path object is stored in the object mapIdObj
I am then attempting to alter the path object by clicking on a link. in the .success of the jQuery.post.success I am iterating through all the elements, and appending an anchor tag to the page, and on jQuery.post.complete I am attempting to bind a click:
$('#superHappyDiv').append('<a id="button'+st.id+'" class="superButton" name="button'+st.id+'" ref="'+st.id+'" class="" href="javascript:;" title="" target="">x</a>');
$('.superButton').live('click onmousedown',function() {
if (window.console) console.log($(this).attr('ref'));
var thisPath = mapIdObj[$(this).attr('ref')];
thisPath.animate({ 'transform': 's2', opacity: .9 }, 300, "<>");
});
Other answers have pointed to this as working, and it does, but not in IE 7, and 8 at least!
Is there a more efficient way to get this working, or working at all in IE?!
Cheers, Bo

Drag and drop SVGs with Raphael JS

Looking for some advice (example would be great) on dragging and dropping SVGs using RaphaelJS.
I have found how to drag an object created withint Raphael
window.onload = function() {
var R = Raphael("canvas", 500, 500);
var c = R.circle(100, 100, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5
});
var start = function () {
...
},
move = function (dx, dy) {
...
},
up = function () {
...
};
c.drag(move, start, up);
};​
But I need to be able to adapt this to work with a seperate SVG file(s) so for example
myPage.html has myImage.svg, I need to be able to drag myImage.svg around the 'canvas'.
I'm thinking something like
var c = R.SOMEMETHOD('myImage.svg');
...
c.drag(move, start, up);
For example.
Is there a way to do this and if so, an example would be brilliant!
This magic method doesn't exist in RaphaelJS. But there is a way to accomplish this. You can have a look at the raphael-svg-import project on GitHub which works well for basic svgs
Then, you'll want to use a grouping facility as you cannot use the Set functionnality of RaphaelJS
1 - import your SVG
2 - As you import, mark the elements so they belong to the same group
Enjoy !!

Categories

Resources