Alright so I've been working on trying to get my stacked area chart to show the value on mouseover, and I got it to work (miracle) but it only shows one value, no matter where you move the mouse. So when I go into any of the 5 different colors, it only shows one value for the whole color, no matter where the mouse is. Could I get some help fixing this??
Here's my code:
var t = 0;
var n = 40;
var dnsData = getDNS();
var connectData = getConnect();
var SSLData = getSSL();
var sendData = getSend();
var serverBusyData = getServerBusy();
var receiveData = getReceive();
function getDNS() {
var time = 0;
var arr = [];
for(var i=0; i<bardata.length; i++){
var obj = {
time: i,
value: bardata[i].aggs.dns.avg
};
arr.push(obj);
}
t=time;
return arr;
}
function getConnect() {
var time = 0;
var arr = [];
for (var i = 0; i < bardata.length; i++) {
var obj = {
time: i,
value: bardata[i].aggs.con.avg + bardata[i].aggs.dns.avg
};
arr.push(obj);
}
t = time;
return arr;
}
function getSSL() {
var time = 0;
var arr = [];
for (var i = 0; i < bardata.length; i++) {
var obj = {
time: i,
value: bardata[i].aggs.ssl.avg + bardata[i].aggs.con.avg + bardata[i].aggs.dns.avg
};
arr.push(obj);
}
t = time;
return arr;
}
function getSend() {
var time = 0;
var arr = [];
for (var i = 0; i < bardata.length; i++) {
var obj = {
time: i,
value: bardata[i].aggs.snd.avg + bardata[i].aggs.ssl.avg + bardata[i].aggs.con.avg + bardata[i].aggs.dns.avg
};
arr.push(obj);
}
t = time;
return arr;
}
function getServerBusy() {
var time = 0;
var arr = [];
for (var i = 0; i < bardata.length; i++) {
var obj = {
time: i,
value: bardata[i].aggs.srvbsy.avg + bardata[i].aggs.snd.avg + bardata[i].aggs.ssl.avg + bardata[i].aggs.con.avg + bardata[i].aggs.dns.avg
};
arr.push(obj);
}
t = time;
return arr;
}
function getReceive() {
var time = 0;
var arr = [];
for (var i = 0; i < bardata.length; i++) {
var obj = {
time: i,
value: bardata[i].aggs.rcv.avg + bardata[i].aggs.srvbsy.avg + bardata[i].aggs.snd.avg + bardata[i].aggs.ssl.avg + bardata[i].aggs.con.avg + bardata[i].aggs.dns.avg
};
arr.push(obj);
}
t = time;
return arr;
}
var margin = {
top: 10,
right: 10,
bottom: 20,
left: 40
},
width = 760 - margin.left - margin.right,
height = 425 - margin.top - margin.bottom;
var x = d3.scale.linear()
.domain([t, n + 1])
.range([0, width]);
var y = d3.scale.linear()
.domain([0, 2500])
.range([height, 0]);
var line = d3.svg.area()
.interpolate("basis")
.x(function (d, i) {
return x(d.time);
})
.y0(function (d, i) {
return y(d.value);
})
.y1(function(d, i){
return height;
});
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// extra svg to clip the graph and x axis as they transition in and out
var graph = g.append("svg")
.attr("width", width)
.attr("height", height + margin.top + margin.bottom);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var axis = graph.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(x.axis = xAxis);
/****************ADDED THESE TWO CHUNKS************************/
var focus = graph.append("svg")
.style("display", "none");
focus.append("circle")
.attr("class", "y")
.style("fill", "none")
.style("stroke", "black")
.attr("r", 4);
/****************ADDED THESE TWO CHUNKS************************/
g.append("g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var path5 = graph.append("g")
.append("path")
.data([receiveData])
.attr("class", "receiveLine")
.style({'fill':'#005266'})
.append("title")
.text(function(d, i){return d[i].value});
var path4 = graph.append("g")
.append("path")
.data([serverBusyData])
.attr("class", "serverBusyLine")
.style({'fill':'#008FB2'})
.on("mouseover", function(){ focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
var path3 = graph.append("g")
.append("path")
.data([sendData])
.attr("class", "sendLine")
.style({'fill':'#00CCFF'})
.on("mouseover", function(){ focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
var path2 = graph.append("g")
.append("path")
.data([SSLData])
.attr("class", "SSLLine")
.style({'fill':'#4DDBFF'})
.on("mouseover", function(){ focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
var path1 = graph.append("g")
.append("path")
.data([connectData])
.attr("class", "connectLine")
.style({'fill':'#99EBFF'})
.on("mouseover", function(){ focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
var path0 = graph.append("g")
.append("path")
.data([dnsData])
.attr("class", "connectLine")
.style({'fill':'#E6FAFF'})
.on("mouseover", function(){ focus.style("display", null); })
.on("mouseout", function() { focus.style("display", "none"); })
.on("mousemove", mousemove);
tick();
function tick() {
graph.select(".connectLine")
.attr("d", line);
graph.select(".SSLLine")
.attr("d", line);
graph.select(".sendLine")
.attr("d", line);
graph.select(".serverBusyLine")
.attr("d", line);
graph.select(".receiveLine")
.attr("d", line);
}
/****************ADDED THESE TWO CHUNKS************************/
var bisectDate = d3.bisector(function(d){return d.value;}).left;
function mousemove(){
var x0 = x.invert(d3.mouse(this)[0]),
i = bisectDate(line, x0, 1),
d0 = line[i - 1],
d1 = line[i];
}
/****************ADDED THESE TWO CHUNKS************************/
Here's a fiddle: https://jsfiddle.net/5kkv0ct4/
I appreciate any and all help!!
As a quick (but not so elegant) solution, you can listen for a mouse move on the graph SVG and then update the tool tips' text using the inverse (domain value) of the mouse coordinate in relation to the y-scale.
So, call the following code on your graph variable:
graph
.on("mousemove", function() {
d3.selectAll("path").select("title").text(y.invert(d3.mouse(this)[1]));
});
Related
I have a stacked area chart that reads from CSV. But it doesn't render the x axis and the graph correctly.
I have tried to change the x axis values, but didn't help.
below is the sample CSV file.
Currently the view shows the y axis of values, and the drug names on the right, but it doesn't show the actual stacked chart or the date x axis values.
So far return x(d.data.date) = returning NaN.
Thank you so much for your help!
date,drug,market_share
2016-01-01,insulin lispro,.01
2016-01-01,alogliptin,0.001323754341
2016-01-01,sitagliptin,.01
2016-01-01,canagliflozin,0.02842158621
2016-01-01,glimepiride,0.05668845799
2016-01-01,repaglinide,0.0005768749342
2016-01-01,insulin glargine,.01
2016-01-01,metformin,0.4972895171
2016-01-01,mifepristone,.02
2016-01-01,exenatide,.02
2016-01-01,bromocriptine,0.0002109506723
2016-01-01,pioglitazone,0.02324500184
2016-01-01,metformin hydrochloride,0.392074889
2016-02-01,saxagliptin,.02
2016-02-01,pioglitazone,0.02247815103
2016-02-01,exenatide,0.03
2016-02-01,repaglinide,0.0006204220565
2016-02-01,metformin hydrochloride,0.394153624
2016-02-01,sitagliptin,.08
2016-02-01,insulin lispro,.05
2016-02-01,canagliflozin,0.02907988245
2016-02-01,metformin,0.4933502396
2016-02-01,insulin glargine,.02
2016-02-01,bromocriptine,0.0002076549233
2016-02-01,mifepristone,.02
2016-02-01,alogliptin,0.001364306972
2016-02-01,glimepiride,0.05857620484
2016-03-01,canagliflozin,0.02908102306
2016-03-01,bromocriptine,0.000195238081
2016-03-01,metformin,0.4966376769
2016-03-01,alogliptin,0.00133532899
2016-03-01,insulin glargine,.03
2016-03-01,sitagliptin,.04
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="div1"></div>
<div id="div2"></div>
</body>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
var parseDate = d3.timeParse("%Y-%m-%d");
function type2(d, i, columns) {
d.date = parseDate(d.date);
return d;
}
function type(d, i, columns) {
d.date = parseDate(d.date);
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = d[columns[i]] / 100;
return d;
}
function drawGraph(error, data, selector, width, height) {
console.log("DATA "+selector+JSON.stringify(data));
console.log("COL "+selector+"---"+data.columns);
var svg = d3.select(selector).append("svg")
.attr("width", width)
.attr("height", height),
margin = {top: 20, right: 20, bottom: 30, left: 50},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var stack = d3.stack();
var area = d3.area()
.x(function (d, i) {
return x(d.data.date);
})
.y0(function (d) {
return y(d[0]);
})
.y1(function (d) {
return y(d[1]);
});
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var keys = data.columns.slice(1);
x.domain(d3.extent(data, function (d) {
return d.date;
}));
z.domain(keys);
stack.keys(keys);
console.log("Stacked Data "+ selector+"---" + JSON.stringify(stack(data)));
var layer = g.selectAll(".layer")
.data(stack(data))
.enter().append("g")
.attr("class", "layer");
layer.append("path")
.attr("class", "area")
.style("fill", function (d) {
return z(d.key);
})
.attr("d", area);
layer.filter(function (d) {
return d[d.length - 1][1] - d[d.length - 1][0] > 0.01;
})
.append("text")
.attr("x", width - 6)
.attr("y", function (d) {
return y((d[d.length - 1][0] + d[d.length - 1][1]) / 2);
})
.attr("dy", ".35em")
.style("font", "10px sans-serif")
.style("text-anchor", "end")
.text(function (d) {
return d.key;
});
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(10, "%"));
}
d3.csv("market_shares.csv", type2, function (error, data) {
let stackedByDate = {}
let drugSet = new Set();
let defaultDrugMarketShareProp = {};
let newData = []
data.forEach(function (item, index) {
drugSet.add(item.drug);
stackedByDate[item.date] = {};
});
let drugNames = [...drugSet];
drugNames.forEach(function (item, index) {
defaultDrugMarketShareProp[item] = 0;
});
data.forEach(function (item, index) {
stackedByDate[item.date] = Object.assign({}, defaultDrugMarketShareProp);
});
data.forEach(function (item, index) {
stackedByDate[item.date][item.drug] = item.market_share;
});
Object.keys(stackedByDate).forEach(function (key) {
hash = {}
hash['date'] = key;
Object.keys(stackedByDate[key]).forEach(function (innerKey) {
hash[innerKey] = stackedByDate[key][innerKey]
});
newData.push(hash);
});
newData.columns = drugNames;
newData.columns.unshift('date');
drawGraph(error, newData, "#div2", 960, 500);
});
</script>
You correctly parsed the date strings. However, in this function...
Object.keys(stackedByDate).forEach(function (key) {
hash = {}
hash['date'] = key;//<----- HERE
Object.keys(stackedByDate[key]).forEach(function (innerKey) {
hash[innerKey] = stackedByDate[key][innerKey]
});
newData.push(hash);
});
... you're converting the date objects back to strings again.
The quickest solution is just:
hash['date'] = new Date(key);
Here is your code with that change only: https://bl.ocks.org/GerardoFurtado/e9538de82e96cc9e3efb5fc4c7b9b970/5ca6920405243c39b93d0245230b955c37c85a2c
I am converting some v2 code to v4 and I am stuck at this point. where does the x an y functions go for v4? Also is this the right way to create nested values? Thanks
d3.stack()
.offset(d3.stackOffsetSilhouette)
.value(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.value; });
var nest = d3.nest()
.key(function(d) { return d.key; });
var layers = stack(nest.entries(mainVal));
Edited to add full code. Everything has been migrated to v4 but I'm just not sure about that section since layers is returning as an empty array.
<body>
<script src="http://d3js.org/d3.v4.js"></script>
<div class="chart">
</div>
<script>
chart("data.json", "orange");
var datearray = [];
var colorrange = [];
function chart(jsonpath, color) {
if (color == "blue") {
colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"];
}
else if (color == "pink") {
colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"];
}
else if (color == "orange") {
colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"];
}
strokecolor = colorrange[0];
var format = d3.timeFormat("%m/%d/%y");
var margin = {top: 20, right: 40, bottom: 30, left: 30};
var width = document.body.clientWidth - margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
var tooltip = d3.select("body")
.append("div")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "20")
.style("visibility", "hidden")
.style("top", "30px")
.style("left", "55px");
var x = d3.scaleTime()
.range([0, width]);
var y = d3.scaleLinear()
.range([height-10, 0]);
var z = d3.scaleOrdinal()
.range(colorrange);
var xAxis = d3.axisBottom()
.scale(x)
.tickFormat(d3.timeWeeks);
var yAxis = d3.axisLeft()
.scale(y);
var yAxisr = d3.axisRight()
.scale(y);
var stack = d3.stack()
.offset(d3.stackOffsetSilhouette)
.value(function(d) { return d.values; });
var nest = d3.nest()
.key(function(d) { return d.key; });
var area = d3.area()
.curve(d3.curveCardinal)
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var svg = d3.select(".chart").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 + ")");
var graph = d3.json(jsonpath, function(data) {
var parsed = [];
var mainVal = [];
for (var i = 0; i < data.length; i ++) {
var timeData = JSON.parse(data[i]).default.timelineData;
parsed.push(timeData);
}
for (var j = 0; j < parsed.length; j++) {
for (var k = 0; k < parsed[j].length; k++) {
obj = {};
var date = new Date(1000*parsed[j][k].time);
obj.value = parsed[j][k].value[0];
obj.date = date;
obj.key = 'arr' + j;
mainVal.push(obj);
}
}
mainVal.forEach(function(d) {
d.date = d.date;
d.value = +d.value;
});
var layers = nest.entries(mainVal);
x.domain(d3.extent(mainVal, function(d) {
return d.date; }));
y.domain([0, d3.max(mainVal, function(d) { return d.y0 + d.y; })]);
svg.selectAll(".layer")
.data(layers)
.enter().append("path")
.attr("class", "layer")
.attr("d", function(d) {
console.log(d.values);
console.log(area(d.values));
return area(d.values); })
.style("fill", function(d, i) {
return z(i); });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ", 0)")
.call(yAxisr);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".layer")
.attr("opacity", 1)
.on("mouseover", function(d, i) {
svg.selectAll(".layer").transition()
.duration(250)
.attr("opacity", function(d, j) {
return j != i ? 0.6 : 1;
})})
.on("mousemove", function(d, i) {
mousex = d3.mouse(this);
mousex = mousex[0];
var invertedx = x.invert(mousex);
invertedx = invertedx.getMonth() + invertedx.getDate();
var selected = (d.values);
for (var k = 0; k < selected.length; k++) {
datearray[k] = selected[k].date
datearray[k] = datearray[k].getMonth() + datearray[k].getDate();
}
mousedate = datearray.indexOf(invertedx);
pro = d.values[mousedate].value;
d3.select(this)
.classed("hover", true)
.attr("stroke", strokecolor)
.attr("stroke-width", "0.5px"),
tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "visible");
})
.on("mouseout", function(d, i) {
svg.selectAll(".layer")
.transition()
.duration(250)
.attr("opacity", "1");
d3.select(this)
.classed("hover", false)
.attr("stroke-width", "0px"), tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ).style("visibility", "hidden");
})
var vertical = d3.select(".chart")
.append("div")
.attr("class", "remove")
.style("position", "absolute")
.style("z-index", "19")
.style("width", "1px")
.style("height", "380px")
.style("top", "10px")
.style("bottom", "30px")
.style("left", "0px")
.style("background", "#fff");
d3.select(".chart")
.on("mousemove", function(){
mousex = d3.mouse(this);
mousex = mousex[0] + 5;
vertical.style("left", mousex + "px" )})
.on("mouseover", function(){
mousex = d3.mouse(this);
mousex = mousex[0] + 5;
vertical.style("left", mousex + "px")});
});
}
</script>
So, I've been updating a functioning but not elegant D3 chart using https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter9/pie-chart.html
My class looks like this:
function doughnutChart(selector_div) {
"use strict";
var _chart = {};
var _width = 200, _height = 200,
_data = [],
_svg, _bodyG, _pieG,
_radius = 100,
_inner_radius = 50;
_chart.render = function() {
if (!_svg) {
_svg = d3.select(selector_div).append("svg")
.attr("height", _height)
.attr("width", _width);
}
renderBody(_svg);
};
function renderBody(svg) {
if (!_bodyG) {
_bodyG = svg.append("g")
.attr("class", "body");
}
renderDoughnut();
}
function renderDoughnut() {
var pie = d3.layout.pie()
.sort(function (d) {
return d.id;
})
.value(function (d) {
return d.count + d.abnormal;
});
var arc = d3.svg.arc()
.outerRadius(_radius)
.innerRadius(_inner_radius);
if (!_pieG) {
_pieG = _bodyG.append("g")
.attr("class", "pie")
.attr("transform", "translate("
+ _radius
+ ","
+ _radius + ")");
}
renderSlices(pie, arc);
renderLabels(pie, arc);
}
}
function renderSlices(pie, arc) {
var slices = _pieG.selectAll("path.arc")
.data(pie(_data));
slices.enter()
.append("path")
.attr("class", "arc")
.attr("fill", function(d) {
return d.data.visualisation_colour;
});
slices.transition()
.attrTween("d", function(d) {
var currentArc = this.__current__;
if (!currentArc) {
currentArc = {startAngle: 0, endAngle: 0};
}
var interpolate = d3.interpolate(currentArc, d);
this.__current__ = interpolate(1);
return function(t) {
return arc(interpolate(t));
};
});
}
function renderLabels() {
_pieG.append("text")
.attr("dy", ".35em")
.style("text-anchor", "middle")
.attr("class", "inside")
.text(function(d) {
var total = 0;
for (var j = 0; j < _data.length; j++) {
total = total + _data[j].count + _data[j].abnormal;
}
return total;
});
}
_chart.data = function(d) {
if (!arguments.length) {
return _data;
}
_data = d;
return _chart;
};
return _chart;
}
When I use:
var chart = doughnutChart("#chart").data(data);
chart.render()
I get a nice chart rendered. But the update doesn't work:
data = $.map(cell_types, function(key, value) {
return key;
});
chart.render();
The main issue is:
How do I update this chart? I'm not sure how to get updated data into the chart. Calling render() again does not update the data despite the data variable being updated, and I can't seem to pass new data in. The book's example doesn't appear to have this issue, as testing that works without issue.
There is actually a simple error in syntax here:
if (!_pieG) {
_pieG = _bodyG.append("g")
.attr("class", "pie")
.attr("transform", "translate("
+ _radius
+ ","
+ _radius + ")");
renderSlices(pie, arc);
renderLabels(pie, arc);
}
Should actually be:
if (!_pieG) {
_pieG = _bodyG.append("g")
.attr("class", "pie")
.attr("transform", "translate("
+ _radius
+ ","
+ _radius + ")");
}
renderSlices(pie, arc);
renderLabels(pie, arc);
And then it updates correctly.
I have an issue and I really need your help.
I have a realtime graph with a vertical bar that moves with cursor and i want it to show the value of the graph (d.time and d.value) when the cursor points to. I am trying to get inspired of the tooltip from here: http://bl.ocks.org/WillTurman/4631136 adn that is what I have made: http://jsfiddle.net/QBDGB/54/ i have two series of data (data1s and data2s) that is generated randomly and I put the time in which the data is generated in "time" variable as you can see:
now = new Date(Date.now() - duration);
var data1 = initialise();
var data2 = initialise();
//Make stacked data
var data1s = data1;
var data2s = [];
for(var i = 0; i < data1s.length; i++){
data2s.push({
value: data1s[i].value + data2[i].value,
time: data2[i].time
}
)};
function initialise() {
var arr = [];
for (var i = 0; i < n; i++) {
var obj = {
time: Date.now(),
value: Math.floor(Math.random() * 100)
};
arr.push(obj);
}
return arr;
}
When I hover around the graph I want the tooltip show the time and value but it does not recognize it and show "undefined" since I do not know how to pass my datasets (data1s and data2s) so "mouseover function can recognize which data to show! This is how the tooltip functions are made and call from "path1" and "path2".
function mouseover() {
div.transition()
.duration(500)
.style("opacity", 1);
}
function mousemove(d) {
div
.text( d.time+ ", " + d.value)
.style("left", (d3.event.pageX ) + "px")
.style("top", (d3.event.pageY ) + "px");
}
function mouseout() {
div.transition()
.duration(500)
.style("opacity", 1e-6);
}
var path1 = svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.data([data1s])
.attr("class", "line1")
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
var path2 =svg.append("g")
.attr("clip-path", "url(#clip)")
.append("path")
.data([data2s])
.attr("class", "line2")
.on("mouseover", mouseover)
.on("mousemove", mousemove)
.on("mouseout", mouseout);
Do you have any idea of what to do? As you can see in http://bl.ocks.org/WillTurman/4631136 the layers can be recognized by
svg.selectAll(".layer")
.attr("opacity", 1)
.on("mouseover", function(d, i) {
svg.selectAll(".layer").transition()
.duration(250)
.attr("opacity", function(d, j) {
return j != i ? 0.6 : 1;
})})
.on("mousemove", function(d, i) {
mousex = d3.mouse(this);
mousex = mousex[0];
var invertedx = x.invert(mousex);
invertedx = invertedx.getMonth() + invertedx.getDate();
var selected = (d.values);
for (var k = 0; k < selected.length; k++) {
datearray[k] = selected[k].date
datearray[k] = datearray[k].getMonth() + datearray[k].getDate();
}
and the the "mousemove" function can be added for each layer but how can I have this for each of my path?
Thank you,
I've managed to get the following working (pie chart changing dynamically based on a slider value):
var x = function() {
return $("#slider").val();
}
var data = function() {
return [x(), ((100-x())/2), ((100-x())/2)];
}
var w = 100,
h = 100,
r = 50,
color = d3.scale.category20(),
pie = d3.layout.pie().sort(null),
arc = d3.svg.arc().outerRadius(r);
var svg = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
var arcs = svg.selectAll("path")
.data(pie(data()))
.enter().append("svg:path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { this._current = d; });
var redraw = function() {
newdata = data(); // swap the data
arcs = arcs.data(pie(newdata)); // recompute the angles and rebind the data
arcs.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
};
// Store the currently-displayed angles in this._current.
// Then, interpolate from this._current to the new angles.
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
I can't seem to modify it to include dynamic labels (use an object for data rather than an array {'label': 'label1', 'value': value}. How would I modify the above code to add labels?
This should work, keeping the labels and the pie chart as separate entities:
var x = function() {
return $("#slider").val();
}
var data = function() {
return [x(), ((100-x())/2), ((100-x())/2)];
}
var labels = function() {
var label1 = "LABEL 1: " + x();
var label2 = "LABEL 2: " + ((100-x())/2);
var label3 = "LABEL 3: " + ((100-x())/2);
return [label1, label2, label3];
}
var w = 200,
h = 100,
r = 50,
color = d3.scale.category20(),
pie = d3.layout.pie().sort(null),
arc = d3.svg.arc().outerRadius(r);
var svg = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + 50 + "," + h / 2 + ")");
var arcs = svg.selectAll("path")
.data(pie(data()))
.enter().append("svg:path")
.attr("fill", function(d, i) { return color(i); })
.attr("d", arc)
.each(function(d) { this._current = d; });
var label_group = svg.selectAll("text")
.data(labels())
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("x", 60)
.attr("y", function(d, i) { return (i * 20) - 16; });
var redraw = function() {
newdata = data(); // swap the data
arcs = arcs.data(pie(newdata)); // recompute the angles and rebind the data
arcs.transition().duration(750).attrTween("d", arcTween); // redraw the arcs
label_group = label_group.data(labels());
label_group.transition().delay(300).text(function(d) {
return d;
});