Rotate D3 symbol - d3.js

I'm rendering a d3 symbol that looks like this:
svg.append('path')
.attr("d", d3.svg.symbol().type("triangle-up").size(10))
.attr("transform", function(d) { return "translate(" + 100 + "," + 100 + ")"; })
.style("fill", "red")
I'd like to rotate this triangle so that the triangle points left <|. How can I rotate this symbol while keeping it at the same position in my viz? I've been trying to do the following, but the symbol moves to the upper left corner of my viz (it doesn't stay in the position created by the transformation):
svg.append('path')
.attr("d", d3.svg.symbol().type("triangle-up").size(10))
.attr("transform", function(d) { return "translate(" + 100 + "," + 100 + ")"; })
.attr("transform", "rotate(-45)")
.style("fill", "red")

The problem is that the second call to set transform overrides the first value here:
.attr("transform", function(d) { return "translate(" + 100 + "," + 100 + ")"; })
.attr("transform", "rotate(-45)") // Only this value will remain as the value of the attr
To fix it, you should append the rotation to the original value of transform:
.attr("transform", function(d) { return "translate(" + 100 + "," + 100 + ") rotate(-45)"; })
Another solution is to put the symbol in nested g elements and apply individual transforms to each of them, example.

Related

D3JS: unable to set only 5 ticks in x Axis

I've been unable to set only 5 ticks on my x Axis, by default it set 10 ticks, multiples of 5, I tried to use ´.ticks(5)´ but it's not working for me. If if visualize the chart on mobile, 10 ticks becomes almost unreadable. But as I mentioned ´.ticks(5)´ it's not working
this is the snippet which draws the x axis:
var xAxis = svg.append("g")
.style("font-size", textSetter())
.attr("class", "xAxis", "axis")
.attr("transform", "translate(" + 0 + "," + heightTwo + ")")
.call(d3.axisBottom(xScale).ticks(5)
.tickPadding(5).tickFormat(d => d + "%"))
How can I solve this? Thanks
You could set all the text in the axis to a particular class and then hide the ticks based on the number for example.
//Create the xAxis and assign x-axisticks class to the tick text
var xAxis = svg.append("g")
.style("font-size", textSetter())
.attr("class", "xAxis", "axis")
.attr("transform", "translate(" + 0 + "," + heightTwo + ")")
.call(d3.axisBottom(xScale)
.selectAll('text')
.attr('class', 'x-axisticks');
//remove the ticks which based on the multiples
var xticks = d3.selectAll('.x-axisticks');
xticks.attr('class', function (d, i) {
i = i + 1;
if (i % 5 !== 0) d3.select(this).remove();
});
Hope this helps. A more specific use-case answer would probably require some more code to be posted from your end so that I can tailor an answer, but this should work.

D3 - Position second x axis labels

I have a stackblitz here - https://stackblitz.com/edit/d3-stacked-trend-bar-positioned-months-1b93nz?file=src%2Fapp%2Fbar-chart.ts
I have a stacked bar chart using D3 in Angular.
I'm trying to position a second axis of labels on the x axis.
Currently I'm using the with of the graph but this means the labels dont line up correctly with the bars.
Is there a better D3 way to add these labels and positino them.
Use the x-position of the bars and position the text in the middle of it.
private drawBarTitle(data:any){
this.chart.append('g')
.attr("transform", "translate(" + 10 + "," + (this.height+10) + ")")
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('transform', (d:any, i:any)=>{
var x = this.x(d.date) + (i%2) * 0.525 * this.x.bandwidth();
return "translate(" + (x + this.x.bandwidth()*0.95*0.25) + "," + 0 + ")"
})
.append('text')
.text((d:any, i:any)=>{ return d.type; })
.attr("dy", "-0.3em")
.classed('trend-type', true)
.style("text-anchor", "end")
.attr("transform", "rotate(-90)");
}

d3 text only appears when added to a group. Why?

I have appended some text to a map I am working on in d3, here is my code:
countriesGroup = svg
.append("g")
.attr("id", "map");
//add background
countriesGroup.append('rect')
.attr("x", 0)
.attr("y", 0)
.attr("width", w)
.attr("height", h);
//Draw countries
countries = countriesGroup.selectAll("path")
.data(j.features)
.enter()
...Draw country borders
//Create Timer Text
countriesGroup.append("text") <-----This worked
.attr("transform", "translate(" + w/2 + "," + h/2 + ")")
.style("fill", "#ff0000")
.text("This is a test");
//Create Timer Text
svg.append("text") <-----This didn't
.attr("transform", "translate(" + w/2 + "," + h/2 + ")")
.style("fill", "#ff0000")
.text("This is a test");
I initially tried appending the Timer text directly to svg but that did not work. When I later tried appending it directly to the countriesGroup group, this worked. How come the text was only able to render when appended to the group, but not when appended directly to the svg?

How to draw vertical text as labels in D3

I'm trying to draw vertical labels for the heatmap that I'm working. I'm using the example from http://bl.ocks.org/tjdecke/5558084. Here is the part of the code that I've changed:
var timeLabels = svg.selectAll(".timeLabel")
.data(ife_nr)
.enter().append("text")
.text(function(d) {
return d;
})
.attr("x", function(d, i) {
return (i * gridSize);
})
.attr("y", 0)
//.style("text-anchor", "middle")
//.attr("transform", "translate(" + gridSize / 2 + '-5' + ")")
.attr("transform", "translate(" + gridSize/2 + '-8' + "), rotate(-90)")
.attr("class", function(d, i) {
return ((i >= 0) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis");
});
But it appears the labels seems to be stacked on top one another on top of the first grid. How can I edit this code to get the labels correctly displayed?
Two problems: first, the translate should have a comma separating the values:
"translate(" + gridSize/2 + ",-8), rotate(-90)")
Assuming that -8 is the y value for the translate. If you don't have a comma, the value inside the parenthesis should be just the x translation (If y is not provided, it is assumed to be zero). But even if there is actually no comma and all that gridSize/2 + '-8' is just the x value you still have a problem, because number plus string is a string. You'll have to clarify this point.
Besides that, for rotating the texts over their centres, you'll have to set the cx and cy of the rotate. Have a look at this demo:
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 100);
var texts = svg.selectAll(".texts")
.data(["foo", "bar", "baz"])
.enter()
.append("text");
texts.attr("y", 50)
.attr("x", function(d,i){ return 50 + 80*i})
.text(function(d){ return d});
texts.attr("transform", function(d,i){
return "rotate(-90 " + (50 + 80*i) + " 50)";
});
<script src="https://d3js.org/d3.v4.js"></script>

font size is not working in my d3.js code

i am writing d3.js for generating many charts and graphs.. but when there is no data i am just appending svg a text and writting "no data to display" and assigning some attributes like x y dy etc.. similarly font-size but except font size every thing is working .
why? here is my code
var svg = d3.select(selector).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
if (!data.IssueTrendsDAO.issueTrendList) {
svg.append("text")
.attr("font-size","34px")
.attr("y", 79)
.attr("x", 40)
.attr("dy", ".47em")
.style("text-anchor", "start")
.style("fill", "#004669")
.style("font-weight", "bold")
.text("No data to display");
}
I think you'll find it works if you assign font-size as a style rather than as an attribute.
.style("font-size", "34px")
(better yet, assign an id or class attribute and set all your styles in CSS)

Resources