I have text labels that I would like to rotate.
in_years.selectAll(".xlabel")
.data(xTickLabels)
.enter()
.append("text")
.attr("class","xlabel")
.attr("text-anchor", "end")
//.attr("transform", "translate(0,0) rotate(-45)")
.attr("font-size", "14px")
.attr("x", (d,i) => xScale(xRange[i]))
.attr("y", (d,i) => height+15)
.text(function(d) { console.log(d);return d})
;
Wit "transform" line commented I obtain graph 1. Uncommenting the line I obtain graph 2 which does not make sense to me.
Any hint on why this happen and how to solve it? I am using d3 v3 for this
Why the rotation effect not as your expectation is due to the css property of rotate(). link
According to the rotate function definition in MDN doc:
''The axis of rotation passes through an origin''
So you have to translate each text element's (x,y) in order to let rotation axis is related to its site in the graphic.
// this code, which each text will rotate according to (0,0)
svg.selectAll('text.norotation')
.data(data)
.enter()
.append('text')
.text((d)=>d)
.classed('norotation', true)
.attr('fill', 'black')
.attr('x', (d,i)=> xScale(i))
.attr('y', 200)
Modified One
//each text element will rotate according to its position
svg.selectAll('text.rotation')
.data(data)
.enter()
.append('text')
.text((d)=>d)
.classed('rotation', true)
.attr('fill', 'black')
.attr('transform', (d,i)=>{
return 'translate( '+xScale(i)+' , '+220+'),'+ 'rotate(45)';})
.attr('x', 0)
.attr('y', 0)
Demo on Observalbe:https://beta.observablehq.com/#weitinglin/d3-rotating-text-labels
Related
I wanted to create a circular crop an image to use in conjunction with a svg circle, and decided on filling the svg circle with a pattern. I have it working for the single case:
defs.append("svg:pattern")
.attr("id", "story1")
.attr("width", 200)
.attr("height", 100)
.attr("patternUnits", "userSpaceOnUse")
.append("svg:image")
.attr("xlink:href", 'ml-image4.png')
.attr("width", 200)
.attr("height", 100)
.attr('x',0)
.attr('y',0);
var circle1 = svg.append("circle")
.attr("cx", 100)
.attr("cy", 50)
.attr("r", 40)
.style("fill", "#fff")
.style("fill", "url(#story1)")
.style('stroke','#000')
.style('stroke-width', 5);
Then I got all gung-ho and tried to adapt for a programmatic implementation, but it didn't pan out so well. I'm hoping there is a way to do it, because my end goal is to have an application that uses many pictures as patterns. It will be like a little gallery where each svg circle is spaced out across the page using .attr('x', function(d,i) { return 100+i*200})) and each circle referencing a different pattern. The pattern id is a data member, so I was trying to do this: .style('fill',function(d) {return "url(#"+d.id+")"; }). I'm not exactly sure why it didn't work; to my eyes it seems functional-ish. I did get the error:
Uncaught DOMException: Failed to execute 'querySelectorAll' on
'Element': 'svg:pattern' is not a valid selector.
Here is my adaptation for programmatic def patterns and a quick look at my data:
var data = [
{'id':'story1', 'Title':'Title1', 'Date':'03/10/2017','Icon':'Icon1.png', 'Link':'www.link1.com/'},
{'id':'story2', 'Title':'Title2', 'Date':'12/15/2017','Icon':'Icon2.png', 'Link':'www.link2.com/'}
];
var defs = svg.append('svg:defs');
defs.selectAll(null)
.data(data)
.enter()
.append('svg:pattern')
.attr('id',function(d) {return d.id; })
.attr('width', 200)
.attr('height', 100)
.attr('patternUnits', 'userSpaceOnUse')
.append('svg:image')
.attr('xlink:href', function(d) {return d.Icon})
.attr('width', 200)
.attr('height', 100)
.attr('x',0)
.attr('y',0);
svg.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d,i) {return 100+i*200})
.attr('cy', 50)
.attr('r',40)
.style('fill',function(d) {return "url(#"+d.id+")"; })
.style('stroke','#000')
.style('stroke-width',3);
Question
Judging by the error, my adaptation seems to be flawed. What can I tweak to get programmatic patterns for svg circles here? In my humble opinion, my approach isn't all that different from the simple case at the very beginning of the post (1 pattern 1 circle), all I was trying to do was scale it up so I can use d3.selectAll() using my data.
I'm trying to draw a graph with d3 inserting images in node circles and drawing arrows on the target node. Nodes with images and edges are properly drawn, but the arrows are missing, although the marker is defined and used in links.
When I change the way nodes are attached to "g", arrows are drawn, but circle and images disappear. Can't figure out where the mistake stays.
D3 code is the following:
// define marker for the arrow
svg.append("defs").selectAll("marker")
.data(["arrow"])
.enter().append("marker")
.attr("id", function(d) { return d; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -1.5)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,-5L10,0L0,5");
// add links
var link = svg.append("g").selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
.attr("marker-end", function(d) { return "url(#arrow)"; })
.style("stroke", "#FF3300");
// add nodes
var node = svg.append("g").selectAll(".node")
.data(nodes)
.enter().append("svg:g")
.attr("class", "node")
.on("dblclick", dblclick)
.call(force.drag);
node.append("svg:circle")
.attr("r", 50)
.style("fill", "#FFEBE6")
.style("stroke", "#FF3300")
.style("stroke-width", 3);
// add images - from base64
node.append("image")
.attr("xlink:href", function(d){
if (d.imgB64) {
return 'data:image/png;base64, ' + d.imgB64 ;
}
})
.attr("x", -40)
.attr("y", -40)
.attr("width", 80)
.attr("height", 80)
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0.0);
})
Nothing wrong with the code, arrows seems to be hidden/overlaid by the node circle and image. Changing the refX and refY attributes to 65 and 0 respectively addresses the issue.
Is it possible to add a background fill to a rect element? I am using rect elements to create a bar graph. Each rect element has a width and fill set. I want to fill the remaining width with a color.
See here: http://codepen.io/jesouhaite08/pen/fhvzA
Thanks!
For best flexibility I would use other rectangles to draw the background for your bars, check the forked example: http://codepen.io/anon/pen/JnlAE
// Bars
svg_fun.selectAll('rect.background')
.data(dataset)
.enter()
.append('rect')
.classed('background', true)
.attr('y', function(d, i) {return i * h_line; })
.attr('x', 0)
.attr('height', 20)
.attr('width', function(d) {return scale_x(max_x);} )
.attr('fill', 'red')
svg_fun.selectAll('rect.bar')
.data(dataset)
.enter()
.append('rect')
.classed('bar', true)
.attr('y', function(d, i) {return i * h_line; })
.attr('x', 0)
.attr('height', 20)
.attr('width', function(d) {return scale_x(d);} )
.attr('fill', 'teal')
I am new to this kind of chord visualization. I am working on a sample http://bl.ocks.org/mbostock/4062006:
I would like to add "black", "blonde","brown","red" as labels in the respective chord. How is this possible.
I tried something like this but is not working:
var textLabel = d3.scale.ordinal().range(['Black','Blonde','Brown','Red']);
svg.append("g").selectAll("path")
.data(chord.groups)
.enter()
.append("path")
.style("fill", function(d) { return fill(d.index); })
.style("stroke", function(d) { return fill(d.index); })
.attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
svg.append("g").append("svg:text")
.attr("x", 6)
.attr("dy", 15)
.append("svg:textPath")
.text(function(d,i) { return textLabel(i+1); })
.on("mouseover", fade(.1))
.on("mouseout", fade(1));
You have forgotten to use the enter selection and also do not link the svg:textPath to an actual path in the SGV. To do this the path you want the text to follow needs to have been given an id attribute and you need to reference this in the textPath with an href attribute.
So you want to add the id attribute to the path you want the text to follow
.attr("id", function(d, i){return "group-" + i;})
You then want to do something like this to add textPath elements
svg.append("g").selectAll("text")
.data(chord.groups)
.enter()
.append("sgv:text")
.attr("x", 6)
.attr("dy", 15)
.append("svg:textPath")
.attr("xlink:href", function(d, i){return "#group-" + i;})
.text(function(d,i) {return textLabel(i+1);});
Finally with the colour black you will probably want to invert the text so you don't end up with black on black text.
.filter(function(d, i){return i === 0 ? true : false;})
.attr("style", "fill:white;");
I'm trying to draw multiple 'cross' symbols inside of a circle for use in a visualization. I'd like to draw the crosses in a 'g' tag and then apply a clipping path.
Is it possible to use clip paths with d3.svg.symbol ?
In the below example, the svg circle is masked correctly with the clip path; however the cross (the last part of the code) isn't.
Am I doing something wrong or is this not a feature?
var svg = d3.select("#maskingExample")
.append("svg:svg")
.attr("width", 500)
.attr("height", 200);
svg.append("svg:clipPath")
.attr("id", "clipper")
.append("svg:rect")
.style("stroke", "gray")
.style("fill", "black")
.attr("x", 50)
.attr("y", 25)
.attr("width", 300)
.attr("height", 45);
svg.append("g").append("svg:circle")
.style("stroke", "gray")
.style("fill", "blue")
.attr("cx", 175)
.attr("cy", 55)
.attr("r", 50)
.attr("clip-path", "url(#clipper)");
svg.append("g").append("path")
.attr("d", d3.svg.symbol()
.size( function(d) { return 3000; })
.type( function(d) { return d3.svg.symbolTypes[1]; }))
.attr("transform", "translate(150, 50)")
.attr("clip-path", "url(#clipper")
.style("fill", "black");
You're missing a close paren. Instead of
.attr("clip-path", "url(#clipper")
it should read
.attr("clip-path", "url(#clipper)")