I am trying to pass a parameter when I click on a pie slice, that was created using the D3 library, with the following code to a Filemaker database script. The dataset is in an Array of Objects format.
var dataset = [{key: 1, amt: 5}, {key: 2, amt: 10}, {key: 3, amt: 20}];
I can can put a constant in place of d.amt and pass the constant to Filemaker.
I initially was drawing the pie chart using an array format and the onclick worked fine using, d.value.
Is d.amt the correct syntax to use to pass the parameter for the Array of Objects data format?
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
.attr("onclick", function(d, i){
return "location.href='" + script + "¶m=" + d.amt + "'";
});
Adding the .on("click", function(d, i) {.. the pie chart did not plot. For the location.href = you have "script¶m=" + d.amt; I need it to be '" + script + "¶m=" + d.amt + "'"; in case it makes a difference.
This is what I have;
...
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")")
.on("click", function(d, i) {
location.href ="script¶m=" + d.amt;
};
d3's on function serves the purpose better:
svg.selectAll("g.arc)
...
.on("click", function(d, i) {
location.href = script + "¶m=" + d.amt;
});
attr sets the target statically, while creating the elements. on determines the target dynamically, when the click occurs.
Apart from that, d.amt is correct, and I'd also expect your attr variant to work.
Related
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.
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)");
}
In the d3 calendar view example, I am trying to modify it to automatically determine the range of years to display from the data given it.
Is it possible to have d3 automatically figure out what arguments to pass to d3.range() to automatically determine the start and end year, rather than have hard-coded literals?
In the .data() line below, I've tried using d3.min() and d3.max() as arguments to d3.range(), but that's not correct. I've tried sorting the nested data beforehand to obtain the first and last entry in the array, but that has not worked. Suggestions?
return d3.select( "body" )
.selectAll( "svg" )
.data(d3.range(1990, 2010))
.enter()
.append( "svg" )
.attr( "width", width )
.attr( "height", height )
.attr( "class", "year" )
.append( "g" )
.attr( "transform", "translate(" + getOffsetX() + "," + getOffsetY() + ")" );
Put everything that is done before the d3.csv("dji.csv", inside the callback and after the d3.nest(), modify the following line
var range = d3.extent(csv, d => Number(d.Date.substring(0,4)));
var svg = d3.select("body")
.selectAll("svg")
.data(d3.range(range[0], range[1]))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");
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>
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.