Simple collision example, using g groups?
Hi all, i test this examples:
1- http://bl.ocks.org/mbostock/3231298 - this example use a invisible circle for generate the force.
2- http://bl.ocks.org/mbostock/1747543 - this example use a central circle for force layout
This examples always use a circles.
My idea is use pie charts with collision force but i can't find a simple example of this.
I use this construction:
chart_vars_object.svg = d3.select(".canvas_svg").append("svg")
.attr({
"width": general_vars_object.width,
"height": general_vars_object.height
})
var nodes = chart_vars_object.svg.selectAll(".pie")
.data(chart_vars_object.json_init_data)
.enter()
.append("g")
.attr("class", function(d) {
return "pie pie_id_" + d.hash_chart_id
})
.attr("width", chart_vars_object.general_radius * 2)
.attr("height", chart_vars_object.general_radius * 2)
.attr("hash_link", function(d) {
return d.hash_link
})
.call(chart_vars_object.force.drag);
chart_vars_object.force.on("tick", function(e) {
chart_vars_object.svg.selectAll(".pie")
.attr("transform", function(d, i) {
return "translate(" + Math.round(d.x) + "," + Math.round(d.y) + ")";
});
});
//CREATE ARC GROUP's
var g = nodes.selectAll(".arc")
.data(function(d) {
return chart_vars_object.pie(d.hash_taggeds);
})
.enter().append("g")
.attr("class", "arc_group")
.attr("hash_type", function(d, i) {
if (i == 0 ) {
return "article";
}
if (i == 1 ) {
return "image";
}
if (i == 2 ) {
return "video";
}
})
.on("click", function() {
d3.select(this).select('.arc')
alert('Abro el Has Tag');
})
.on("mouseover", function() {
d3.select(this).select('.arc')
.classed("active", true )
})
.on("mouseout", function() {
d3.select(this).select('.arc')
.classed("active", false)
});
//CREATE PATHS WITH ARC
chart_vars_object.path = g.append("path")
.attr("class","arc")
.style({'cursor': 'pointer', 'opacity': '0.9'})
chart_vars_object.path.transition()
.duration(20)
.attr("fill", function(d) {
return chart_vars_object.color(d.data.hash_taggeds_name);
})
.attr("d", chart_vars_object.arc)
.each(function(d) {
this._current = d;
});
Any suggest?
Related
I was using d3 version 4.5 earlier in my project for d3 pack circles. Now I have used latest version and got difference in pack layout symmetry. Before Image and After Image
Here is my code in both cases. Want to have same symmetry as it was in earlier version. Is there any new way to get this symmetry in latest version of d3.
var diameter = 250;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var bubble = d3.pack(data)
.size([diameter, 185])
.padding(1.4);
var svg = d3.select("#trending-topic")
.append("svg")
.attr("width", diameter)
.attr("height", 185)
.attr("class", "bubble");
var nodes = d3.hierarchy(data)
.sum(function(d) {
return d.Count;
});
var format = d3.format(",d");
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
var node = svg.selectAll(".node")
.data(bubble(nodes)
.descendants())
.enter()
.filter(function(d) {
return !d.children;
})
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.attr("title", function(d) {
return d.Name;
});
/* transparent circle with border */
node.append("circle")
.attr("r", function(d) {
return d.r;
//return d.data.Radius;
})
.style("fill", function(d, i) {
return d.data.fillColor;
})
.on("click", function(d) {
getTopicArticle(d.data.tid);
});
node.append("text")
.each(function(d) {
var arr = d.data.Name.split(" ");
for(i = 0; i < arr.length; i++) {
if(arr[i].length > 10) {
arr[i] = arr[i].substring(0, 7) + '...';
}
d3.select(this)
.append("tspan")
.text(arr[i])
.attr("dy", i ? "1.2em" : 0)
.attr("x", 0)
.attr("text-anchor", "middle")
.attr("class", "tspan" + i)
.attr("fill", "white")
.attr("font-size", function(d) {
return d.r / 3;
})
.on("click", function(d) {
getTopicArticle(d.data.tid);
});
}
d3.select(this)
.append("title")
.text(d.data.Name);
});
d3.select(self.frameElement)
.style("height", 185 + "px");
d3.selectAll(".node")
.on("mouseover", function(d) {
var circle = d3.select(this)
.select("circle");
var text = d3.select(this)
.selectAll("tspan");
text.transition()
.duration(500)
.attr("font-size", function(d) {
return d.r;
});
})
.on("mousemove", function(d) {
})
.on("mouseleave", function(d) {
var circle = d3.select(this)
.select("circle");
circle.transition()
.duration(500)
.attr("r", function(d) {
return d.r;
});
var text = d3.select(this)
.selectAll("tspan");
text.transition()
.duration(500)
.attr("font-size", function(d) {
return d.r / 3;
});
});
You were right, it's this commit in d3-hierarchy between 1.1.1 and 1.1.2, which in turn was introduced between d3 4.5.0 and 4.5.1. It addresses this issue, about packing circles more condensely.
I recommend just accepting the changes, but if you really don't want to change the layout, import d3-hierarchy 1.1.1 *after* d3` to override the hierarchy module. This returns the same layout as the older version of d3:
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.1/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-hierarchy/1.1.1/d3-hierarchy.min.js"></script>
The downside is that by making the package versions out of sync, you might break something now or in the future, so it's not a long term sustainable approach.
To test use the following snippet and comment/uncomment the script imports.
var diameter = 250;
var color = d3.scaleOrdinal(d3.schemeCategory20);
var data = {
children: [{
Name: 'Economy',
fillColor: 'grey',
Count: 12
},
{
Name: 'Politics',
fillColor: 'grey',
Count: 10
},
{
Name: 'ESG',
fillColor: 'lightblue',
Count: 5
},
{
Name: 'Tech',
fillColor: 'lightblue',
Count: 5
},
{
Name: 'Leisure',
fillColor: 'pink',
Count: 4
},
{
Name: 'Coronavirus',
fillColor: 'pink',
Count: 4
},
{
Name: 'Blockchain',
fillColor: 'darkblue',
Count: 2,
},
{
Name: 'Sports',
fillColor: 'darkblue',
Count: 2,
},
{
Name: 'Coding',
fillColor: 'purple',
Count: 1,
},
{
Name: 'India',
fillColor: 'purple',
Count: 1,
}
],
};
var bubble = d3.pack(data).size([diameter, 185]).padding(1.4);
var svg = d3.select("#trending-topic")
.append("svg")
.attr("width", diameter)
.attr("height", 185)
.attr("class", "bubble");
var nodes = d3.hierarchy(data)
.sum(function(d) {
return d.Count;
});
var format = d3.format(",d");
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
var node = svg.selectAll(".node")
.data(bubble(nodes).descendants())
.enter()
.filter(function(d) {
return !d.children
})
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
.attr("title", function(d) {
return d.Name;
});
/* transparent circle with border */
node.append("circle").attr("r", function(d) {
return d.r;
//return d.data.Radius;
}).style("fill", function(d, i) {
return d.data.fillColor;
});
node.append("text").each(function(d) {
var arr = d.data.Name.split(" ");
for (i = 0; i < arr.length; i++) {
if (arr[i].length > 10) {
arr[i] = arr[i].substring(0, 7) + '...';
}
d3.select(this).append("tspan")
.text(arr[i])
.attr("dy", i ? "1.2em" : 0)
.attr("x", 0)
.attr("text-anchor", "middle")
.attr("class", "tspan" + i).attr("fill", "white").attr("font-size", function(d) {
return d.r / 3;
});
}
d3.select(this).append("title").text(d.data.Name);
});
d3.select(self.frameElement).style("height", 185 + "px");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.1/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-hierarchy/1.1.1/d3-hierarchy.min.js"></script>
<div id="trending-topic"></div>
I am beginner in d3 v3. I created multiple donut charts. When I move my mouse over a slice, I get the tooltip that appears. But I would also like the slice to grow a little bit.
I have already tried several codes but I can't get there. I wonder if the problem may be related to d3 tip
this is my js file :
//Source : http://bl.ocks.org/mbostock/1305337
var m = 15,
r = 80,
z = d3.scale.ordinal()
.range(["#50FFC5", "#54E868", "#54CCE8", "#6395FF"]);
var pie = d3.layout.pie()
.value(function (d) {
return +d.count;
})
.sort(function (a, b) {
return b.count - a.count;
});
var arc = d3.svg.arc()
.innerRadius(r / 2)
.outerRadius(r);
var radius = d3.scale.linear()
.range([10, r])
var tip = d3.tip()
.attr('class', 'd3-tip')
.html(function (d) {
return d.data.genre + ": " + d.data.count;
})
.direction('s');
d3.csv("../CSV/genreHameau.csv", function (error, hameau) {
if (error) throw error;
var datas = d3.nest()
.key(function (d) {
return d.origine;
})
.entries(hameau);
datas.forEach(function (d) {
totalOrigin = d3.sum(d.values, function (d) {
return +d.count;
})
d.values.forEach(function (dd) {
dd.totalOrigin = totalOrigin
})
})
datas.sort(function (a, b) {
return d3.descending(a.values[0].totalOrigin, b.values[0].totalOrigin)
})
// définir le radius / rayon des arcs (rendre fonction de 'count')
var max = d3.max(datas, function (d) {
return d.values[0].totalOrigin
})
var min = d3.min(datas, function (d) {
return d.values[0].totalOrigin
})
radius.domain([min, max])
arc
.innerRadius(function (d) {
return radius(d.data.totalOrigin) / 2
})
.outerRadius(function (d) {
return radius(d.data.totalOrigin)
})
function size(d) {
return radius(d.values[0].totalOrigin) + m
}
var div = d3.select("body").selectAll("div")
.data(datas)
.enter().append("div") // http://code.google.com/p/chromium/issues/detail?id=98951
.style("display", "inline-block")
.style("width", function (d) {
return 2 * size(d) + "px"
})
.style("height", function (d) {
return 2 * size(d) + "px"
})
.style("min-width", "80px")
.style("min-height", "80px")
div.append("span")
.attr("class", "nomhameau")
.text(function (d) {
return d.key;
})
.append("span")
.attr("class", "nombrehameau")
.text(function (d) {
return " (" + d.values[0].totalOrigin + ")"
});
var svg = div.append("svg")
//.attr("width", (r + m) * 2)
//.attr("height", (r + m) * 2)
.attr("width", function (d) {
return 2 * size(d)
})
.attr("height", function (d) {
return 2 * size(d)
})
.append("g")
.attr("transform", function (d) {
return "translate (" + size(d) + "," + size(d) + ")"
});
svg.call(tip);
var g = svg.selectAll("g")
.data(function (d) {
return pie(d.values);
})
.enter().append("g")
.on("mouseover", tip.show)
.on("mouseout", tip.hide)
g.append("path")
.attr("d", arc)
.style("fill", function (d) {
return z(d.data.genre);
})
.append("title")
});
Thank you for your help
I would do it this way:
Just like you created the arc, create a new one with a greater radius, either inner, outer or both, something like:
var arcHighlight = d3.svg.arc()
.innerRadius(r / 2)
.outerRadius(r*1.1);
Then you add mouseover and mouseout events to the slice and modify the slice doing something like:
// Add a colored arc path, with a mouseover title showing the count.
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return z(d.data.carrier); })
// new code
.on('mouseover', function(d) {
d3.select(this)
.transition()
.attr('d', arcHighlight(d));
})
.on('mouseout', function(d) {
d3.select(this)
.transition()
.attr('d', arc(d));
})
.append("title")
.text(function(d) { return d.data.carrier + ": " + d.data.count; });
The transition is optional, but it looks fancier ;)
I'm doing a visual project to show natural disaster in 1900-2018 using d3. I want add an interactive action that one can choose the first year and last year to show.
Originally I create the picture as the following:
d3.csv("output.csv", rowConventer, function (data) {
dataset = data;
var xScale = d3.scaleBand()
.domain(d3.range(dataset.length))
.range([padding, width - padding])
.paddingInner(0.05);
var yScale = d3.scaleLinear()
.domain([0,
d3.max(dataset, function (d) {
return d.AllNaturalDisasters;
})])
.range([height - padding, padding])
.nice();
stack = d3.stack().keys(["Drought", "Earthquake", "ExtremeTemperature", "ExtremeWeather", "Flood", "Impact", "Landslide", "MassMovementDry", "VolcanicActivity", "Wildfire"]);
series = stack(dataset);
gr = svg.append("g");
groups = gr.selectAll("g")
.data(series)
.enter()
.append("g")
.style("fill", function(d, i) {
return colors(i);
})
.attr("class", "groups");
rects = groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return yScale(d[1]);
})
.attr("height", function(d) {
return yScale(d[0]) - yScale(d[1]);
})
.attr("width", xScale.bandwidth())
.append("title")
.text(function (d) {
var rect = this.parentNode;// the rectangle, parent of the title
var g = rect.parentNode;// the g, parent of the rect.
return d.data.Year + ", " + d3.select(g).datum().key + "," + (d[1]-d[0]);
});
d3.select("button")
.on("click", choosePeriod);
I have simplified some code to make my question simple. At the last row, I add an event listener to achieve what I described above. And the update function is choosePeriod. Now it is as following:
function choosePeriod() {
firstYear = parseInt(document.getElementById("FirstYear").value);
lastYear = parseInt(document.getElementById("LastYear").value);
d3.csv("output.csv", rowConventer, function (newdata) {
dataset = newdata;
series=stack(dataset);
groups.data(series);
groups.selectAll("rect")
.data(function (d) {
return d;
})
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScales(i);
})
.attr("y", function(d) {
return yScales(d[1]);
})
.attr("height", function(d) {
return yScales(d[0]) - yScales(d[1]);
})
.attr("width", xScales.bandwidth())
.append("title")
.text(function (d) {
var rect = this.parentNode;// the rectangle, parent of the title
var g = rect.parentNode;// the g, parent of the rect.
return d.data.Year + ", " + d3.select(g).datum().key + "," + (d[1]-d[0]);
});
groups.selectAll("rect")
.data(function (d) {
return d;
})
.exit()
.remove();
})
}
The change of dataset is achieved by rowConventer, which is not important in this question. Now the functionchoosePeriod is not running as envisioned! Theenter and the exit and update are all not work well! The whole picture is a mess! What I want is, for instance, if I input the firstYear=1900 and the lastYear=2000, then the picture should be updated with the period 1900-2000 to show. How can I achieve it?
I am unfamiliar the arrangement of the entire structure, I mean, at some place using d3.select() by class or id instead of label is better, right?
It looks like you've dealt with the enter and the exit selections. The only bit you're missing is the update selection, which will deal with the rectangles that already exist and don't need adding or removing. To do this copy your update pattern but just remove the enter().append() bit, e.g.:
groups.selectAll("rect")
.data(function (d) {
return d;
})
.attr("x", function(d, i) {
return xScales(i);
})
.attr("y", function(d) {
return yScales(d[1]);
})
.attr("height", function(d) {
return yScales(d[0]) - yScales(d[1]);
})
.attr("width", xScales.bandwidth())
.append("title")
.text(function (d) {
var rect = this.parentNode;// the rectangle, parent of the title
var g = rect.parentNode;// the g, parent of the rect.
return d.data.Year + ", " + d3.select(g).datum().key + "," + (d[1]-d[0]);
})
I have prototype code I am working with here:
jsfiddle
The example shows how to add a segment when new data is added but not how to remove it again when the data changes [back]. I am fairly new to d3 and don't quite get the exit() function yet...
if you reverse the initial and second dataset you will see that the grapes segment is never removed. Thanks in advance!
any help would be great!
The update code: (my final chart needs to update on a timer when data changes)
var arcs = arc_grp.selectAll("path")
.data(donut(data));
arcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { return this.current = d; });
var sliceLabel = label_group.selectAll("text")
.data(donut(data));
sliceLabel.enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) { return "translate(" + (arc.centroid(d)) +
")"; })
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) { return 1e-6; }
else { return 1; }
})
.text(function(d) { return d.data.label; });
};
To remove elements without data, you have to use exit(), which...
Returns the exit selection: existing DOM elements in the selection for which no new datum was found.
So, inside your updateChart function, you need an exit selection for both paths and texts:
var newArcs = arcs.data(donut(dataset));
newArcs.exit().remove();
var newSlices = sliceLabel.data(donut(dataset));
newSlices.exit().remove();
Here is your updated code:
// Setup all the constants
var duration = 500;
var width = 500
var height = 300
var radius = Math.floor(Math.min(width / 2, height / 2) * 0.9);
var colors = ["#d62728", "#ff9900", "#004963", "#3497D3"];
// Test Data
var d2 = [{
label: 'apples',
value: 20
}, {
label: 'oranges',
value: 50
}, {
label: 'pears',
value: 100
}];
var d1 = [{
label: 'apples',
value: 100
}, {
label: 'oranges',
value: 20
}, {
label: 'pears',
value: 20
}, {
label: 'grapes',
value: 20
}];
// Set the initial data
var data = d1
var updateChart = function(dataset) {
var newArcs = arcs.data(donut(dataset));
newArcs.exit().remove();
newArcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
newArcs.transition()
.duration(duration)
.attrTween("d", arcTween);
var newSlices = sliceLabel.data(donut(dataset));
newSlices.exit().remove();
newSlices.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
});
sliceLabel.data(donut(dataset)).enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
})
.text(function(d) {
return d.data.label;
});
};
var color = d3.scale.category20();
var donut = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.innerRadius(radius * .4)
.outerRadius(radius);
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var arc_grp = svg.append("g")
.attr("class", "arcGrp")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var label_group = svg.append("g")
.attr("class", "lblGroup")
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
var arcs = arc_grp.selectAll("path")
.data(donut(data));
arcs.enter()
.append("path")
.attr("stroke", "white")
.attr("stroke-width", 0.8)
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
.each(function(d) {
return this.current = d;
});
var sliceLabel = label_group.selectAll("text")
.data(donut(data));
sliceLabel.enter()
.append("text")
.attr("class", "arcLabel")
.attr("transform", function(d) {
return "translate(" + (arc.centroid(d)) + ")";
})
.attr("text-anchor", "middle")
.style("fill-opacity", function(d) {
if (d.value === 0) {
return 1e-6;
} else {
return 1;
}
})
.text(function(d) {
return d.data.label;
});
// Update the data
setInterval(function(model) {
return updateChart(d2);
}, 2000);
// Tween Function
var arcTween = function(a) {
var i = d3.interpolate(this.current, a);
this.current = i(0);
return function(t) {
return arc(i(t));
};
};
.arcLabel {
font: 10px sans-serif;
fill: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I am able to populate a stacked bar chart first time, but my requirement is to update the stacked bar chart with new data on button click. On button click, i m making call to backend and getting the data, Could you please guide me as how to update the stacked bar char chart. My problem is passing the new data to bar chart.
d3.json("http://myhost/ITLabourEffortChart/effort/effort",function(error, data){
color.domain(d3.keys(data.effort[0]).filter(function(key) {
return key !== "qName"; }));
data.effort.forEach(function(d) {
var y0 = 0;
d.effortHr = color.domain().map(function(name) {
return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.effortHr[d.effortHr.length - 1].y1;
});
x.domain(data.effort.map(function(d) { return d.qName; }));
y.domain([0, d3.max(data.effort, function(d) {
return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("FTE");
var state = svg.selectAll(".layer")
.data(data.effort)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + x(d.qName) + ",0)"; });
rect = state.selectAll("rect")
.attr("id", "barchart")
.data(function(d) {
return d.effortHr; })
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); });
On Update i am calling below method
function redraw() {
d3.json("http://localhost:8080/ITLabourEffortChart/effort/effort/YrReports",function(error, data){
color.domain(d3.keys(data.effort[0]).filter(function(key) {
return key !== "qName"; }));
data.effort.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {name: name, y0: y0, y1: y0 += +d[name]}; });
d.total = d.ages[d.ages.length - 1].y1;
});
var updatebar = svg.selectAll("#barchart");
// Update…
updatebar
.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.transition()
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.style("fill", function(d) { return color(d.name); }
.attr("x", function(d) {
return x(d.x); })
);
});
.attr("x", function(d) {
return x(d.x); })
);
});
To update your data you will just need to select the svg elements again and rebind the data. In your example you are already selecting the #barchart, now you just need to rebind the data. And you can do that in the same way you did it when you first created the svg Elements. So something like this should do the trick:
var updatebar = svg.selectAll("#barchart");
.data(newdata)
.transition()
.duration(500)
... (etc.)
Here you can find a more detailed explaination:
http://chimera.labs.oreilly.com/books/1230000000345/ch09.html#_updating_data
Update:
Ok, unfortunately I cannot use Fiddle so I just post my working code here. As far as I could see you have a problem with your selectAll, because there is no element called .effort. Here is the updated code for your redraw-function:
function redraw() {
var effort = [];
var obj = {
pfte: "20",
efte: "50",
qName: "Q1"
};
var obj2 = {
pfte: "10",
efte: "13",
qName: "Q2"
};
effort[0] = obj;
effort[1] = obj2;
var newDataSet = new Object();
newDataSet.effort = effort;
color.domain(d3.keys(newDataSet.effort[0]).filter(function (key) {
return key !== "qName";
}));
effortDataSet = newDataSet.effort;
effortDataSet.forEach(function (d) {
var y0 = 0;
d.effortHr = color.domain().map(function (name) {
return { name: name, y0: y0, y1: y0 += +d[name] };
});
d.total = d.effortHr[d.effortHr.length - 1].y1;
});
state = svg.selectAll(".g")
.data(effortDataSet)
.attr("class", "g")
.attr("transform", function (d) { return "translate(" + x(d.qName) + ",0)"; });
state = state.selectAll("rect")
.data(function (d) {
return d.effortHr;
})
.attr("width", x.rangeBand())
.attr("y", function (d) {
return y(d.y1);
})
.attr("height", function (d) {
//console.log(y(d.y0) - y(d.y1));
return y(d.y0) - y(d.y1);
})
.style("fill", function (d) { return color(d.name); });
}