SVG Snap select a group by it's ID - javascript

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);

Related

Dynamic SVG creation using JavaScript - adding extra spacing to textContent with IE11 Support [duplicate]

To preserve spaces in a textelement of svg, one should use 'xml:space="preserve"' as an attribute of the text (jsfiddle). However, it isn't working. What am I doing wrong?
// init snap
var svgElement=document.getElementById("mainSvgId");
var s = Snap(svgElement).attr({height: 300, width: 300});
// greate group with rectanle
var parentGroup=s.g().attr({id: "parent"});
var rect1 = s.rect(0, 0, 200, 200).attr({fill: "#bada55"});
parentGroup.add(rect1);
// add text with preserve attribute
var text = s.text(0, 20, " text1 text2");
text.node.setAttribute("xml:space", "preserve");
parentGroup.add(text);
You're almost there. You need to properly create the attribute in the xml namespace for which you need setAttributeNS rather than setAttribute
text.node.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve");

how to update renderer.text() in highcharts after a graph has been drawn?

In my application, which uses highcharts lib, i use svg draw function for my chart load/redraw events.
I set all my chart data to equal value so that all the stacks will have same height, while the real data is kept in temp array that is drawn as svg in this way:
var dataFormat = getLabelByStatus(curCount, yearsObj[i].data[0]);
var css = (point.color == USERS_YEARS_COLOR) ? highchartAttr().dataLabelsBoldStyle : highchartAttr().dataLabelsStyle;
// draw text
var text = renderer.text(dataFormat, -9999, -5).add(point.label);
text.attr({
x: (lineLength - text.getBBox().width) / 3
}).css(css)
This works great but now i want to change this data in a callback function.
I still can access the renderer object, but neither i can find my old printed data to edit it, nor i can find a suitable edit function.
You can save your custom text element in a variable or in the chart like this
chart.customText = chart.renderer.text('Series 1', 140, 140)
.attr({
rotation: -25
})
.css({
color: '#4572A7',
fontSize: '16px'
})
.add();
Then you can access it and use attr({text}) to change its text
chart.customText.attr({
text: Math.random()
})
example: http://jsfiddle.net/28nwb7pj/
Actually i found a bypass solution for this.
In the draw function, i added an id attribute so later on it is easy to get it with jquery selector and edit it with .text().
text.attr({
x: (lineLength - text.getBBox().width) / 3,
id: 'text_' + i // id added to make it modifiable
}).css(css)
change text example in callback function:
$('#text_2').children().text(435)

Raphael: Adding Multiple Paths on Array Items

I'm using Raphael. I'm trying to have two separate svg paths on my array options (wheel.people and wheel.leadEntrepreneur) so that I can style them differently. So in essence I want to add another path alongside the one that exists. One is for an svg shape and the other will be for an svg icon. I have managed to construct the shapes using the code below but now need to overlay the icons on top of the shapes. So How do I create an additional path for the icons and apply different styling?
var R = Raphael("paper", 400, 400);
var attr = {
fill: "#333",
stroke: "#fff",
"stroke-width": 1,
"stroke-linejoin": "round",
cursor: "pointer"
};
var wheel = {};
wheel.people = R.path("M205.1,84.2c-0.8-0.4-1.6-0.7-2.5-1.1c-0.1-0.1-0.3-0.1-0.5-0.2c-5.4-2.2-11-3.9-16.6-5 c-0.2,0-0.3-0.1-0.5-0.1c-5.7-1.1-11.5-1.7-17.3-1.7h-0.5c-4.7,0-9.4,0.4-14,1.1l-4.7-6.5l-0.8-1.1v0l-40.8-57 c9.1-3.5,18.4-6.2,27.9-8.1c0.2-0.1,0.3-0.1,0.5-0.1c10.5-2.1,21.2-3.1,31.9-3.1h0.5c10.7,0,21.4,1.1,31.9,3.1 c0.2,0,0.4,0.1,0.5,0.1c0.3,0.1,0.7,0.1,1,0.2l3.6,72v0l0.1,1.2v0L205.1,84.2z").attr(attr);
wheel.leadEntrepreneur = R.path("M285,50l-0.3,0.6l-35.6,62l-0.6,1l-3.3,5.8c-0.5-0.8-1-1.7-1.6-2.5c-0.1-0.1-0.2-0.3-0.3-0.4 c-3.2-4.7-6.9-9.2-11-13.4c0,0-0.1-0.1-0.1-0.1c-0.1-0.1-0.2-0.2-0.3-0.3c-4.2-4.1-8.7-7.8-13.4-11c-0.1-0.1-0.3-0.2-0.4-0.3 c-4.1-2.7-8.5-5.1-12.9-7.1l-0.3-6.2v0l-0.1-1.2v0l-3.6-72c10.1,2.1,20.1,5.1,29.7,9.1c0.2,0.1,0.3,0.1,0.5,0.2 c9.8,4.1,19.3,9.1,28.3,15.1c0.1,0.1,0.3,0.2,0.4,0.3c8.7,5.9,17,12.7,24.8,20.4C284.8,49.8,284.9,49.9,285,50L285,50z").attr(attr);

How to add Kineticjs shape Circle on Kineticjs Text onclick?

I wanna be able to click on var textradie text "Show radie" and then add two circles kinGroups[index].add(circle); and kinGroups[index].add(circlered);. Im adding the two circles on my Group kinGroups[index].
All my jsonObjects[i].radie == false, so I dont know why only one object in kinGroups[index] have two circles. All my three objects should have two circles, but only one object have two circles.
var textradius = new Kinetic.Text({
x: 1000,
y: 500,
fontFamily: 'Calibri',
fontSize: 18,
text: 'Show radius',
fill: 'black'
});
kinGroups[index].add(textradie);
textradius.on('click', function() {
for(i=0; i<jsonObjects.length; i++) {
console.log("testing");
if(kinGroups[index].getName() == jsonObjects[i].name) {
if(jsonObjects[i].radie == false) {
kinGroups[index].add(circle);
kinGroups[index].add(circlered);
}
}
}
});
You have to add new circle and circlered objects to the groups.
You could use the clone() method to do this:
kinGroups[index].add(circle.clone());
kinGroups[index].add(circlered.clone());
[ Addition: example code ]
Demo: http://jsfiddle.net/m1erickson/4uAdc/
Assume you have:
A group,
A text element in that group. The text element is named "One".
Other elements in that group. Some of the other elements are named "One".
If you click on the text named "One", here's how to draw a double-circle around the other elements that are also named "One".
// define a circle that can be cloned
var circle=new Kinetic.Circle({
stroke: 'black',
strokeWidth: 2,
});
// get all children with the same name as the clicked text
var children=group.find("."+text.getName());
// iterate those children and add cloned circles
for(var i=0;i<children.length;i++){
// get the x,y of the other elements with the same name as the text
var child=children[i];
var x=child.getX();
var y=child.getY();
// add cloned circles around those other elements
var red =circle.clone({x:x,y:y,radius:10,stroke:"red"});
var blue=circle.clone({x:x,y:y,radius:15,stroke:"blue"});
text.group.add(red);
text.group.add(blue);
}
layer.draw();

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

Categories

Resources