exit().remove() is not removing the first bar - d3.js

Whenever the slider is dragged and a new date is selected it does not redraw the first bar, it redraws all the other bars. For example, try date 09/06 and then 09/17. The first bar for id 54042 will not redraw. This is the link to my bl.ocks http://blockbuilder.org/fall16mis/87a39bc00b1b356f78dfd0954f345444
This is the code:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.tooltip {
opacity: 0;
background-color: #ffe047;
position: absolute;
}
.grid line {
stroke: lightgrey;
shape-rendering: crispEdges;
}
.ticks {
font-size: 11px;
}
.track,
.track-inset,
.track-overlay {
stroke-linecap: round;
}
.track {
stroke: #000;
stroke-opacity: 0.3;
stroke-width: 10px;
}
.track-inset {
stroke: #ddd;
stroke-width: 8px;
}
.track-overlay {
pointer-events: stroke;
stroke-width: 50px;
stroke: transparent;
cursor: crosshair;
}
.handle {
fill: #fff;
stroke: #000;
stroke-opacity: 0.5;
stroke-width: 1.25px;
}
.bar:hover{
fill:#0f9fff;
}
.legend{
color:#005ebc;
z-index:0;
}
</style>
</head>
<body>
<div id="slider"></div>
<script>
var json_data = "id,date,start_time,end_time\n\
54042,2017/09/06,5.50,5.53\n\
54042,2017/09/06,7.55,9.19\n\
54042,2017/09/16,11.12,12.28\n\
54042,2017/09/23,13.56,15.03\n\
54042,2017/09/07,16.29,17.33\n\
54042,2017/09/06,19.56,20.53\n\
54042,2017/09/20,21.3,22.14\n\
98765,2017/09/06,5.1,6.51\n\
98765,2017/09/06,11.4,11.53\n\
98765,2017/09/06,12.2,12.42\n\
98765,2017/09/06,12.55,14.2\n\
98765,2017/09/16,21.42,21.59\n\
98765,2017/09/16,22.01,23.13\n\
98765,2017/09/16,23.16,23.51\n\
98765,2017/09/23,13.41,14.03\n\
65299,2017/09/06,7.23,8.21\n\
65299,2017/09/06,9.37,10.23\n\
65299,2017/09/06,11.46,13.29\n\
65299,2017/09/06,18.07,19.57\n\
65299,2017/09/17,14.41,16.22\n\
65299,2017/09/17,21.39,23.39\n\
79408,2017/09/06,9.37,10.17\n\
79408,2017/09/06,11.03,12.08\n\
79408,2017/09/06,13.14,15.53\n\
79408,2017/09/06,16.05,17.48\n\
79408,2017/09/06,19.47,20.23\n\
38338,2017/09/06,8.22,9.28\n\
38338,2017/09/06,11.34,12.17\n\
38338,2017/09/07,12.43,13.35\n\
38338,2017/09/07,14.12,15.48\n\
38338,2017/09/07,16.09,17.23\n\
38338,2017/09/07,18.31,19.19\n\
38338,2017/09/07,21.49,23.26\n\
81757,2017/09/06,6.31,7.41\n\
81757,2017/09/06,8.18,9.39\n\
81757,2017/09/06,10.18,11.23\n\
81757,2017/09/06,13.02,14.04\n\
81757,2017/09/07,15.22,17.23\n\
81757,2017/09/07,20.32,22.01\n\
68077,2017/09/06,11.1,12.45\n\
68077,2017/09/06,15.23,16.54\n\
68077,2017/09/06,17.31,19.05\n\
68077,2017/09/06,20.39,21.3\n\
68077,2017/09/06,21.41,22.37\n\
58381,2017/09/06,16.51,17.55\n\
58381,2017/09/06,19.34,20.55\n\
58381,2017/09/06,21.33,22.51\n\
58381,2017/09/07,14.46,16.15\n\
37500,2017/09/06,8.2,10.18\n\
37500,2017/09/06,11.37,13.34\n\
37500,2017/09/06,19.22,20.16\n\
37500,2017/09/06,21.55,22.09\n\
37500,2017/09/16,14.16,16.26\n\
37500,2017/09/16,16.58,17.48\n\
39146,2017/09/06,19.47,20.21\n\
39146,2017/09/06,20.35,21.29\n\
39146,2017/09/06,22.01,23.25\n\
39146,2017/09/16,8.03,9.56\n\
39146,2017/09/16,10.23,12.52\n\
39146,2017/09/16,13.25,14.28";
window.data = d3.csvParse(json_data, function(d){ return {
id:d.id,
date:d.date,
start_time:+d.start_time,
end_time:+d.end_time}; });
window.minDate = d3.min(window.data,function(d){ return d.date; });
window.maxDate = d3.max(window.data,function(d){ return d.date; });
window.names = window.data.map(function(d){
return d.id; });
var parseDate = d3.timeParse("%Y/%m/%d");
var displayDate = d3.timeFormat("%m/%d");
var forChartDate = d3.timeFormat("%Y/%m/%d");
var height = 500;
var width = 800;
var margin = {left: 50, right: 20, bottom: 0, top: 70};
var tooltip = d3.select("body").append("div").attr("class", "tooltip")
var svg = d3.select("body").append("svg").attr("height","1000px").attr("width","100%");
var chartGroup = svg.append("g").attr("transform","translate("+margin.left+","+(margin.top+10)+")");
var legend = svg.append("g").attr("transform","translate("+margin.left+","+(margin.top+10)+")");
var chartDate = window.minDate;
var displaySlider = function(data){
window.x = d3.scaleLinear()
.domain([0, 24])
.range([0, width]);
window.y = d3.scaleBand()
.domain(window.names)
.rangeRound([height, 0])
.paddingInner(0.3);
function make_y_gridlines() {
return d3.axisLeft(y)
};
function make_x_gridlines() {
return d3.axisBottom(x)
};
chartGroup.append("g")
.attr("class","axis y")
.call(d3.axisLeft(y))
chartGroup.append("g")
.attr("class","axis x")
.call(d3.axisBottom(x))
.attr("transform","translate(0,"+height+")")
.call(d3.axisBottom(x)
.ticks(24));
chartGroup.append("g")
.attr("class", "grid")
.call(make_y_gridlines()
.tickSize(-width)
.tickFormat("")
);
chartGroup.append("g")
.attr("class", "grid")
.call(make_x_gridlines()
.tickSize(height)
.tickFormat("")
)
var newData = data.filter(function(d){
return d.date==chartDate;
})
displayBar(newData);
var x1 = d3.scaleTime()
.range([0, width])
.domain([parseDate(minDate), parseDate(maxDate)])
.clamp(true);
var slider = svg.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + margin.left + ",30)");
slider.append("line")
.attr("class", "track")
.attr("x1", x1.range()[0])
.attr("x2", x1.range()[1])
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-inset")
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "track-overlay")
.call(d3.drag()
.on("start.interrupt", function() { slider.interrupt(); })
.on("drag end", function() { sliderFunc(x1.invert(d3.event.x)); }));
slider.insert("g", ".track-overlay")
.attr("class", "ticks")
.attr("transform", "translate(0," + 10 + ")")
.selectAll("text")
.data(x1.ticks(15))
.enter()
.append("text")
.attr("x", x1)
.attr("y", 10)
.attr("text-anchor", "middle")
.text(function(d) { return displayDate(d); });
var label = slider.append("text")
.attr("class", "label")
.attr("text-anchor", "middle")
.text(minDate)
.attr("transform", "translate(0," + (-10) + ")");
var handle = slider.insert("circle", ".track-overlay")
.attr("class", "handle")
.attr("r", 7);
function sliderFunc(h) {
handle.attr("cx", x1(h));
label.attr("x", x1(h))
.text(displayDate(h));
chartDate = forChartDate(h);
console.log(chartDate);
newData = data.filter(function(d){
return d.date==chartDate;
})
//displayText(newData);
displayBar(newData);
}
};
var displayBar = function(data){
var bars = chartGroup.selectAll(".bar")
.data(data, function(d){
console.log(d);
return d;
});
bars.exit().remove();
bar_enter = bars.enter().append("rect")
bar_enter.attr("class", "bar")
.attr("x", function(d) {
console.log(d.start_time);
return window.x(d.start_time); })
.attr("y", function(d) { return window.y(d.id); })
.attr("height", window.y.bandwidth())
.attr("fill", "green")
.transition()
.duration(600)
.attr("width", function(d) { return window.x(d.end_time-d.start_time); });
bar_enter.on('mousemove', function(d,i){
tooltip.style("opacity","1")
.style("left",(d3.event.pageX+10)+"px")
.style("top",d3.event.pageY+"px");
tooltip.html(" Start Time:"+d.start_time+" End Time:"+d.end_time);
})
bar_enter.on('mouseout', function(){
tooltip.style("opacity","0")
});
};
displaySlider(window.data);
</script>
</body>

You cannot use the whole object in the key function:
var bars = chartGroup.selectAll(".bar")
.data(data, function(d){
return d;
});
The API explains it:
key function may be specified to control which datum is assigned to which element, replacing the default join-by-index, by computing a string identifier for each datum and element. (emphasis mine)
Therefore, instead of using the whole object, use a property (like the id):
var bars = chartGroup.selectAll(".bar")
.data(data, function(d){
return d.id;
});
Here is the updated bl.ocks: https://bl.ocks.org/GerardoFurtado/57d014aa5124bdbe5774e1457816ff43/07a233d46aa3ae91bcffb8682de9ed8376c99b9a

Related

d3 line graph using csv

I have a data in csv like this:
date,partner,units
2012-05-01,team1,34.12
2012-04-30,team1,45.56
2012-04-27,team2,67.89
2012-04-26,team1,78.54
2012-04-25,team2,89.23
2012-04-24,team2,99.23
2012-04-23,team2,101.34
I want to plot two lines (one for team1, one for team2 using this data), but I am just getting a scatterplot using the following complete d3 code, is my filtering wrong?
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
#line1 {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
#line2 {
fill: none;
stroke: red;
stroke-width: 2px;
}
</style>
<input type="button" onclick="hideLine()">
<input type="button" onclick="showLine()">
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%Y-%m-%d");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the 1st line
var valueline = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.units); });
// define the 2nd line
var valueline2 = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.units); });
var svg = d3.select("body").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 + ")");
// Get the data
d3.csv("data1.csv", function(error, data) {
if (error) throw error;
// format the data
data.forEach(function(d) {
d.date = parseTime(d.date);
d.units = +d.units;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
m = d3.max(data, function(d) {
var m = d.units;
return m;
});
console.log("Max:", m);
y.domain([0,m]);
// Add the valueline path.
svg.append("path")
.data([data])
.filter(function(d) { return d.partner == 'team1'; })
.attr("id", "line1")
.attr("d", valueline);
console.log("DATA", data)
svg.selectAll(".point")
.data(data)
.enter()
.append("circle")
.attr("class", "point")
.attr("cx", function (d, i) {
return x(d.date);
})
.attr("cy", function(d) {
return y(d.units);
})
.attr("r", 4)
.on("mouseover", function(d) { console.log(d.units) });
// Add the valueline2 path.
svg.append("path")
.data([data])
.filter(function(d) { return d.partner == 'team2'; })
.attr("id", "line2")
.style("stroke", "red")
.attr("d", valueline2)
.on("mouseover", function(d) {console.log(d)});
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
});
function hideLine() {
console.log("Hideline");
d3.select("#line2").attr("style", "opacity:0");
}
function showLine() {
console.log("ShowLine");
d3.select("#line2").attr("style", "opacity:1");
}
</script>
</body>
Yes, your filter is wrong. You are wrapping your data in another [] which means the filter is only operating on the outer array.
Do this instead:
svg.append("path")
.datum(data.filter(function(d) { return d.partner == 'team1'; }))
.attr("id", "line1")
.attr("d", valueline);
Working example here.

D3.js How to hide/show line when click select options?

I tried to use D3.js to draw lines when you click on different checkbox. It will get data of that option. Here is an example I used D3 multi-series line chart with tooltips and legend. I have got the specific data object that is corresponding the checkbox I choose. Howevery, I don't know how to draw it on svg. Please help me and I will appreciate you so much.
I also find a website "www.cotrino.com/starpaths/" that shows the final effect I want to implement.
My D3 effect
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<script src="http://d3js.org/d3.v4.js"></script>
<body>
<svg width="1000" height="500"></svg>
<div id="disease_list"></div>
</body>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 80, bottom: 30, left: 50},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//make a clip path for the graph
var clip = svg.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height);
var parseTime = d3.timeParse("%Y-%m");
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]);
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { console.log(d.date); return x(d.date); })
.y(function(d) { console.log(d.date); return y(d.count); });
var color = d3.scaleOrdinal(d3.schemeCategory20);
d3.csv("./top10highestNormalize.csv", type, function(error, data) {
if (error) throw error;
var diseases = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d) {
return {date: d.date, count: d[id]};
})
};
});
console.log(diseases);
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(diseases, function(c) { return d3.min(c.values, function(d) { return d.count; }); }),
d3.max(diseases, function(c) { return d3.max(c.values, function(d) { return d.count; }); })
]);
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))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("fill", "#000")
.text("Count");
/*
var disease = g.selectAll(".disease")
.data(diseases)
.enter().append("g")
.attr("class", "disease");
*/
// Create the shape selectors
var selector = d3.select("#disease_list").append("select");
labels = selector.selectAll("option")
.data(diseases)
.enter()
.append("option")
.attr("value",function(d,i) {return i;})
.text(function(d) {return d.id;});
var menu = d3.select("#disease_list select")
.on("change", redraw);
// var series = menu.property("value");
//console.log(series);
// all the meat goes in the redraw function
function redraw() {
console.log("redraw start");
// get value from menu selection
// the option values are set in HTML and correspond
//to the [type] value we used to nest the data
var series = menu.property("value");
console.log(series);
// only retrieve data from the selected series, using the nest we just created
var adata = diseases[series];
console.log(adata);
}
});
function type(d, _, columns) {
d.date = parseTime(d.date);
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
return d;
}
</script>
top10highestNormalize.csv
date,disseminated sclerosis,sclerosis,gestural tics,venereal disease,bite,cot death,venereal disease,cardiovascular disease,diseases vascular,pruritis,pus,cystic fibrosis,fibroses
2010-04,0,0,0,0,0,0,0,0,0,0,0,0,0
2010-05,0,0,0.06898023,0.068783069,0.085790885,0.065761258,0.068783069,0,0,0.001204094,0.023051592,0,0
2010-06,0.076923077,0.076923077,0.190584554,0.199972867,0.201072386,0.171789373,0.199972867,0.071428571,0.071428571,0.004816376,0.031284303,0.2,0.2
2010-07,0.230769231,0.230769231,0.221590101,0.224664225,0.225201072,0.235167977,0.224664225,0.214285714,0.285714286,0.00602047,0.038419319,0,0
2010-08,0.538461538,0.538461538,0.174797326,0.182471849,0.174262735,0.192041935,0.182471849,0.071428571,0.071428571,0.003612282,0.023051592,0,0
2010-09,0.230769231,0.230769231,0.287725786,0.277845611,0.252010724,0.259471051,0.277845611,0,0,0.004214329,0.046652031,0,0
2010-10,0.076923077,0.076923077,0.295406059,0.299416633,0.285969616,0.265665952,0.299416633,0,0.071428571,0.007224564,0.03402854,0.066666667,0.066666667
2010-11,0.153846154,0.153846154,0.284027877,0.279337946,0.261840929,0.276149631,0.279337946,0,0,0.006622517,0.050493963,0,0
2010-12,0.153846154,0.153846154,0.271511876,0.237552571,0.213583557,0.237312366,0.237552571,0.142857143,0.142857143,0.004214329,0.035126235,0,0
2011-01,0.076923077,0.076923077,0.306642014,0.312440646,0.28150134,0.305694544,0.312440646,0.142857143,0.142857143,0.006622517,0.046103183,0,0.066666667
2011-02,0.076923077,0.076923077,0.288721377,0.262243929,0.219839142,0.25899452,0.262243929,0.142857143,0.142857143,0.007224564,0.038968167,0,0.066666667
2011-03,0.076923077,0.076923077,0.271654103,0.255324922,0.253798034,0.266857279,0.255324922,0.071428571,0.071428571,0.007224564,0.051591658,0,0
2011-04,0.461538462,0.461538462,0.291423695,0.252068919,0.235031278,0.284250655,0.252068919,0,0,0.009030704,0.045005488,0,0
2011-05,0.153846154,0.153846154,0.448158157,0.380681047,0.351206434,0.439123183,0.380681047,0,0,0.011438892,0.079582876,0.333333333,0.4
2011-06,0.153846154,0.153846154,0.498079932,0.437661104,0.391420912,0.424827258,0.437661104,0.142857143,0.142857143,0.009632751,0.063117453,0,0.066666667
2011-07,0,0,0.410467928,0.424094424,0.419124218,0.379080295,0.424094424,0,0.071428571,0.009030704,0.061470911,1,1
2011-08,0.076923077,0.076923077,0.268382876,0.262922263,0.238605898,0.267810341,0.262922263,0.214285714,0.214285714,0.002408188,0.038968167,0,0
2011-09,0.230769231,0.230769231,0.510027023,0.469949803,0.470956211,0.444841553,0.469949803,0,0,0.014449127,0.075740944,0.133333333,0.2
2011-10,0.076923077,0.076923077,0.462380885,0.434540768,0.431635389,0.417679295,0.434540768,0.142857143,0.142857143,0.006622517,0.073545554,0,0.066666667
2011-11,0.153846154,0.153846154,0.519698478,0.457061457,0.415549598,0.443888492,0.457061457,0.142857143,0.142857143,0.01384708,0.06805708,0.2,0.2
2011-12,1,1,0.382449154,0.35002035,0.319928508,0.315701692,0.35002035,0,0,0.002408188,0.060373216,0,0
2012-01,0.461538462,0.461538462,0.492390841,0.45312712,0.409294013,0.45389564,0.45312712,0.571428571,0.571428571,0.007224564,0.060373216,0,0
2012-02,0.076923077,0.076923077,0.382875836,0.375932709,0.350312779,0.369073147,0.375932709,0.071428571,0.071428571,0.003612282,0.049945115,0.066666667,0.066666667
2012-03,0.923076923,1,1,0.922127255,1,0.871098404,0.922127255,0.5,0.5,0.01384708,0.171789243,0,0.066666667
2012-04,0.230769231,0.307692308,0.699331532,0.676977344,0.63360143,0.645699309,0.676977344,0.142857143,0.142857143,0.012040939,0.092206367,0.133333333,0.133333333
2012-05,0.846153846,0.846153846,0.801735173,0.752408086,0.776586238,0.7436264,0.752408086,0.785714286,0.785714286,0.016857315,0.131723381,0.466666667,0.466666667
2012-06,0.384615385,0.461538462,0.730479306,0.732193732,0.625558534,0.657850846,0.732193732,0,0,0.011438892,0.118002195,0.6,0.666666667
2012-07,0.384615385,0.384615385,0.751386716,0.738434405,0.71849866,0.714081487,0.738434405,0.285714286,0.285714286,0.009030704,0.126783754,0.2,0.2
2012-08,0.384615385,0.461538462,0.700327123,0.643467643,0.619302949,0.646890636,0.643467643,0.285714286,0.285714286,0.012642986,0.150933041,0.2,0.266666667
2012-09,0.076923077,0.230769231,0.72137676,0.701804368,0.63538874,0.70455087,0.701804368,0.214285714,0.214285714,0.011438892,0.130076839,0.066666667,0.066666667
2012-10,0.230769231,0.230769231,0.846252311,0.863112196,0.796246649,0.825827972,0.863112196,0.071428571,0.071428571,0.036724865,0.127881449,0.333333333,0.333333333
2012-11,0.692307692,0.692307692,0.895605177,1,0.798927614,0.909935668,1,0.214285714,0.357142857,0.012642986,0.143798024,0,0.133333333
2012-12,0.923076923,1,0.795903854,0.803283137,0.683646113,0.827257565,0.803283137,0.142857143,0.142857143,0.008428657,0.104829857,0.6,0.6
2013-01,0.230769231,0.384615385,0.92106386,0.964862298,0.848078642,0.944007624,0.964862298,0.285714286,0.357142857,0.015653221,0.146542261,0.533333333,0.733333333
2013-02,0.153846154,0.307692308,0.830322856,0.872880206,0.798927614,0.755777937,0.872880206,0.142857143,0.142857143,0.010234798,0.110318332,0,0.066666667
2013-03,0.230769231,0.230769231,0.927037406,0.944105277,0.885612154,0.953061711,0.944105277,0.142857143,0.142857143,0.009632751,0.131174533,0,0.133333333
2013-04,0.384615385,0.384615385,0.796046082,0.775471442,0.671134942,0.715749345,0.775471442,0,0,0.012040939,0.12349067,0.133333333,0.133333333
2013-05,0.923076923,1,0.824633765,0.844254511,0.742627346,0.843697879,0.844254511,0.142857143,0.142857143,0.015653221,0.149286498,0,0
2013-06,0.307692308,0.307692308,0.884369222,0.949667616,0.865951743,1,0.949667616,0.071428571,0.071428571,0.020469597,0.135016465,0.466666667,0.466666667
2013-07,0.461538462,0.461538462,0.864172948,0.935829602,0.843610366,0.939480581,0.935829602,0.071428571,0.071428571,0.015051174,0.128979144,0.066666667,0.2
2013-08,0.153846154,0.153846154,0.670886076,0.738163071,0.753351206,0.821300929,0.738163071,0.071428571,0.214285714,0.012642986,0.098243688,0,0
2013-09,0.230769231,0.230769231,0.876262267,0.861484195,0.744414656,0.996426019,0.861484195,0,0,0.024081878,0.144895719,0.066666667,0.066666667
2013-10,0.615384615,0.615384615,0.917508178,0.885361552,0.806970509,0.841315225,0.885361552,0.642857143,0.642857143,0.030704395,0.115806806,0.2,0.4
2013-11,0,0.076923077,0.857061584,0.903540904,0.791778374,0.845127472,0.903540904,0.5,0.5,0.012642986,0.093852909,0,0
2013-12,0.230769231,0.230769231,0.704878396,0.719169719,0.584450402,0.81915654,0.719169719,0.285714286,0.5,0.015653221,0.108122942,0,0
2014-01,0.461538462,0.461538462,0.900014223,0.856328856,0.717605004,0.98903979,0.856328856,0.357142857,0.5,0.030102348,0.137211855,0,0.066666667
2014-02,0,0,0.707865169,0.703296703,0.63717605,0.796997856,0.703296703,1,1,0.012642986,0.097145993,0,0
2014-03,0.230769231,0.230769231,0.815531219,0.800434134,0.7256479,0.786275911,0.800434134,0.714285714,0.714285714,0.009632751,0.099341383,0.533333333,0.6
2014-04,0.153846154,0.153846154,0.756506898,0.790259124,0.615728329,0.778174887,0.790259124,0,0,0.011438892,0.12349067,0,0
2014-05,0.461538462,0.461538462,0.85990613,0.767331434,0.705987489,0.78008101,0.767331434,0.142857143,0.285714286,0.014449127,0.13611416,0.066666667,0.133333333
2014-06,0.076923077,0.153846154,0.670886076,0.713064713,0.615728329,0.735763641,0.713064713,0.285714286,0.285714286,0.010836845,0.102634468,0,0
2014-07,0.076923077,0.076923077,0.672592803,0.801655135,0.621090259,0.680009531,0.801655135,0.071428571,0.071428571,0.007224564,0.103183315,0,0
2014-08,0.384615385,0.461538462,0.487270659,0.58377425,0.486148347,0.575887539,0.58377425,0.071428571,0.071428571,0.005418423,0.079582876,0,0.133333333
2014-09,0,0.076923077,0.715545442,0.678062678,0.669347632,0.705980462,0.678062678,0,0,0.01384708,0.103183315,0,0.066666667
2014-10,0.230769231,0.307692308,0.742995306,0.723511057,0.630920465,0.679294734,0.723511057,0,0,0.016857315,0.1064764,0,0
2014-11,0,0,0.672735031,0.623388957,0.583556747,0.64927329,0.623388957,0,0,0.004816376,0.115806806,0.066666667,0.066666667
2014-12,0.307692308,0.384615385,0.591096572,0.55704789,0.478999106,0.491303312,0.55704789,0.285714286,0.428571429,0.003010235,0.074643249,0,0
2015-01,0.076923077,0.153846154,0.659223439,0.561117894,0.531724754,0.605432452,0.561117894,0.071428571,0.071428571,0.007224564,0.094401756,0.133333333,0.133333333
2015-02,0.230769231,0.307692308,0.61840421,0.564780898,0.512064343,0.585656421,0.564780898,0.071428571,0.071428571,0.007224564,0.096597146,0,0
2015-03,0,0,0.770302944,0.677927011,0.599642538,0.675482487,0.677927011,0.071428571,0.071428571,0.009632751,0.111964874,0.066666667,0.2
2015-04,0.076923077,0.076923077,0.706016214,0.61687695,0.731903485,0.563497736,0.61687695,0.071428571,0.071428571,0.008428657,0.097145993,0,0
2015-05,0,0.076923077,0.655383303,0.614027947,0.55406613,0.6154396,0.614027947,0.071428571,0.071428571,0.012642986,0.099341383,0,0
2015-06,0,0.076923077,0.564357844,0.540632207,0.527256479,0.598284489,0.540632207,0.142857143,0.142857143,0.00602047,0.091657519,0,0
2015-07,0.076923077,0.076923077,0.486417295,0.525301859,0.511170688,0.566356922,0.525301859,0,0,0.015653221,0.08726674,0.066666667,0.066666667
2015-08,0.230769231,0.230769231,0.408476746,0.386379053,0.320822163,0.465094115,0.386379053,0,0,0.003010235,0.056531284,0,0
2015-09,0.538461538,0.538461538,0.870999858,0.792701126,0.747095621,0.883964737,0.792701126,0,0,0.013245033,0.156421515,0,0
2015-10,0.153846154,0.153846154,0.469492249,0.435490435,0.320822163,0.51227067,0.435490435,0,0,0.174593618,0.221734358,0,0
2015-11,0.153846154,0.153846154,0.322998151,0.309455976,0.273458445,0.346676197,0.309455976,0,0,0.462974112,0.481888035,0.133333333,0.133333333
2015-12,0.076923077,0.076923077,0.342767743,0.309320309,0.27971403,0.384798666,0.309320309,0,0,0.464780253,0.482436883,0.066666667,0.066666667
2016-01,0.307692308,0.384615385,0.415872564,0.349477683,0.358355675,0.442458899,0.349477683,0,0,0.559903672,0.581229418,0.066666667,0.066666667
2016-02,0,0,0.445455838,0.403744404,0.316353887,0.457469621,0.403744404,0,0,0.54846478,0.568605928,0.066666667,0.066666667
2016-03,0,0,0.471198976,0.400352734,0.317247542,0.508220157,0.400352734,0.142857143,0.142857143,0.604455148,0.628430296,0,0
2016-04,0,0,0.582989617,0.570343237,0.575513852,0.603764594,0.570343237,0.214285714,0.214285714,1,1,0,0
You need to create your line variable:
var myLine = svg.append("path");
And then, inside redraw(), changing it according to the option selected:
myLine.datum(adata.values)
.attr("d", line);
Here is a demo plunker: https://plnkr.co/edit/YjGO9TLDBXj13JQuO5bm?p=preview
PS: I changed your x-scale range:
var x = d3.scaleTime().range([margin.left, width]);
And also added a call to redraw() when the code runs for the first time.

How to add seperate lines to map

On a d3 v4 chart, I have arcs drawn for multiple coordinates. All is well there. Now I would like to draw the lines from a json request. Any new lines would be drawn, whilst existing lines would remain. As I understand, each line would require its own transition....
If I understand correctly, the iteration of coordinates begins at
line.attr("d", function(c) {...}
Which iterates over each set of coordinates, and then internally groups them so that they are all 'triggered' at the same time, as the one event. Any explanation on this gratefully received.
Plunker: https://plnkr.co/edit/Ax4Tby47lFlryzVWCHi2?p=preview
Kev
Not sure I'm reading your question correctly, but it sounds like you want your animations to start one after another. This can be accomplished with a .delay:
.attr("stroke-dasharray", "0, 1000") //<-- hide the line
.transition()
.delay(function(d, i) {
return 5000 * i; //<-- i is the index of the line, so stagger the animation start by index * duration
})
.duration(5000)
.attrTween("stroke-dasharray", function() {
var len = this.getTotalLength();
return function(t) {
return (d3.interpolateString("0," + len, len + ",0"))(t)
};
})
Full Code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<style>
.stroke {
fill: none;
stroke: #000;
stroke-width: 3px;
}
.fill{
fill: #fff;
}
.graticule {
fill: none;
stroke: #777;
stroke-width: 0.5px;
stroke-opacity: 0.5;
}
/* the color of land in countries */
.land {
fill: #222;
}
/* the color of borders */
.boundary {
fill: none;
stroke: #fff;
stroke-width: 0.5px;
}
</style>
<svg width="800" height="600"></svg>
<script src="//d3js.org/d3.v4.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var projection = d3.geoMercator()
.scale((width - 3) / (2 * Math.PI))
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
var graticule = d3.geoGraticule();
svg.append("defs").append("path")
.datum({
type: "Sphere"
})
.attr("id", "sphere")
.attr("d", path);
svg.append("use")
.attr("class", "stroke")
.attr("xlink:href", "#sphere");
svg.append("use")
.attr("class", "fill")
.attr("xlink:href", "#sphere");
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
d3.json("https://rawgit.com/mbostock/topojson/master/examples/world-50m.json", function(error, world) {
if (error) throw error;
d3.json("https://jsonblob.com/api/5806b733e4b0bcac9f817223", function(coord){
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
svg.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) {
return a !== b;
}))
.attr("class", "boundary")
.attr("d", path);
var line = svg.selectAll(".paths")
.data(coord)
.enter()
.append("path");
line.attr("d", function(c) {
console.log(c);
var d = {
source: projection(c.source),
target: projection(c.destination)
};
var dx = d.target[0] - d.source[0],
dy = d.target[1] - d.source[1],
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source[0] + "," + d.source[1] + "A" + dr + "," + dr +
" 0 0,1 " + d.target[0] + "," + d.target[1];
})
.style("stroke", "red") // color of the arc line
.style("stroke-width", 5)
.style("fill", "none")
.attr("stroke-dasharray", "0, 1000")
.transition()
.delay(function(d, i) {
return 5000 * i;
})
.duration(5000)
.attrTween("stroke-dasharray", function() {
var len = this.getTotalLength();
return function(t) {
return (d3.interpolateString("0," + len, len + ",0"))(t)
};
})
.on('end', function(d) {
var c = projection(d.destination);
svg.append('circle')
.attr('cx', c[0])
.attr('cy', c[1])
.attr('r', 0)
.style('fill', 'white') // color of the cirle
.style('fill-opacity', '0.5')
.transition()
.duration(2000)
.attr('r', 50)
.on('end', function(d) {
d3.select(this)
.transition()
.duration(2000)
.attr('r', 10);
});
});
});
});
</script>
</body>
</html>

d3.js brush with multiline chart

I'm making a multi-line chart and using a brush to select time periods. It's broadly based on Mike Bostock's example at http://bl.ocks.org/mbostock/1667367
My chart is at http://lowercasen.com/dev/d3/general/piezobrush.html
My problem is in selecting the multiple lines in my 'focus' area to apply the brush to. I've nested the data based on a key, so the data is within a function. Because the function that calls my brush is outside that function, it can't access the data and I'm getting a TypeError: undefined is not an object (evaluating 'data.length')
Here's the code that nests the data:
dataNest.forEach(function(d, i) {
focus.append("path")
.attr("class", "line")
.attr("id", d.key.replace(/\s+/g, '')) //the replace stuff is getting rid of spaces
.attr("d", levelFocus(d.values));
context.append("path")
.attr("class", "line")
.attr("id", d.key.replace(/\s+/g, '')) //the replace stuff is getting rid of spaces
.attr("d", levelContext(d.values));
and at the bottom I have the function for the brush:
function brushed() {
xFocus.domain(brush.empty() ? xContext.domain() : brush.extent());
focus.selectAll(".line").attr("d", levelFocus(d.values));
focus.select(".x.axis").call(xAxisFocus);
}
It works fine for the x axis (if I comment out the line where I'm trying to select the lines) but I don't know how to select the lines correctly.
Apologies for any garbled syntax or confusing language, my coding skills are basic at best.
Any help is greatly appreciated, I've searched for hours for a solution.
Here's the full code as requested by Lars
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Multiline with brush</title>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="d3/tooltip.js"></script>
<link href="styles/evidentlySoCharts.css" rel="stylesheet">
<meta name="viewport" content="initial-scale=1">
<style>
svg {
font: 10px sans-serif;
}
path {
stroke-width: 1;
fill: none;
}
#Stream1, #Nebo1D {
stroke: #009390;
}
#Stream1Legend, #Nebo1DLegend {
fill: #009390;
}
#Stream2, #Nebo2D {
stroke: #8dc63f;
}
#Stream2Legend, #Nebo2DLegend {
fill: #8dc63f;
}
#Stream3, #Nebo1S {
stroke: #132d46;
}
#Stream3Legend, #Nebo1SLegend {
fill: #132d46;
}
#Stream4, #Nebo2S {
stroke: #aaa813;
}
#Stream4Legend, #Nebo2SLegend {
fill: #aaa813;
}
#Stream5, #Nebo3 {
stroke: #619dd4;
}
#Stream5Legend, #Nebo3Legend {
fill: #619dd4;
}
.pn1d, .pn2d {
fill: none;
clip-path: url(#clip);
}
.pn1d {
stroke: #009390;
}
.pn2d {
stroke: #1b4164;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
stroke-width: 1px;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script>
var marginFocus = {top: 10, right: 10, bottom: 250, left: 40},
marginContext = {top: 430, right: 10, bottom: 170, left: 40},
width = 960 - marginFocus.left - marginFocus.right,
heightFocus = 650 - marginFocus.top - marginFocus.bottom,
heightContext = 650 - marginContext.top - marginContext.bottom;
legendOffset = 550;
var parseDate = d3.time.format("%d/%m/%y %H:%M").parse;
var xFocus = d3.time.scale().range([0, width]),
xContext = d3.time.scale().range([0, width]),
yFocus = d3.scale.linear().range([heightFocus, 0]),
yContext = d3.scale.linear().range([heightContext, 0]);
var xAxisFocus = d3.svg.axis().scale(xFocus).orient("bottom"),
xAxisContext = d3.svg.axis().scale(xContext).orient("bottom"),
yAxisFocus = d3.svg.axis().scale(yFocus).orient("left");
var levelFocus = d3.svg.line()
.interpolate("linear")
.x(function(d) { return xFocus(d.date); })
.y(function(d) { return yFocus(d.level); });
var levelContext = d3.svg.line()
.interpolate("linear")
.x(function(d) { return xContext(d.date); })
.y(function(d) { return yContext(d.level); });
var svg = d3.select("body").append("svg")
.attr("width", width + marginFocus.left + marginFocus.right)
.attr("height", heightFocus + marginFocus.top + marginFocus.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", heightFocus);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + marginFocus.left + "," + marginFocus.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + marginContext.left + "," + marginContext.top + ")");
d3.csv("data/PiezoNeboNestSimple.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.level = +d.level;
});
xFocus.domain(d3.extent(data.map(function(d) { return d.date; })));
yFocus.domain([d3.min(data.map(function(d) { return d.level; })) -2,0]);
xContext.domain(xFocus.domain());
yContext.domain(yFocus.domain());
// Nest the entries by piezo
var dataNest = d3.nest()
.key(function(d) {return d.piezo;})
.entries(data);
legendSpace = width/dataNest.length; // spacing for legend // ******
var brush = d3.svg.brush()
.x(xContext)
.on("brush", brushed);
focus.selectAll("g").data(dataNest)
.enter()
.append("g")
.attr("class", "line")
.attr("id", function(d) { return d.key.replace(/\s+/g, '') }) //the replace stuff is getting rid of spaces
.append("path")
.attr("d", function(d) { return levelFocus(d.values); });
context.selectAll("g").data(dataNest)
.enter()
.append("g")
.attr("class", "line")
.attr("id", function(d) { return d.key.replace(/\s+/g, '') }) //the replace stuff is getting rid of spaces
.append("path")
.attr("d", function(d) { return levelContext(d.values); });
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + heightFocus + ")")
.call(xAxisFocus);
focus.append("g")
.attr("class", "y axis")
.call(yAxisFocus);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + heightContext + ")")
.call(xAxisContext);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", heightContext + 7);
function brushed() {
xFocus.domain(brush.empty() ? xContext.domain() : brush.extent());
focus.selectAll(".line").attr("d", levelFocus(dataNest.values));
focus.select(".x.axis").call(xAxisFocus);
}
});
</script>
</body>
</html>
It mostly boils down to two things as far as I can see. First, the elements you're selecting to be updated are the g and not the path elements and second, you need to reference the data bound to the elements in order to set d. Both are easily fixed and the brushed function looks something like this.
function brushed() {
xFocus.domain(brush.empty() ? xContext.domain() : brush.extent());
focus.selectAll("path").attr("d", function(d) { return levelFocus(d.values); });
focus.select(".x.axis").call(xAxisFocus);
}
Complete demo here. Note that some bits are still missing, in particular the clip path to restrict the lines to the chart area. This can be copied and pasted directly from the example you've referenced though.

D3.JS - how do I add gridlines to my pie chart

I have extended the pie-chart example at:
with pies that vary in radius depending on a percentage. I would like to add gridlines (circles) every 20 percent, but I can't figure out how.
here is the updated csv:
age,population,percent
<5,2704659,67
5-13,4499890,38
14-17,2159981,91
18-24,3853788,49
25-44,14106543,71
45-64,8819342,88
=65,612463,64
and here is the updated code with pie-parts of different radius:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
background: #333;
}
.arc path {
stroke: #fff;
stroke-width: 2px;
}
.arc grid {
stroke: #fff;
stroke-width: 1;
stroke-dasharray: 5,5;
}
.arc text {
fill:#fff;
font-size:12px;
font-weight:bold;
}
.arc line {
stroke: #fff;
}
</style>
<body>
<script src="d3.js"></script>
<script>
var width = 960,
height = 500,
radius = Math.min(width, height) / 2 - 10;
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
var arc = d3.svg.arc()
.outerRadius(function(d) { return 50 + (radius - 50) * d.data.percent / 100; })
.innerRadius(20);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d.population; });
var grid = d3.svg.area.radial()
.radius(150);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.population = +d.population;
d.percent = d.percent;
});
var g = svg.selectAll(".arc")
.data(pie(data))
.enter().append("g")
.attr("class", "arc");
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.age); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text(function(d) { return d.data.age; });
});
</script>
First set the number of ticks:
var numTicks = 5; // Each tick is 20%
Then create the data to create the gridlines:
var sdat = [];
for (i=0; i<=numTicks; i++) {
sdat[i] = (radius/numTicks) * i;
}
And then you can use a function to create the radial gridlines, and you can call it from within the d3.csv block:
addCircleAxes = function() {
var circleAxes, i;
svg.selectAll('.circle-ticks').remove();
circleAxes = svg.selectAll('.circle-ticks')
.data(sdat)
.enter().append('svg:g')
.attr("class", "circle-ticks");
// radial tick lines
circleAxes.append("svg:circle")
.attr("r", String)
.attr("class", "circle")
.style("stroke", "#CCC")
.style("opacity", 0.5)
.style("fill", "none");
// Labels for each circle
circleAxes.append("svg:text")
.attr("text-anchor", "center")
.attr("dy", function(d) { return d - 5 })
.style("fill", "#fff")
.text(function(d,i) { return i * (100/numTicks) });
};
An example is here: http://bl.ocks.org/3994129
(Borrowed from: http://kreese.net/blog/2012/08/26/d3-js-creating-a-polar-area-diagram-radial-bar-chart/)

Resources