Draw SVG image on paths but as big as needed - javascript

So I would like to show an image on a path. The pathes are created via topojson coordinates. The points are on the right position on my map. So the next thing is to show a SVG image on that point.
I tried that with appending svg:image, but no chance. I also tried to bring it into the path with the same result. I nowhere can see that image. Here an example with an PNG image. Because at least that should work to exclude SVG issues:
var featureCollection = topojson.feature(currentMap, currentMap.objects.points);
svgmap.append("path")
.attr("id", "points")
.selectAll("path")
.data(featureCollection.features)
.enter().append("path")
.attr("d", path);
svgmap.append("svg:image")
.attr("class","svgimage")
.attr("xlink:href", "pics/point.jpg" )
.attr("x", -20)
.attr("y", -20)
.attr("width", 13)
.attr("height", 13);
Edit
svgimage.append("pattern")
.attr("id","p1")
.attr("patternUnits","userSpaceOnUse")
.attr("width","32")
.attr("height","32")
.append("image")
.attr("xlink:href", "pics/point.jpg" )
.attr("width", 10)
.attr("height", 10);
svgmap.append("g")
.attr("id", "points")
.selectAll("path")
.data(featureCollection.features)
.enter().append("path")
.attr("d", path)
.attr("fill", "url(#p1)");
But still not working.
Edit2
I mentioned that it is an issue with the size. So I now played a bit with the sizes and there I can see some more, but most of them are not fully imaged. Just some pieces of the cirle somehow. Strange thing. I keep on testing:
svgimage.append("pattern")
.attr("id","p1")
.attr("patternUnits","userSpaceOnUse")
.attr("width","10")
.attr("height","10")
.append("image")
.attr("xlink:href", "pics/point.jpg" )
.attr("width", 15)
.attr("height", 15);
Here a picture of the current result (jpg): http://i.imgur.com/T58DA1j.png not yet perfect.
This is when I increase the pointRadius (this is now a SVG): http://i.imgur.com/Z7nZUWk.png

The solution is pretty easy. The size of the picture was just not correctly set. Also the userSpaceOnUse needs to be deleted and if needed you can set the creation position with x and y:
svgimage.append("pattern")
.attr("id","p1")
.attr("width","10")
.attr("height","10")
.append("image")
.attr("xlink:href", "pics/point.jpg" )
.attr("width", 5)
.attr("height", 5)
.attr("x", 1)
.attr("y", 2);
and in the second part it is important to set the pointRadius. You can set it directly on the path or in the definition. If you want to use different sizes later on it makes more sense to set it in the path directly:
.attr("d", path.pointRadius(3.5))

Related

How to do stroke-opacity:0 with d3

Here is my code. My target - do intervals between slices in pie chart.
chart.svg.selectAll('path')
.style('stroke-opacity','0.0')
.style('stroke-width','10');
I think if stroke opacity will be 0 on piechart slices on web page it will be similar to interval between slices.
Problem: if stroke opacity equals to zero that doesn't work. If equals to number from 0.1 to 1.0 - all works. But I have another color from background.
Please give a hand to beginner! Thanks for attention and have a nice day.
I believe the problem comes from the misconception that, when you set stroke-opacity to 0, the stroke will be transparent and reveal the background colour, and the fill of the element will end at the internal limits of the stroke. But, in fact, if you set the stroke-opacity to 0, you'll reveal the fill of the element (and the background colour, once the stroke goes inwards and outwards in the default stroke-alignment).
Look, for instance, at this example:
var svg = d3.select("body")
.append("svg")
.attr("width", 300)
.attr("height", 300);
var color = d3.scale.category10();
data = [10, 20];
var rects = svg.selectAll(".rect")
.data(data)
.enter()
.append("rect");
rects.attr("x", function(d){ return d*10})
.attr("y", 0)
.attr("width", 100)
.attr("height", 80)
.attr("fill", function(d){ return color(d)})
.attr("stroke-width", 10)
.attr("stroke", "white")
.attr("stroke-opacity", 0);
var rects2 = svg.selectAll(".rect2")
.data(data)
.enter()
.append("rect");
rects2.attr("x", function(d){ return d*10})
.attr("y", 100)
.attr("width", 100)
.attr("height", 80)
.attr("fill", function(d){ return color(d)})
.attr("stroke-width", 10)
.attr("stroke", "white");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
Both the pairs of rectangles are absolutely equal:
rects.attr("x", function(d){ return d*10})
.attr("y", 0)
.attr("width", 100)
.attr("height", 80)
.attr("fill", function(d){ return color(d)})
.attr("stroke-width", 10)
.attr("stroke", "white")
The only difference is that, in the upper pair, I add:
.attr("stroke-opacity", 0);
And that is the same of having no stroke.
You can see that, independent of the stroke alignment, the area and the size of the element is the same. Check the default stroke:
The rect element, outlined by a black line, remains the same.
To finish, I just found this fiddle (I don't know who's the author), and I set the stroke to white and stroke-width to 10: this is what you want, imitating a real padding. But you'll not get this result setting the stroke opacity to 0: https://jsfiddle.net/j1769sx2/

D3 generated rectangle "click" function not executing

Inside of my d3 code, I generate a rectangle like this:
svg.selectAll("g")
.append("rect")
.attr("width", 30)
.attr("height", 30)
.attr("class", "close-box initial-hidden")
.attr("x", 500)
.attr("y", 110)
.on("click", function() {
$('.initial-hidden').hide();
})
.append("text")
.text("x")
I am using click events on many of my other svg elements and they are working fine, but I can't get the click event on the rectangle to work at all. Am I missing something about SVG rectangle?

D3 chart like the US government analytics

I want to modify charts I have used in D3 to be like those on the US government analytics. I am unsure where to start. The JSfiddle below is where I am starting from.
Do I have to modify the chart to a stacked bar chart, a bullet chart or simply create the recs and add more space between them and position labels above the charts?
Has anyone done anything similar with D3?
My starting point: http://jsfiddle.net/Monduiz/drhdtsaq/
The Y axis, rects and labels:
[...]
var y = d3.scale.ordinal()
.domain(["Earnings", "Industry", "Housing", "Jobs"])
.rangeRoundBands([0, height], 0.2);
[...]
bar.append("rect")
.attr("width", 0)
.attr("height", barHeight - 1)
.attr("fill", "#9D489A")
.attr("width", function(d){return x(d.value);});
bar.append("text")
.attr("class", "text")
.attr("x", function(d) { return x(d.value) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d.value; })
.attr("fill", "white")
.attr("font-family", "sans-serif")
.attr("font-size", "14px")
.attr("text-anchor", "end");
This is what I want to do:
EDIT
I have made some progress. Updated fiddle: http://jsfiddle.net/Monduiz/drhdtsaq/33/
Now I need to find how to move the ordinal categories between the bars.
Well, I got close enough after some attempts. I can polish things up with CSS.
updated fiddle: http://jsfiddle.net/Monduiz/drhdtsaq/66/
Basically, the solution is to create another set of rectangles called first using a second set of data to full value of the scale used. Then its just a matter of adjusting the size of the bars and positioning the labels.
bar2.append("rect")
.attr("height", y.rangeBand()-15)
.attr("fill", "#EDEDED")
.attr("width", function(d){return x(d);});
bar.append("rect")
.attr("height", y.rangeBand()-15)
.attr("fill", "#FFB340")
.attr("width", function(d){return x(d.value);});

Very Simple D3: How to Draw an Arc?

It would be nice to learn D3. After reading many examples, I think I understand it. My first project is to make a color wheel, without transitions for simplicity. But it appears even that is not simple enough for my first project! For project zero, I am trying to get something to show on the screen. Hopefully something I wrote (and dear read has fixed), and not an example.
What did I do wrong? http://jsfiddle.net/aGdMX/1/
var arc = d3.svg.arc()
.innerRadius(40)
.outerRadius(100)
.startAngle(0)
.endAngle(1)
;
var chart = d3.select("body").append("svg:svg")
.attr("class", "chart")
.attr("width", 420)
.attr("height", 420).append("svg:g")
.attr("transform", "translate(200,200)")
;
chart.selectAll("path")
.data(data)
.enter().append("svg:path")
.attr("fill", function(d, i){
return d3.rgb("black");
})
.attr("d", arc)
;
Thank you
Your example here doesn't have any data defined. If you just want to draw the svg statically, skip the selectAll() and data() bindings:
chart
.append("svg:path")
.attr("fill", function(d, i){
return d3.rgb("black");
})
.attr("d", arc)
;
Or define some data and use that to drive the drawing:
http://jsfiddle.net/findango/aGdMX/2/
(plus .attr("fill"... should be .style("fill"...)

d3 enter/append/exit/remove sequence only appending

A set of rectangles is drawn initially with the following enter/append/exit/remove sequence, no problem. When I pass different data (meant to replace the existing data entirely) the new rectangles are drawn on top of the existing rectangles.
I am selecting "lgnds" instead of rect, because I have drawn other rectangles that I don't wish to disturb.
var svg = d3.select("#graph").append("svg")
elements = svg
.selectAll("lgnds")
.data(data, function(d){return d;});
elements
.enter()
.append("rect")
.attr("width", 15)
.attr("height", rectHeight)
.attr("x", 5)
.attr("y", function (d,i){return ((i*rectHeight)+(gap*(i+1)));})
.style("fill", function(d){ return d.color;});
elements
.exit()
.remove();

Categories