I am trying to create a bar chart using D3.js. My initial requirement is to create a bar chart based on one set of data. It should be changed every time I press a button here.
The second dataset values are now taken to update but the order of the bars does not change depending on the second dataset. Note that I do not want to sort directly. Instead I want to update the values based on new dataset.
var sortBars = function () {
iteration_number = iteration_number + 1;
//alert(iteration_number);
sortOrder = !sortOrder;
sortItems = function (a, b) {
if (sortOrder) {
return a.value - b.value;
}
return b.value - a.value;
};
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset1.length))
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset1, function (d) {
return d.value;
})])
.range([0, h]);
svg.selectAll("rect")
.data(dataset1, key)
.enter()
.append("rect")
.attr("x", function (d, i) {
return xScale(i);
})
.attr("y", function (d) {
return h - yScale(d.value);
})
.attr("width", xScale.rangeBand())
.attr("height", function (d) {
return yScale(d.value);
})
.attr("transform", function (d, i) {
return "translate(" + [0, d] + ")"
})
.attr("fill", function (d) {
return "rgb(0, 0, " + (d.value * 10) + ")";
})
//Tooltip
.on("mouseover", function (d) {
//Get this bar's x/y values, then augment for the tooltip
var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.rangeBand() / 2;
var yPosition = parseFloat(d3.select(this).attr("y")) + 14;
//Update Tooltip Position & value
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.select("#value")
.text(d.value);
d3.select("#tooltip").classed("hidden", false)
})
.on("mouseout", function () {
//Remove the tooltip
d3.select("#tooltip").classed("hidden", true);
})
.transition()
.delay(function (d, i) {
return i * 50;
})
.duration(1000)
.attr("x", function (d, i) {
return xScale(i);
});
svg.selectAll('text')
.data(dataset1, key)
.enter()
.append("text")
.text(function (d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("x", function (d, i) {
return xScale(i) + xScale.rangeBand() / 2;
})
.attr("y", function (d) {
return h - yScale(d.value) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "white");
};
FIDDLER
I could get the values changed now. But I want the change to look like swapping of bars in this chart. But this does not happen.
FIDDLER
Related
I have the following data set with only text and color information
var inputs = [{"text": "inleaf1", "col": "red"}, {"text": "inleaf2", "col": "blue"}, {"text": "inleaf3", "col": "green"}];
and the following is used to draw rectangles with text elements in it
var inputleaf = container.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("class", "input-leaf")
.attr("width", elementwidth)
.attr("height", elementheight)
.attr("x", startX)
.attr("y", function (d, i) {
return startY + ((elementheight + verticalmargin) * i);
})
.attr("stroke-width", "2")
.attr("fill", "none")
.attr("stroke", function (d) {
return d.col;
})
.call(function (d) {
//--------------------add position details to the data set
});
var inputtext = container.selectAll("text")
.data(data)
.enter().append("text")
.attr("x", startX + elementwidth / 10)
.attr("y", function (d, i) {
return startY + (elementheight / 2) + ((elementheight + verticalmargin) * i);
})
.text(function (d) {
return d.text;
});
during iteration, how can I add more attributes to the dataset, such as the position details. Basically I want to update the dataset.
This is one solution, maybe not the best one : update you data when you set the attr. For example :
.attr("y", function (d, i) {
var y = i * 10;
inputs[i].y = y // or d.y = y
return y;
})
See this fiddle
You can use selection.each:
var inputleaf = container.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("class", "input-leaf")
.attr("width", elementwidth)
.attr("height", elementheight)
.attr("x", startX)
.attr("y", function (d, i) {
return startY + ((elementheight + verticalmargin) * i);
})
.attr("stroke-width", "2")
.attr("fill", "none")
.attr("stroke", function (d) {
return d.col;
})
.each(function (d) {
//add position details to the data set
d.x = d3.select(this).attr('x');
d.y = d3.select(this).attr('y');
});
I am new to D3 and trying to dynamically update the chart if the source json is modified. But I am not able to achieve this.
Please check this plunkr
Js:
var width = 500,
height = 500,
radius = Math.min(width, height) / 2;
var x = d3.scale.linear()
.range([0, 2 * Math.PI]);
var y = d3.scale.sqrt()
.range([0, radius]);
var color = d3.scale.category10();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ") rotate(-90 0 0)");
var partition = d3.layout.partition()
.value(function(d) {
return d.size;
});
var arc = d3.svg.arc()
.startAngle(function(d) {
return Math.max(0, Math.min(2 * Math.PI, x(d.x)));
})
.endAngle(function(d) {
return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx)));
})
.innerRadius(function(d) {
return Math.max(0, y(d.y));
})
.outerRadius(function(d) {
return Math.max(0, y(d.y + d.dy));
});
//d3.json("/d/4063550/flare.json", function(error, root) {
var root = initItems;
var g = svg.selectAll("g")
.data(partition.nodes(root))
.enter().append("g");
var path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
});
//.append("text")
var text = g.append("text")
.attr("x", function(d) {
return y(d.y);
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
.text(function(d) {
return d.name;
})
.style("fill", "white");
function computeTextRotation(d) {
var angle = x(d.x + d.dx / 2) - Math.PI / 2;
return angle / Math.PI * 180;
}
function click(d) {
console.log(d)
// fade out all text elements
if (d.size !== undefined) {
d.size += 100;
};
text.transition().attr("opacity", 0);
path.transition()
.duration(750)
.attrTween("d", arcTween(d))
.each("end", function(e, i) {
// check if the animated element's data e lies within the visible angle span given in d
if (e.x >= d.x && e.x < (d.x + d.dx)) {
// get a selection of the associated text element
var arcText = d3.select(this.parentNode).select("text");
// fade in the text element and recalculate positions
arcText.transition().duration(750)
.attr("opacity", 1)
.attr("transform", function() {
return "rotate(" + computeTextRotation(e) + ")"
})
.attr("x", function(d) {
return y(d.y);
});
}
});
} //});
// Word wrap!
var insertLinebreaks = function(t, d, width) {
alert(0)
var el = d3.select(t);
var p = d3.select(t.parentNode);
p.append("g")
.attr("x", function(d) {
return y(d.y);
})
// .attr("dx", "6") // margin
//.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
//p
.append("foreignObject")
.attr('x', -width / 2)
.attr("width", width)
.attr("height", 200)
.append("xhtml:p")
.attr('style', 'word-wrap: break-word; text-align:center;')
.html(d.name);
alert(1)
el.remove();
alert(2)
};
//g.selectAll("text")
// .each(function(d,i){ insertLinebreaks(this, d, 50 ); });
d3.select(self.frameElement).style("height", height + "px");
// Interpolate the scales!
function arcTween(d) {
var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, 1]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
return function(d, i) {
return i ? function(t) {
return arc(d);
} : function(t) {
x.domain(xd(t));
y.domain(yd(t)).range(yr(t));
return arc(d);
};
};
}
function arcTweenUpdate(a) {
console.log(path);
var _self = this;
var i = d3.interpolate({ x: this.x0, dx: this.dx0 }, a);
return function(t) {
var b = i(t);
console.log(window);
_self.x0 = b.x;
_self.dx0 = b.dx;
return arc(b);
};
}
setTimeout(function() {
path.data(partition.nodes(newItems))
.transition()
.duration(750)
.attrTween("d", arcTweenUpdate)
}, 2000);
In addition to what #Cyril has suggested about removing the following line:
d3.select(self.frameElement).style("height", height + "px");
I made further modifications in your fiddle: working fiddle
The idea used here is to add a function updateChart which takes the items and then generate the chart:
var updateChart = function (items) {
// code to update the chart with new items
}
updateChart(initItems);
setTimeout(function () { updateChart(newItems); }, 2000);
This doesn't use the arcTweenUpdate function you have created but I will try to explain the underlying concept:
First, you will need to JOIN the new data with your existing data:
// DATA JOIN - Join new data with old elements, if any.
var gs = svg.selectAll("g").data(partition.nodes(root));
then, ENTER to create new elements if required:
// ENTER
var g = gs.enter().append("g").on("click", click);
But, we also need to UPDATE the existing/new path and text nodes with new data:
// UPDATE
var path = g.append("path");
gs.select('path')
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
//.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
})
.transition().duration(500)
.attr("d", arc);
var text = g.append("text");
gs.select('text')
.attr("x", function(d) {
return y(d.y);
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
.text(function(d) {
return d.name;
})
.style("fill", "white");
and, after everything is created/updated remove the g nodes which are not being used i.e. EXIT:
// EXIT - Remove old elements as needed.
gs.exit().transition().duration(500).style("fill-opacity", 1e-6).remove();
This whole pattern of JOIN + ENTER + UPDATE + EXIT is demonstrated in following articles by Mike Bostock:
General Update Pattern - I
General Update Pattern - II
General Update Pattern - III
In side the fiddle the setTimeout is not running because:
d3.select(self.frameElement).style("height", height + "px");
You will get Uncaught SecurityError: Failed to read the 'frame' property from 'Window': Blocked a frame with origin "https://fiddle.jshell.net" from accessing a frame with origin and the setTimeout never gets called.
So you can remove this line d3.select(self.frameElement).style("height", height + "px"); just for the fiddle.
Apart from that:
Your timeout function should look like this:
setTimeout(function() {
//remove the old graph
svg.selectAll("*").remove();
root = newItems;
g = svg.selectAll("g")
.data(partition.nodes(newItems))
.enter().append("g");
/make path
path = g.append("path")
.attr("d", arc)
.style("fill", function(d) {
return color((d.children ? d : d.parent).name);
})
.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
});
//make text
text = g.append("text")
.attr("x", function(d) {
return y(d.y);
})
.attr("dx", "6") // margin
.attr("dy", ".35em") // vertical-align
.attr("transform", function(d) {
return "rotate(" + computeTextRotation(d) + ")";
})
.text(function(d) {
return d.name;
})
.style("fill", "white");
}
working fiddle here
for the enter() and transitions to work you need to give d3 a way to identify each item in your data. the .data() function has a second parameter that lets you return something to use as an id. enter() will use the id to decide whether the object is new.
try changing
path.data(partition.nodes(newItems))
.data(partition.nodes(root));
to
path.data(partition.nodes(newItems), function(d){return d.name});
.data(partition.nodes(root), function(d){return d.name});
Brand new to D3.js and damn what a learning curve....
Below is the graph as it stand when my page is loaded with the original static data. As you can see from the picture, the columns rise sequentially from left to right as they should.
I have the D3 code placed inside a Backbone view. The goal of this program is to change the values on a set interval. When the values change I want to use the transform aspect of D3 to animate the column moving either up or down depending on the number.
However, I'd like them to all move up and down based on a set y axis that applies to each column. It seems, instead, that each column moves the numbers up and down based upon a different y axis, and this changes in each column with each iteration. For example, a column with a value of 115311 could wind up moving down if a value of 188000 is generated, then up again for a value of 112000.
For example, here are the columns after the second iteration of numbers are created (also note, the rect elements that serve as the columns are not being re-drawn. If anyone has any idea why that is happening as well it would be greatly appreciated)
Model
var DataPoint = Backbone.Model.extend({
initialize: function (lbl, ctrct, rtrn) {
this.set({
label: lbl,
contract: ctrct,
annReturn: rtrn
})
},
randomize: function () {
this.set({
contract: (Math.random() * (140000 - 100000 + 1) + 100000).toFixed(2)
});
}
});
Collection
var DataSeries = Backbone.Collection.extend({
model: DataPoint,
fetch: function () {
this.reset();
this.add([
new DataPoint("1/7yrs", "111830.17", "1.63%"),
new DataPoint("2/7yrs", "115311.17", "2.07%"),
new DataPoint("3/7yrs", "118984.65", "2.52%"),
new DataPoint("4/7yrs", "122859.65", "2.98%"),
new DataPoint("5/7yrs", "126947.77", "3.46%"),
new DataPoint("6/7yrs", "131260.74", "3.94%"),
new DataPoint("7/7yrs", "135810.92", "4.44%")
])
},
randomize: function () {
this.each(function (m) {
m.randomize();
});
}
});
View
var BarGraph = Backbone.View.extend({
"el": "#graph",
options: {barDemo: ""},
initialize: function (options) {
_.bindAll(this, "render", "frame");
this.collection.bind("change", this.render);
this.options.barDemo = d3.selectAll($(this.el)).append("svg:svg")
.attr("width", width)
.attr("height", height + 60);
this.collection.fetch();
},
render: function () {
var data = this.collection.models;
var x = d3.scale.linear().domain([0, data.length]).range([0, width]);
var y = d3.scale.linear().domain([0, d3.max(data, function (d) {
console.log(d);
console.log();
return d.attributes.contract
})])
.rangeRound([0, height]);
this.options.barDemo.selectAll("rect")
.data(data)
.enter()
.append("svg:rect")
.attr("x", function (d, i) {
//console.log(x(i));
return x(i);
})
.attr("y", function (d) {
//console.log(height - y(d.attributes.contract));
return height - y(d.attributes.contract);
})
.attr("height", function (d) {
console.log(y(d.attributes.contract));
return y(d.attributes.contract);
})
.attr("width", barWidth)
.attr("fill", "#2d578b");
this.options.barDemo.selectAll("text")
.data(data)
.enter()
.append("svg:text")
.attr("x", function (d, i) {
//console.log(x(i) + barWidth);
return x(i) + barWidth;
})
.attr("y", function (d) {
return height - y(d.attributes.contract);
})
.attr("dx", -barWidth / 2)
.attr("dy", "1.2em")
.attr("text-anchor", "middle")
.text(function(d) {
//console.log(d.contract);
return d.attributes.contract
})
.attr("fill", "white");
this.options.barDemo.selectAll("text.yAxis")
.data(data)
.enter().append("svg:text")
.attr("x", function (d, i) { return x(i) + barWidth; })
.attr("y", height)
.attr("dx", -barWidth / 2)
.attr("dy", "15px")
.attr("text-anchor", "middle")
.attr("style", "font-size: 12; font-family; Helvetica, sans-serif")
.text(function (d) { return d.label; })
.attr("transform", "translate(0, 18)")
.attr("class", "yAxis");
var rect = this.options.barDemo.selectAll("rect").data(data, function (d, i) { return i; });
rect.enter().insert("rect", "text").attr("x", function (d, i) {
return x(i);
}).attr("height", function (d) {
return x(d.attributes.contract);
}).attr("width", barWidth);
rect.transition().duration(1000).attr("height", function (d) {
return x(d.attributes.contract);
}).attr("width", barWidth);
rect.exit().remove();
var text = this.options.barDemo.selectAll("text").data(data, function (d, i) {
return i;
});
text.enter().append("text")
.attr("x", function (d, i) { return x(i) + barWidth; })
.attr("y", function (d) { return height - y(d.attributes.contract); })
.attr("dx", -barWidth / 2)
.attr("dy", "1.2em")
.attr("text-anchor", "middle")
.text(function (d) { return d.attributes.contract })
.attr("fill", "white");
text
.transition()
.duration(1100)
.attr("y", function (d) {
return y(d.attributes.contract);
})
.text(function (d) { return d.attributes.contract; });
},
frame: function () {
//this.chart.append("line").attr("y1", 0).attr("y2", h - 10).style("stroke", "#000");
//this.chart.append("line").attr("x1", 0).attr("x2", w).attr("y1", h - 10).attr("y2", h - 10).style("stroke", "#000");
}
});
Startup code
$(function() {
var dataSeries = new DataSeries();
new BarGraph({
collection: dataSeries
}).render();
setInterval(function () {
dataSeries.randomize();
}, 2000);
});
Below is the code that finally fixed my render function. I needed to adjust the y and height attributes in when the rect was changed and selected, mainly, among a couple other minor changes.
render: function () {
var data = this.collection.models;
var x = d3.scale.linear().domain([0, data.length]).range([0, width]);
var y = d3.scale.linear().domain([100000, 140000]).range([height, 0]);
this.options.barDemo.selectAll("rect")
.data(data)
.enter()
.append("svg:rect")
.attr("x", function (d, i) { return x(i); })
.attr("y", function (d) { return y(d.attributes.contract); })
.attr("height", function (d) { return height - y(d.attributes.contract); })
.attr("width", barWidth)
.attr("fill", "#2d578b");
this.options.barDemo.selectAll("text")
.data(data)
.enter()
.append("svg:text")
.attr("x", function (d, i) { return x(i) + barWidth; })
.attr("y", function (d) { return y(d.attributes.contract); })
.attr("dx", -barWidth / 2)
.attr("dy", "1.2em")
.attr("text-anchor", "middle")
.text(function(d) { return d.attributes.contract; })
.attr("fill", "white");
this.options.barDemo.selectAll("text.yAxis")
.data(data)
.enter().append("svg:text")
.attr("x", function (d, i) { return x(i) + barWidth; })
.attr("y", height)
.attr("dx", -barWidth / 2)
.attr("dy", "15px")
.attr("text-anchor", "middle")
.attr("style", "font-size: 12; font-family; Helvetica, sans-serif")
.text(function (d) { return d.attributes.label; })
.attr("transform", "translate(0, 18)")
.attr("class", "yAxis");
var rect = this.options.barDemo.selectAll("rect").data(data, function (d, i) { return i; });
rect.enter().append("rect", "text").attr("x", function (d, i) {
return x(i);
}).attr("y", function (d) {
return y(d.attributes.contract);
}).attr("height", function (d) {
return height - y(d.attributes.contract);
}).attr("width", barWidth);
rect.transition().duration(1000).attr("y", function(d) {
return y(d.attributes.contract);
}).attr("height", function (d) {
return height - y(d.attributes.contract);
}).attr("width", barWidth);
rect.exit().remove();
var text = this.options.barDemo.selectAll("text").data(data, function (d, i) {
return i;
});
text
.transition()
.duration(1100)
.attr("y", function (d) {
return y(d.attributes.contract);
})
.text(function (d) {
console.log("from transition");
console.log(d);
return d.attributes.contract;
});
},
I am trying to dynamically update my d3 treemap when the data updates. I have two functions, one that I call initially to build the treemap and another to redraw the treemap. When I redraw the treemap, I get a thin black bar on top of the treemap, and the first element in the array that I am graphing goes black. If I click on either of the two black elements. I get the error...
Uncaught TypeError: Cannot read property 'dx' of undefined
So the data being passed to the cell is undefined.
Additionally when I call regraph I have checked and the data has changed, but the graph is unchanged from when I initially built the treemap with the exception of the two black elements.
The code for building the treemap is below. Also the createObj function takes two arrays and creates a Json object.
function drawTreeMap(array1,array2){
console.log("got to drawing");
nestedJson=createObj(array1, array2);
w = 1880 - 80,
h = 900 - 180,
x = d3.scale.linear().range([0, w]),
y = d3.scale.linear().range([0, h]),
color = d3.scale.linear()
.range(['lightgreen', 'darkgreen']) // or use hex values
.domain([computeMin(array2), computeMaxNum(array2)]);
root,
node;
treemap = d3.layout.treemap()
.round(false)
.size([w, h])
.sticky(true)
.padding([10, 0, 0, 0])
.value(function(d) { return d.size; });
svg = d3.select("#body").append("div")
.attr("class", "chart")
.style("width", w + "px")
.style("height", h + "px")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(.5,.5)");
node = root = nestedJson;
var nodes = treemap.nodes(root)
.filter(function(d) { return !d.children; });
var cell = svg.selectAll("g")
.data(nodes)
.enter().append("svg:g")
.attr("class", "cell")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.on("click", function(d) { return zoom(node == d.parent ? root : d.parent); });
cell.append("svg:rect")
.attr("width", function(d) { return d.dx - 1; })
.attr("height", function(d) { return d.dy ; })
.style("fill", function(d) { return color(d.size)});
cell.append("svg:text")
.attr("x", function(d) { return d.dx / 2; })
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return (d.name+",-- "+d.size); })
.style("opacity", function(d) { d.w = this.getComputedTextLength(); return d.dx > d.w ? 1 : 0; });
d3.select(window).on("click", function() { zoom(root); });
d3.select("select").on("change", function() {
treemap.value(this.value == "size" ? size : count).nodes(root);
zoom(node);
});
}
The code for redrawing is below.
function redrawGraphFromJson(data) {
treemap = d3.layout.treemap()
.round(false)
.size([w,h])
.value(function(d) { return d.size; })
.sticky(true);
// Draw the graph
node = root = data;
var nodes = treemap.nodes(root)
.filter(function(d) { return !d.children; });
var cell = svg.selectAll("g")
.data(nodes)
.attr("class", "cell")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
.on("click", function(d) { return zoom(node == d.parent ? root : d.parent); });
cell.append("svg:rect")
.attr("width", function(d) { return d.dx - 1; })
.attr("height", function(d) { return d.dy ; })
.style("fill", function(d) { return color(d.size);});
cell.append("svg:text")
.attr("x", function(d) { return d.dx / 2; })
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return (d.name+",-- "+d.size); })
.style("opacity", function(d) { d.w = this.getComputedTextLength(); return d.dx > d.w ? 1 : 0; });
}
Thank you.
In your redrawing of the graph, you are going to want to .exit() on the initial graph and then .enter() to update the groups with the new data. This will replace the old map with the new.
http://bost.ocks.org/mike/join/ explains it perfectly and has a really good example to look at.
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);});