Remove comma to separate groups of thousands of axis labels in D3 - javascript

I took this redraw function from http://bl.ocks.org/stepheneb/1182434 and I would like to adapt it.
How to remove the comma separator for the groups of thousands? in the code console.log(self.x.ticks(10).map(self.x.tickFormat(2, ".1"))) works and yields numbers in this format: [ "0", "1000", "2000",.. ], which is what I want. When I put it in .data() as in the code I get [ "0", "1,000", "2,000",.. ].
I am using a zoom so i cannot hardcode the labels.
The main part of the code should be:
fx = self.x.tickFormat(10),
//fx = self.x.tickFormat(d3.format("f2")), //does not work
fy = self.y.tickFormat(10);
// Regenerate x-ticks…
var gx = self.vis.selectAll("g.x")
.data(self.x.ticks(10).map(self.x.tickFormat(2, ".1")), String)
.attr("transform", tx);
console.log(self.x.ticks(10).map(self.x.tickFormat(2, ".1")))
gx.select("text")
.text(fx);
The whole redraw function:
SimpSimpleGraph.prototype.redraw = function() {
var self = this;
return function() {
var tx = function(d) {
return "translate(" + self.x(d) + ",0)";
},
ty = function(d) {
return "translate(0," + self.y(d) + ")";
},
stroke = function(d) {
return d ? "#ccc" : "#666";
},
fx = self.x.tickFormat(10),
//fx = self.x.tickFormat(d3.format("f2")), //does not work
fy = self.y.tickFormat(10);
// Regenerate x-ticks…
var gx = self.vis.selectAll("g.x")
.data(self.x.ticks(10).map(self.x.tickFormat(2, ".1")), String)
.attr("transform", tx);
console.log(self.x.ticks(10).map(self.x.tickFormat(2, ".1")))
gx.select("text")
.text(fx);
var gxe = gx.enter().insert("g", "a")
.attr("class", "x")
.attr("transform", tx);
gxe.append("line")
.attr("stroke", stroke)
.attr("y1", 0)
.attr("y2", self.height);
gxe.append("text")
.attr("class", "axis label")
.attr("y", self.height)
.attr("dy", "1em")
.attr("text-anchor", "middle")
.text(fx)
.style("cursor", "ew-resize")
.on("mouseover", function(d) { d3.select(this).style("font-weight", "bold");})
.on("mouseout", function(d) { d3.select(this).style("font-weight", "normal");})
.on("mousedown.drag", self.xaxis_drag())
.on("touchstart.drag", self.xaxis_drag());
gx.exit().remove();
// Regenerate y-ticks…
var gy = self.vis.selectAll("g.y")
.data(self.y.ticks(10), String)
.attr("transform", ty);
gy.select("text")
.text(fy);
var gye = gy.enter().insert("g", "a")
.attr("class", "y")
.attr("transform", ty)
.attr("background-fill", "#FFEEB6");
gye.append("line")
.attr("stroke", stroke)
.attr("x1", 0)
.attr("x2", self.width);
gye.append("text")
.attr("class", "axis label")
.attr("x", -3)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(fy)
.style("cursor", "ns-resize")
.on("mouseover", function(d) { d3.select(this).style("font-weight", "bold");})
.on("mouseout", function(d) { d3.select(this).style("font-weight", "normal");})
.on("mousedown.drag", self.yaxis_drag())
.on("touchstart.drag", self.yaxis_drag());
gy.exit().remove();
//This zoom is call after the plot has loaded
self.plot.call(d3.behavior.zoom().x(self.x).y(self.y).on("zoom", self.redraw()));
self.update();
}
}

As far as changing the way d3 outputs numbers, I haven't the foggiest clue. But you can alter these values afterwards using string prototype .replace.
Example
var someString = 'The catcher in the rye';
someString.replace('catcher','captcha'); //"The captcha in the rye"
And here is how you apply this to an array.
http://jsfiddle.net/sq2johrv/1/

Use .ticks(myTicksCount, '.f') instead of .ticks(myTicksCount) to remove the comma to separate groups of thousands.
For details, see the docs on
https://github.com/d3/d3-axis/blob/master/README.md#axis_ticks
https://github.com/d3/d3-axis/blob/master/README.md#axis_tickFormat
https://github.com/d3/d3-format
You can test the format specifiers (including your own) on http://bl.ocks.org/zanarmstrong/05c1e95bf7aa16c4768e

Related

d3js: Update data array and change graph

I have a d3 script for which the data that I have is as shown below:
var data = [{name: "A", rank: 0, student_percentile: 100.0},
{name: "B", rank: 45, student_percentile: 40.3},
{name: "C", rank: 89, student_percentile: 89.7},
{name: "D", rank: 23, student_percentile: 10.9},
{name: "E", rank: 56, student_percentile: 30.3}];
This data array has been fetched from the server.
I have a d3 script given below:
function d3Data(){
data = data.sort(function(x,y){
return d3.ascending(+x.rank, +y.rank);
});
var size = document.getElementById("range").value;
console.log(size);
data = data.slice(0,size);
d3(data);
}
function d3(data){
var margin = 40,
width = 600,
height = 400;
console.log(data);
var xscale = d3.scaleLinear()
.domain(
d3.extent(data, function(d) { return +d.student_percentile; })
)
.nice()
.range([0, width]);
var yscale = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return +d.rank; }))
.nice()
.range([height, 0]);
var xAxis = d3.axisBottom().scale(xscale);
var yAxis = d3.axisLeft().scale(yscale);
var svg = d3.select('.chart')
.append('svg')
.attr('class', 'chart')
.attr("width", width + margin + margin)
.attr("height", height + margin + margin + 10 )
.append("g")
.attr("transform", "translate(" + margin + "," + margin + ")");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var circles = svg.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("opacity", 0.3)
.attr("r", 20)
.style("fill", "blue")
.attr("cx", function(d) {
return xscale(+d.student_percentile);
})
.attr("cy", function(d) {
return yscale(+d.rank);
})
.on('mouseover', function(d, i) {
d3.select(this)
.transition()
.duration(1000)
.ease(d3.easeBounce)
.attr("r", 32)
.style("fill", "orange")
.style("cursor", "pointer")
.attr("text-anchor", "middle");
texts.filter(function(e) {
return e.rank === d.rank;
})
.attr("font-size", "20px")
})
.on('mouseout', function(d, i) {
d3.select(this).transition()
.style("opacity", 0.3)
.attr("r", 20)
.style("fill", "blue")
.style("cursor", "default");
texts.filter(function(e) {
return e.rank === d.rank;
})
.transition()
.duration(1000)
.ease(d3.easeBounce)
.attr("font-size", "10px")
});
var texts = svg.selectAll(null)
.data(data)
.enter()
.append('text')
.attr("x", function(d) {
return xscale(+d.student_percentile);
})
.attr("text-anchor", "middle")
.attr("y", function(d) {
return yscale(+d.rank);
})
.text(function(d) {
return +d.student_percentile;
})
.attr("pointer-events", "none")
.attr("font-family", "sans-serif")
.attr("font-size", "10px")
.attr("fill", "red");
svg.append("text")
.attr("transform", "translate(" + (width / 2) + " ," + (height + margin) + ")")
.style("text-anchor", "middle")
.text("Percentile");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Rank");
$('circle').tipsy({
console.log("tipsy");
gravity: 'w',
html: true,
title: function() {
var d = this.__data__;
return d.name + '<br/>' + d.rank;
}
});
}
$(document).ready(function(){
d3Data();
});
function rangeVal(){
d3Data();
}
function fadeOut() {
svg.selectAll("circle")
.transition()
.style("opacity", 0.3)
.attr("r", 20)
.style("fill", "blue");
}
function handleMouseOver() {
d3.select(this)
.attr("r", 32)
.style("fill", "orange");
}
I call the function d3Data when the document gets loaded and also when button is clicked (rangeVal is the function that is called on button click). On button click, I want to apply different filters on data and then make the graph again. Currently what is happening is I am getting multiple graphs on button click but the existing graph is not getting updated. The current output is as shown: multiple graphs
I just want d3Data() function to update original data array every time button is clicked and then make the graph again. How can I do that?
Each an every time depend upon the data SVG is newly created. So you have to remove the SVG Before Creation
//d3.select("Your Id Name or Your Class Name").select("svg").remove();
In Your Code, I changed follow as
d3.select('.chart').select("svg").remove();
var svg = d3.select('.chart')
I found the solution. I had to make two changes. In function d3data, I was updating the same array again and again, so the data was not getting updated correctly and before calling d3(), I had to remove existing graph.
function d3Data(){
data_sorted = data.sort(function(x,y){
return d3.ascending(+x.rank, +y.rank);
}); // update array and put it in another variable
var size = document.getElementById("range").value;
console.log(size);
data_sliced = data_sorted.slice(0,size);
d3.select('.chart').html(""); //this to remove existing graph
d3(data_sliced);
}

D3.js Combining Candlestick Chart with Line Graph

I am trying to plot a moving average on top of a candlestick chart but the "path" is not appearing completely on the svg canvas that I created.
I have tried looking at several post on how to put a line on top of a bar graph (because I figured it would be similar) but it has not worked.
A couple of the examples and post I have looked at are below:
https://bl.ocks.org/nanu146/f48ffc5ec10270f55c9e1fb3da8b38f0
d3.js How to add lines to a bar chart
D3.js combining bar and line chart
I have all the data in a array.
I am using the same x "scale" for both the candle stick graph and the moving average (line). I have tried using the same y "scale" for both the line and the candlestick but it did not work. Therefore i tried creating 2 scales for y, one for the moving average and one for the candlestick chart. That is what Im doing in my code below.
<script src="https://d3js.org/d3.v4.min.js"></script>
<script type="text/javascript">
var twoHundredDayCandleStickChart = [];
//pulling from 2 properties so must do this way
#for (int i = 0; i != 100; ++i)
{
#:twoHundredDayCandleStickChart.push({date: '#Model.DailyTimeSeriesData.Data.ElementAt(i).Key', high: '#Model.DailyTimeSeriesData.Data.ElementAt(i).Value.high', low: '#Model.DailyTimeSeriesData.Data.ElementAt(i).Value.low', open: '#Model.DailyTimeSeriesData.Data.ElementAt(i).Value.open', close: '#Model.DailyTimeSeriesData.Data.ElementAt(i).Value.close', sma: '#Model.TwoHundredDaySma.Data.ElementAt(i).Value.Sma'})
}
console.log(twoHundredDayCandleStickChart);
var width = 900;
var height = 500;
var margin = 50;
function min(a, b) { return a < b ? a : b; }
function max(a, b) { return a > b ? a : b; }
//y for the candlestick
var y = d3.scaleLinear().range([height - margin, margin]);
var x = d3.scaleTime().range([margin, width - margin]);
//y for the line
var y1 = d3.scaleLinear().range([height - margin, margin]);
//line for the sma
var line1 = d3.line()
.x(function (d) { return x(d["date"]); })
.y(function (d) { return y(d["sma"]); });
function buildChart(data) {
data.forEach(function (d) {
d.date = new Date(d.date);
d.high = +d.high;
d.low = +d.low;
d.open = +d.open;
d.close = +d.close;
d.sma = +d.sma;
});
var chart = d3.select("#twoHundredDaySmaWithCandleStickChart")
.append("svg")
.attr("class", "chart")
.attr("width", width)
.attr("height", height);
//map is going to create an array with all the lows and then d3.min will take the min out of all of them
y.domain([d3.min(data.map(function (x) { return x["low"]; })), d3.max(data.map(function (x) { return x["high"]; }))])
x.domain(d3.extent(data, function (d) { return d["date"]; }))
y1.domain(d3.extent(68, d3.max(data, function (d) { return d["sma"]; })))
//grid for the chart; x and y axis
chart.selectAll("line.x")
.data(x.ticks(10))
.enter().append("line")
.attr("class", "x")
//.text(String)
.attr("x1", x)
.attr("x2", x)
.attr("y1", margin)
.attr("y2", height - margin)
.attr("stroke", "#ccc");
chart.selectAll("line.y")
.data(y.ticks(10))
.enter().append("line")
.attr("class", "y")
.attr("x1", margin)
.attr("x2", width - margin)
.attr("y1", y)
.attr("y2", y)
.attr("stroke", "#ccc");
//x axis
chart.append("g")
.attr("transform", "translate(0," + 450 + ")") //need to change this 450 to a variable- it is how far down the axis will go
.attr("class", "xrule") // give it a class so it can be used to select only xaxis labels or change color
//the x axis
.call(d3.axisBottom(x))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function (d) {
return "rotate(-65)"
});
//the y axis
chart.selectAll("text.yrule")
.data(y.ticks(10))
.enter()
.append("text")
.attr("class", "yrule")
.attr("x", 0)
.attr("y", y)
.attr("dy", 0)
.attr("dx", 20)
.attr("text-anchor", "middle")
.text(String);
//add rectangles- if open higher then close then red
chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("x", function (d) { return x(d["date"]); })
.attr("y", function (d) { return y(max(d["open"], d["close"])); })
.attr("height", function (d) { return y(min(d["open"], d["close"])) - y(max(d["open"], d["close"])); })
.attr("width", function (d) { return 0.5 * (width - 2 * margin) / data.length; })
.attr("fill", function (d) { return d["open"] > d["close"] ? "red" : "green"; });
//add a stem to the rectangle
chart.selectAll("line.stem")
.data(data)
.enter().append("line")
.attr("class", "stem")
.attr("x1", function (d) { return x(d["date"]) + 0.25 * (width - 2 * margin) / data.length; })
.attr("x2", function (d) { return x(d["date"]) + 0.25 * (width - 2 * margin) / data.length; })
.attr("y1", function (d) { return y(d["high"]); })
.attr("y2", function (d) { return y(d["low"]); })
.attr("stroke", function (d) { return d.open > d.close ? "red" : "green"; });
chart.append("path")
.data([data])
.attr("d", line1)
.attr("class", "line")
.style("stroke", "white")
.attr("fill", "none")
.attr("stroke-width", 2);
}
buildChart(twoHundredDayCandleStickChart);
</script>
The above code is giving me the image below:
The problem in the chart above was my scales! I was taking the domain for the candle stick data but the line data was a lot lower of a min. Therefore the whole graph was not showing up on the scale because the min of the domain had to be adjusted. MANY hours wasted but hopefully this can save someone else time!
d3.select("#twoHundredDaySmaWithCandleStickChart")
Try to change the above code like below
d3.select("svg") or give the div Id

how to change stack order of text label in JavaScript?

I am trying to plot a network graph using networkD3 in R. I wanted to make some changes to the display so that the text labels (which appears when mouseover) can be easily read.
Please refer to the link here for an example. Note: Jump to the d3ForceNetwork plot.
As seen in the example, the labels are hard to read due to its colour and it often gets obstructed by the surrounding nodes. I have been messing around with the JS file and managed to change the text label color to black. However, having no knowledge of JS or CSS (I can't even tell the difference between the 2 actually), I have no idea how I can change the stack order such that the text labels will always be displayed above any other objects.
Can anyone advise me on how I can achieve the desired outcome?
Below is the full JS file:
HTMLWidgets.widget({
name: "forceNetwork",
type: "output",
initialize: function(el, width, height) {
d3.select(el).append("svg")
.attr("width", width)
.attr("height", height);
return d3.layout.force();
},
resize: function(el, width, height, force) {
d3.select(el).select("svg")
.attr("width", width)
.attr("height", height);
force.size([width, height]).resume();
},
renderValue: function(el, x, force) {
// Compute the node radius using the javascript math expression specified
function nodeSize(d) {
if(options.nodesize){
return eval(options.radiusCalculation);
}else{
return 6}
}
// alias options
var options = x.options;
// convert links and nodes data frames to d3 friendly format
var links = HTMLWidgets.dataframeToD3(x.links);
var nodes = HTMLWidgets.dataframeToD3(x.nodes);
// get the width and height
var width = el.offsetWidth;
var height = el.offsetHeight;
var color = eval(options.colourScale);
// set this up even if zoom = F
var zoom = d3.behavior.zoom();
// create d3 force layout
force
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(options.linkDistance)
.charge(options.charge)
.on("tick", tick)
.start();
// thanks http://plnkr.co/edit/cxLlvIlmo1Y6vJyPs6N9?p=preview
// http://stackoverflow.com/questions/22924253/adding-pan-zoom-to-d3js-force-directed
var drag = force.drag()
.on("dragstart", dragstart)
// allow force drag to work with pan/zoom drag
function dragstart(d) {
d3.event.sourceEvent.preventDefault();
d3.event.sourceEvent.stopPropagation();
}
// select the svg element and remove existing children
var svg = d3.select(el).select("svg");
svg.selectAll("*").remove();
// add two g layers; the first will be zoom target if zoom = T
// fine to have two g layers even if zoom = F
svg = svg
.append("g").attr("class","zoom-layer")
.append("g")
// add zooming if requested
if (options.zoom) {
function redraw() {
d3.select(el).select(".zoom-layer").attr("transform",
"translate(" + d3.event.translate + ")"+
" scale(" + d3.event.scale + ")");
}
zoom.on("zoom", redraw)
d3.select(el).select("svg")
.attr("pointer-events", "all")
.call(zoom);
} else {
zoom.on("zoom", null);
}
// draw links
var link = svg.selectAll(".link")
.data(force.links())
.enter().append("line")
.attr("class", "link")
.style("stroke", function(d) { return d.colour ; })
//.style("stroke", options.linkColour)
.style("opacity", options.opacity)
.style("stroke-width", eval("(" + options.linkWidth + ")"))
.on("mouseover", function(d) {
d3.select(this)
.style("opacity", 1);
})
.on("mouseout", function(d) {
d3.select(this)
.style("opacity", options.opacity);
});
// draw nodes
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.style("fill", function(d) { return color(d.group); })
.style("opacity", options.opacity)
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", click)
.call(force.drag);
node.append("circle")
.attr("r", function(d){return nodeSize(d);})
.style("stroke", "#fff")
.style("opacity", options.opacity)
.style("stroke-width", "1.5px");
node.append("svg:text")
.attr("class", "nodetext")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name })
.style("font", options.fontSize + "px " + options.fontFamily)
.style("opacity", options.opacityNoHover)
.style("pointer-events", "none");
function tick() {
node.attr("transform", function(d) {
if(options.bounded){ // adds bounding box
d.x = Math.max(nodeSize(d), Math.min(width - nodeSize(d), d.x));
d.y = Math.max(nodeSize(d), Math.min(height - nodeSize(d), d.y));
}
return "translate(" + d.x + "," + d.y + ")"});
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
}
function mouseover() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", function(d){return nodeSize(d)+5;});
d3.select(this).select("text").transition()
.duration(750)
.attr("x", 13)
.style("stroke-width", ".5px")
.style("font", options.clickTextSize + "px ")
.style('fill', 'black')
.style('position','relative')
.style("opacity", 1);
}
function mouseout() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", function(d){return nodeSize(d);});
d3.select(this).select("text").transition()
.duration(1250)
.attr("x", 0)
.style("font", options.fontSize + "px ")
.style("opacity", options.opacityNoHover);
}
function click(d) {
return eval(options.clickAction)
}
// add legend option
if(options.legend){
var legendRectSize = 18;
var legendSpacing = 4;
var legend = svg.selectAll('.legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing;
var offset = height * color.domain().length / 2;
var horz = legendRectSize;
var vert = i * height+4;
return 'translate(' + horz + ',' + vert + ')';
});
legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.style('fill', 'darkOrange')
.text(function(d) { return d; });
}
// make font-family consistent across all elements
d3.select(el).selectAll('text').style('font-family', options.fontFamily);
},
});
I suspect I need to make some changes to the code over here:
function mouseover() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", function(d){return nodeSize(d)+5;});
d3.select(this).select("text").transition()
.duration(750)
.attr("x", 13)
.style("stroke-width", ".5px")
.style("font", options.clickTextSize + "px ")
.style('fill', 'black')
.style("opacity", 1);
}
You need to resort the node groups holding the circles and text so the currently mouseover'ed one is the last in that group, and thus the last one drawn so it appears on top of the others. See the first answer here -->
Updating SVG Element Z-Index With D3
In your case, if your data doesn't have an id field you may have to use 'name' instead as below (adapted to use the mouseover function you've got):
function mouseover(d) {
d3.selectAll("g.node").sort(function (a, b) {
if (a.name != d.name) return -1; // a is not the hovered element, send "a" to the back
else return 1; // a is the hovered element, bring "a" to the front (by making it last)
});
// your code continues
The pain might be that you have to do this edit for every d3 graph generated by this R script, unless you can edit the R code/package itself. (or you could suggest it to the package author as an enhancement.)

Overlapping legend d3.js

I am creating the legends with triangle shapes. One is "Yes", the other one is "No". By running the code below, it generate two triangles but they are overlapping. I am trying to seperate them by using this line of code .attr("y", function(d,i) {return 50+i*40;}) but seems like it doesn't work.
Can anyone tell me how to fix it? Thanks!
Click here! This is an html sreenshot for this part of script
var legendname = ["Yes","No"];
var legend = svg.selectAll(".legend")
.data(legendname)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(" + (w + 150) + "," + (m.t - 30) + ")";
});
legend.append("path")
.attr("d", d3.svg.symbol().type("triangle-up").size(128))
*** .attr("y", function(d,i) {return 50+i*40;})
.style('fill', function(d) {return color(d);});
legend.append("text")
.attr("y", function(d,i) {return 50+i*20;})
.attr("x", 30)
.text(function(d) { return d; })
You will have to update the translate y attribute of groups instead of the paths. And also there is no need for extra calculations for y attributes of texts and paths then.
.attr("transform", function(d, i) {
return "translate(" + (w + 150) + "," + (30+i*40) + ")";
});
Working Code Snippet:
var w=40; //Sample chart width
var color = d3.scale.category20c();
var svg = d3.select("body").append("svg").attr({ height: 500, width: 400 });
var legendname = ["Yes", "No"];
var legend = svg.selectAll(".legend")
.data(legendname)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(" + (w + 150) + "," + (30+i*40) + ")";
});
legend.append("path")
.attr("d", d3.svg.symbol().type("triangle-up").size(128))
.style('fill', function(d,i) {
return color(i);
});
legend.append("text")
.attr("dx",10)
.attr("dy",".4em")
.text(function(d) {
return d;
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

How to display data value on every layout of stacked barchart in d3

I have created a stacked bar chart in d3.
Here I want to display the value like this below example (This is Simple Bar chart)
http://bl.ocks.org/enjalot/1218567
But not outside the bar, inside the bar like below :
http://bl.ocks.org/diethardsteiner/3287802
This is my Stacked function which is working fine :
function barStack(d)
{
var l = d[0].length
while (l--) {
var posBase = 0,
negBase = 0;
d.forEach(function (d) {
d = d[l]
d.size = Math.abs(d.y)
if (d.y < 0) {
d.y0 = negBase
negBase -= d.size
} else {
d.y0 = posBase = posBase + d.size
}
})
}
d.extent = d3.extent(d3.merge(d3.merge(d.map(function (e) {
return e.map(function (f) {
return [f.y0, f.y0 - f.size]
})
}))))
return d
}
For stacked Bar
svg.selectAll(".series")
.data(data)
.enter()
.append("g")
.attr("class", "g")
.style("fill", function (d, i) {return color(i)})
.selectAll("rect")
.data(Object)
.enter()
.append("rect")
.attr("x", function (d, i) {return x(x.domain()[i])})
.attr("y", function (d) { return y(d.y0) })
.attr("height", function (d) { return y(0) - y(d.size) })
.attr("width", x.rangeBand())
;
This was also running fine.
My data is like that
var data = [{x:"abc", y1:"3", y2:"4", y3:"10"},
{x:"abc2", y1:"6", y2:"-2", y3:"-3" },
{x:"abc3", y1:"-3", y2:"-9", y3:"4"}
]
Now I want to show this value of y1, y2 and y3 in every stacked layout.
I have tried this below code, but this is not displaying the value over layout.
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("transform", "translate(50,0)")
.attr("text-anchor", "middle")
.attr("x", function(d, i) {return (i * (width / data.length)) + ((width / data.length - 50) / 2);})
.attr("y", function(d) {return y(0) - y(d.size) + 14;})
.attr("class", "yAxis")
.text(function(d) {return y(d.size);})
;
Please help me on this, where I need to change or what exact I need to put instead of this or might be above code was totally wrong.
Please let me know if any more input required by me. I have the total POC and I can share that too.
i have added all code in jsfiddle
http://jsfiddle.net/goldenbutter/HZqkm/
Here is a fiddle that does what you want.
var plots = svg.selectAll(".series").data(data)
.enter()
.append("g")
.classed("series",true)
.style("fill", function(d,i) {return color(i)})
plots.selectAll("rect").data(Object)
.enter().append("rect")
.attr("x",function(d,i) { return x(x.domain()[i])})
.attr("y",function(d) { return y(d.y0)})
.attr("height",function(d) { return y(0)-y(d.size)})
.attr("width",x.rangeBand());
plots.selectAll("text.lab").data(Object)
.enter().append("text")
.attr('fill','black')
.attr("text-anchor", "middle")
.attr("x", function(d, i) { return x(x.domain()[i]) + (x.rangeBand()/2)})
.attr("y", function(d) {return y(d.y0) + 20})
.text(function(d) {return (d.size).toFixed(2);});

Categories