d3 multiline chart animations - javascript
I am building multiline charts - I am keen to improve this so it can handle multiple line data sets - and also animation/update features.
would be looking to separate the setup and update methods
http://jsfiddle.net/NYEaX/1408/
var selector = methods.el["selector"];
var padding = 5;
var svg = d3.select(selector).append("svg:svg")
.attr("class", "chart")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("class", "linechart")
.attr("transform", "translate(30,30)");
var margin = {
top: 35,
right: 35,
bottom: 35,
left: 35
},
width = h - margin.left - margin.right,
height = w - margin.top - margin.bottom;
var formatDate = d3.time.format("%d-%b-%y");
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0])
.domain([0, 315])
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.close);
});
//mash arrays together to return max and min vals
var d = data[0].concat(data[1]);
x.domain(d3.extent(d, function(d) {
return d.date;
}));
y.domain(d3.extent(d, function(d) {
return d.close;
}));
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("Price ($)");
svg.append("path")
.datum(data[0])
.attr("class", "line")
.attr('stroke', 'red')
.attr("d", line);
svg.append("path")
.datum(data[1])
.attr("class", "line")
.attr('stroke', 'blue')
.attr("d", line);
function type(d) {
d.date = formatDate.parse(d.date);
d.close = +d.close;
return d;
}
Related
How to dynamically create append svg line using d3js?
I am attempting to draw markers to a zoomable / pannable graph. My current version is available at https://jsfiddle.net/n2enn80o/ raw = {"l2":[-58,-44,-31,-21,-17,-16,-16,-15,-15,-14,-13,-12,-11,-10,-9,-7,-5,-3,-1,2,4,8,11,14,17,20,24,28,32,37,41,46,51,56,60,64,69,73,77,82,84,87,87,87,87,85,82,77,73,66,60,53,46,39,33,26,20,13,8,4,-1,-6,-10,-14,-16,-19,-22,-25,-26,-27,-28,-29,-30,-31,-31,-32,-32,-32,-32,-31,-31,-31,-31,-31,-30,-31,-30,-30,-30,-30,-29,-28,-27,-27,-27,-27,-27,-26,-26,-26,-26,-26,-26,-26,-26,-25,-25,-25,-25,-25,-25,-25,-25,-25,-24,-24,-24,-25,-25,-24,-23,-23,-23,-23,-23,-23,-23,-23,-23,-22,-22,-22,-22,-22,-22,-21,-21,-21,-21,-20,-20,-20,-20,-19,-18,-16,-13,-10,-6,-2,1,4,7,9,12,14,16,16,16,15,13,9,6,2,-1,-4,-7,-10,-11,-12,-14,-15,-16,-17,-18,-19,-19,-20,-20,-20,-20,-20,-20,-20,-24,-32,-45,-54,-50,-25,25,97,182,252,270,220,126,35,-25,-53,-65,-71,-70,-60,-46,-32,-22,-18,-16,-16,-15,-14,-13,-13,-12,-11,-10,-8,-7,-5,-3,-1,1,4,7,10,14,17,21,24,28,32,36,40,45,50,55,59,64,69,72,77,81,84,87,88,88,87,84,82,77,73,67,61,54,47,39,33,26,20,14,9,4,-1,-6,-9,-13,-16,-19,-22,-24,-26,-28,-29,-29,-30,-30,-31,-32,-32,-32,-31,-31,-32,-31,-31,-31,-31,-30,-30,-29,-29,-29,-29,-28,-28,-27,-27,-28,-28,-26,-26,-26,-26,-26,-26,-26,-26,-25,-25,-25,-25,-25,-25,-26,-26,-25,-24,-24,-24,-24,-24,-24,-24,-23,-23,-23,-23,-23,-23,-23,-24,-22,-22,-22,-22,-22,-22,-22,-21,-22,-20,-20,-20,-20,-20,-19,-18,-16,-13,-10,-8,-3,0,4,7,9,11,13,15,16,16,16,14,11,6,2,-2,-4,-7,-9,-11,-12,-14,-16,-17,-18,-19,-19,-19,-19,-20,-20,-20,-20,-20,-20,-23,-30,-43,-54,-53,-30,17,88,172,245,271,230,138,45,-19,-50,-63,-70,-70,-61,-48,-34,-23,-18,-17,-16,-16,-15,-14,-13,-13,-11,-10,-8,-7,-5,-3,-1,1,4,7,9,13,16,20,23,27,31,36,40,44,49,54,59,63,68,73,76,81,83,86,88,87,87,85,82,78,73,68,62,55,48,40,33,27,20,14,9,4,0,-5,-9,-13,-16,-19,-22,-24,-26,-28,-29,-29,-29,-30,-31,-31,-32,-31,-32,-32,-32,-32], "startts":1357714800000,"marker1":[50,100]}; var data =[]; for(var i=0;i<raw.l2.length;i++) { var marker = Number.NaN; for(var j=0;j<raw.marker1.length;j++) { if(i==raw.marker1[j]) { marker=i; break; } } var obj = {"date":raw.startts+(1/244.140625*1000)*i, "value":raw.l2[i]/75,"marker":marker} data.push(obj) } margin = { top: 20, right: 20, bottom: 20, left: 45 }; width = 1800 - margin.left - margin.right; height = 600 - margin.top - margin.bottom; var x = d3.time.scale() .domain(d3.extent(data, function (d) { return d.date; })) .range([0, width]); var y = d3.scale.linear() .domain(d3.extent(data, function (d) { return d.value; })) .range([height, 0]); var line = d3.svg.line() .x(function (d) { return x(d.date); }) .y(function (d) { return y(d.value); }); var zoom = d3.behavior.zoom() .x(x) .y(y) .on("zoom", zoomed); svg = d3.select('#chart') .append("svg:svg") .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .append("svg:g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .call(zoom); svg.append("svg:rect") .attr("width", width) .attr("height", height) .attr("class", "plot"); var make_x_axis = function () { return d3.svg.axis() .scale(x) .orient("bottom") .ticks(5); }; var make_y_axis = function () { return d3.svg.axis() .scale(y) .orient("left") .ticks(5); }; var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(5); svg.append("svg:g") .attr("class", "x axis") .attr("transform", "translate(0, " + height + ")") .call(xAxis); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(5); svg.append("g") .attr("class", "y axis") .call(yAxis); var marker = svg.append("line") .attr("x1",100) .attr("y1", 0) .attr("x2",100) .attr("y2", height) .attr("class", "marker") svg.append("text") .attr("x", 100) .attr("y", 0) .attr("dy", ".35em") .attr("dx", 5) .attr("class", "marker-text") .text(function(d) { return "test"; }); svg.append("g") .attr("class", "x grid") .attr("transform", "translate(0," + height + ")") .call(make_x_axis() .tickSize(-height, 0, 0) .tickFormat("")); svg.append("g") .attr("class", "y grid") .call(make_y_axis() .tickSize(-width, 0, 0) .tickFormat("")); 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 chartBody = svg.append("g") .attr("clip-path", "url(#clip)"); chartBody.append("svg:path") .datum(data) .attr("class", "line") .attr("d", line); function zoomed() { console.log(d3.event.translate); console.log(d3.event.scale); svg.select(".x.axis").call(xAxis); svg.select(".y.axis").call(yAxis); svg.select(".x.grid") .call(make_x_axis() .tickSize(-height, 0, 0) .tickFormat("")); svg.select(".y.grid") .call(make_y_axis() .tickSize(-width, 0, 0) .tickFormat("")); svg.select(".line") .attr("class", "line") .attr("d", line); } I have been able to add static lines to my d3 plot in the example, what i am trying to achieve is to make the marker line along with the text "test" to be moving along with the graph. What I have tried is to use a d3.svg.line() with a line generator, but it ends up not getting the reference to d. Another version I have attempted is to create a function as below but that does not get the reference of d, and draws the line at zero. Here i attempted to draw the line if and only if the marker tag was present in the data. By default when populating the data i have ensured that it has Number.NaN when i dont need to draw the marker. var marker = svg.append("line") .attr("x1",function(d) { if(d.marker!=Number.NaN) return x(d.date); }) .attr("y1", 0) .attr("x2",function(d) { if(d.marker!=Number.NaN) return x(d.date); }) .attr("y2", height) .attr("class", "marker")
I have made a couple of small changes, as per my reply to your question. Inside your zoom handler zoomed() you need to change the x1 & x2 attributes of marker, and the x attr of markerText. This function fires on each zoom event to move stuff around or redraw stuff according to your zoom, and your axes. raw = {"l2":[-58,-44,-31,-21,-17,-16,-16,-15,-15,-14,-13,-12,-11,-10,-9,-7,-5,-3,-1,2,4,8,11,14,17,20,24,28,32,37,41,46,51,56,60,64,69,73,77,82,84,87,87,87,87,85,82,77,73,66,60,53,46,39,33,26,20,13,8,4,-1,-6,-10,-14,-16,-19,-22,-25,-26,-27,-28,-29,-30,-31,-31,-32,-32,-32,-32,-31,-31,-31,-31,-31,-30,-31,-30,-30,-30,-30,-29,-28,-27,-27,-27,-27,-27,-26,-26,-26,-26,-26,-26,-26,-26,-25,-25,-25,-25,-25,-25,-25,-25,-25,-24,-24,-24,-25,-25,-24,-23,-23,-23,-23,-23,-23,-23,-23,-23,-22,-22,-22,-22,-22,-22,-21,-21,-21,-21,-20,-20,-20,-20,-19,-18,-16,-13,-10,-6,-2,1,4,7,9,12,14,16,16,16,15,13,9,6,2,-1,-4,-7,-10,-11,-12,-14,-15,-16,-17,-18,-19,-19,-20,-20,-20,-20,-20,-20,-20,-24,-32,-45,-54,-50,-25,25,97,182,252,270,220,126,35,-25,-53,-65,-71,-70,-60,-46,-32,-22,-18,-16,-16,-15,-14,-13,-13,-12,-11,-10,-8,-7,-5,-3,-1,1,4,7,10,14,17,21,24,28,32,36,40,45,50,55,59,64,69,72,77,81,84,87,88,88,87,84,82,77,73,67,61,54,47,39,33,26,20,14,9,4,-1,-6,-9,-13,-16,-19,-22,-24,-26,-28,-29,-29,-30,-30,-31,-32,-32,-32,-31,-31,-32,-31,-31,-31,-31,-30,-30,-29,-29,-29,-29,-28,-28,-27,-27,-28,-28,-26,-26,-26,-26,-26,-26,-26,-26,-25,-25,-25,-25,-25,-25,-26,-26,-25,-24,-24,-24,-24,-24,-24,-24,-23,-23,-23,-23,-23,-23,-23,-24,-22,-22,-22,-22,-22,-22,-22,-21,-22,-20,-20,-20,-20,-20,-19,-18,-16,-13,-10,-8,-3,0,4,7,9,11,13,15,16,16,16,14,11,6,2,-2,-4,-7,-9,-11,-12,-14,-16,-17,-18,-19,-19,-19,-19,-20,-20,-20,-20,-20,-20,-23,-30,-43,-54,-53,-30,17,88,172,245,271,230,138,45,-19,-50,-63,-70,-70,-61,-48,-34,-23,-18,-17,-16,-16,-15,-14,-13,-13,-11,-10,-8,-7,-5,-3,-1,1,4,7,9,13,16,20,23,27,31,36,40,44,49,54,59,63,68,73,76,81,83,86,88,87,87,85,82,78,73,68,62,55,48,40,33,27,20,14,9,4,0,-5,-9,-13,-16,-19,-22,-24,-26,-28,-29,-29,-29,-30,-31,-31,-32,-31,-32,-32,-32,-32], "startts":1357714800000,"marker1":[50,100]}; var data =[]; for(var i=0;i<raw.l2.length;i++) { var marker = Number.NaN; for(var j=0;j<raw.marker1.length;j++) { if(i==raw.marker1[j]) { marker=i; break; } } var obj = {"date":raw.startts+(1/244.140625*1000)*i, "value":raw.l2[i]/75,"marker":marker} data.push(obj) } margin = { top: 20, right: 20, bottom: 20, left: 45 }; width = 1800 - margin.left - margin.right; height = 600 - margin.top - margin.bottom; var x = d3.time.scale() .domain(d3.extent(data, function (d) { return d.date; })) .range([0, width]); var y = d3.scale.linear() .domain(d3.extent(data, function (d) { return d.value; })) .range([height, 0]); var line = d3.svg.line() .x(function (d) { return x(d.date); }) .y(function (d) { return y(d.value); }); var zoom = d3.behavior.zoom() .x(x) .y(y) .on("zoom", zoomed); svg = d3.select('#chart') .append("svg:svg") .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .append("svg:g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .call(zoom); svg.append("svg:rect") .attr("width", width) .attr("height", height) .attr("class", "plot"); var make_x_axis = function () { return d3.svg.axis() .scale(x) .orient("bottom") .ticks(5); }; var make_y_axis = function () { return d3.svg.axis() .scale(y) .orient("left") .ticks(5); }; var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(5); svg.append("svg:g") .attr("class", "x axis") .attr("transform", "translate(0, " + height + ")") .call(xAxis); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(5); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.append("g") .attr("class", "x grid") .attr("transform", "translate(0," + height + ")") .call(make_x_axis() .tickSize(-height, 0, 0) .tickFormat("")); svg.append("g") .attr("class", "y grid") .call(make_y_axis() .tickSize(-width, 0, 0) .tickFormat("")); // Moved this after you append your grids var marker = svg.append("line") .attr("x1",100) .attr("y1", 0) .attr("x2",100) .attr("y2", height) .attr("class", "marker") // Moved this after you append your grids & saved it to a var for later use var markerText = svg.append("text") .attr("x", 100) .attr("y", 0) .attr("dy", ".35em") .attr("dx", 5) .attr("class", "marker-text") .text(function(d) { return "test"; }); 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 chartBody = svg.append("g") .attr("clip-path", "url(#clip)"); chartBody.append("svg:path") .datum(data) .attr("class", "line") .attr("d", line); function zoomed() { console.log(d3.event.translate); console.log(d3.event.scale); svg.select(".x.axis").call(xAxis); svg.select(".y.axis").call(yAxis); svg.select(".x.grid") .call(make_x_axis() .tickSize(-height, 0, 0) .tickFormat("")); svg.select(".y.grid") .call(make_y_axis() .tickSize(-width, 0, 0) .tickFormat("")); svg.select(".line") .attr("class", "line") .attr("d", line); // Position at the start time according to your x scale. x(val) // It's not clear from your question where you want to position it var markerPos = x(raw.startts); // Move marker to position marker.attr("x1", markerPos ).attr("x2", markerPos ); // Move marker text to position markerText.attr("x", markerPos ); } Fiddle: https://jsfiddle.net/kqnLfkvw/1/
This can be solved by using d3 axis. A working example is available at https://jsfiddle.net/3gww76s0/ var make_x_marker = function (scale=1, transform=[0,0]) { console.log(transform) var markers =[]; var markerLabels={}; for (i=0; i<raw.marker1.length; i++) { var value=transform[0]+scale*(1/244.140625*1000)*raw.marker1[i]; markers.push(value) markerLabels[value]="A"+Math.floor(Math.random()*26); } return d3.svg.axis() .orient("top") .tickValues(markers) .tickSize(height-15) .tickFormat(function(d){return markerLabels[d]}) };
D3 bar chart does not dynamically update y-axis and x-axis properly
I am trying to dynamically update my bar chart from a json data set. Data look like this : [{x=a,y=1},{x=b,y=2},{x=c,y=4}], [{x=d,y=0.1},{x=a,y=1}],{x=b,y=4}] I used the code to set the dimensions of the canvas (y-axis and x-axis): var margin = {top: 20, right: 20, bottom: 70, left: 40}, width = 600 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; The whole code : // set the ranges var x = d3.scale.ordinal().rangeRoundBands([0, width], .05); var y = d3.scale.linear().range([height, 0]); // define the axis var xAxis = d3.svg.axis() .scale(x) .orient("bottom") var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(10); // add the SVG element var chart = d3.select(".chart") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // load the data data=mydata data.forEach(function(d) { d.x = d.x; d.y = +d.y; }); // scale the range of the data x.domain(data.map(function(d) { return d.x; })); y.domain([0, d3.max(data, function(d) { return d.y; })]); // add axis chart.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", "-.55em") .attr("transform", "rotate(-90)" ); chart.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 5) .attr("dy", ".71em") .style("text-anchor", "end") .text("Frequency"); // Add bar chart chart.selectAll("bar") .data(data) .enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.x); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.y); }) .attr("height", function(d) { return height - y(d.y); }); //Call function to update barchart function redraw(data){ x.domain(data.map(function(d) { return d.x; })); y.domain([0, d3.max(data, function(d) { return d.y; })]); chart.select(".x.axis").remove(); chart.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.8em") .attr("dy", "-.55em") .attr("transform", "rotate(-90)" ); // y-axis chart.select(".y.axis").remove(); chart.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("Frequency"); var bar = chart.selectAll(".bar") .data(data, function(d) { return d.x; }); // new data: bar.enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.x); }) .attr("y", function(d) { return y(d.y); }) .attr("height", function(d) { return height - y(d.y); }) .attr("width", x.rangeBand()); // removed data: // bar.exit().remove(); chart.select(".y.axis").transition().delay(750).call(yAxis) // updated data: bar .transition() .duration(750) .attr("y", function(d) { return y(d.y); }) .attr("height", function(d) { return height - y(d.y); }); }
In this case you will have to redefine the xAxis and yAxis to use the new scale values you define in the function, by pretty much copying the declaration into the function scope. // define the axis var xAxis = d3.svg.axis() .scale(x) .orient("bottom") var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(10); The primary reason you're getting the old values on the axis is because when you call ".call(xAxis)" inside the function the x scale associated with that axis declaration is the original one. Hope this helps..
D3 line chart Invalid value for <path> attribute
So i have the following js to create my linechart: var data = scope.dataset; var margin = {top: 20, right: 20, bottom: 30, left: 50}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var line = d3.svg.line() .x(function (d) { return x(d.label); }) .y(function (d) { return y(d.value); }); data.forEach(function (d) { d.label = d.label; d.value = d.value; }); var svg = d3.select("#lbLineChart").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 + ")"); x.domain(d3.extent(data, function (d) { return d.label; })); y.domain(d3.extent(data, function (d) { return d.value; })); 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("Price ($)"); svg.append("path") .datum(data) .attr("class", "line") .attr("d", line); Where the data is an array of objects: {label: 'mylabel', value: 5} Invalid value for <path> attribute Im not quite sure what im doing wrong? ive checked the variables again and again but was unable to find where there is an error.
Path not showing d3 (binding issue?)
I've been working on a project using fake data and sketches I've found online to create a line graph. However, I can't display paths with a JSON file containing numerical data. This is not the final data but I'm using the field "Id" as numerical value. I should be able to see a diagonal line, but nothing shows on the graph. <body> <script> var margin = {top: 20, right: 30, bottom: 30, left: 50}, width = 900 - margin.left - margin.right, height = 500 - margin.top - margin.bottom, a = 3.779528*5, f = width/height, ticksX = 1+ (width/a), ticksY = 1+ (height/a*f) c = 1 + (width/a*10); var x = d3.scale.linear() .domain([194, 2229]) .range([0, width]); var y = d3.scale.linear() .domain([194, 2229]) .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .tickSize(-height) .tickPadding(10) .tickSubdivide(true) .ticks(ticksX) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .tickPadding(10) .tickSize(-width) .tickSubdivide(true) .ticks(ticksY) .orient("left"); var zoom = d3.behavior.zoom() .x(x) //.y(y) .scaleExtent([1, 10]) .on("zoom", zoomed); var svg = d3.select("body").append("svg") .call(zoom) .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); d3.json("pacientes.json", function(error, data) { data.forEach(function(d) { d.Id = +d.Id; d.Edad = +d.Edad; console.log(d.Id); }); x.domain(d3.extent(data, function(d) { return d.Id; })); y.domain(d3.extent(data, function(d) { return d.Id; })); svg.append("clipPath") .attr("id", "clip") .append("rect") .attr("width", width) .attr("height", height); var line = d3.svg.line() .interpolate("linear") .x(function(d) { return x(d.Id); }) .y(function(d) { return y(d.Edad); }); svg.selectAll('svg-path') .data(data) .enter() .append("path") .attr("x", function(d) { return x(d.Id); }) .attr("y", function(d) { return x(d.Id); }) .style("stroke-width", 10) .attr("class", "line") .attr("clip-path", "url(#clip)") .attr('stroke', 'blue') .attr("d", line); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.append("g") .attr("class", "y axis") .append("text") .attr("class", "axis-label") .attr("transform", "rotate(-90)") .attr("y", (-margin.left) + 10) .attr("x", -height/2) .text('mV'); }); // closing line function zoomed() { svg.select(".x.axis").call(xAxis); svg.select(".y.axis").call(yAxis); svg.selectAll('path.line').attr('d', line); ); } </script> </body> </html> I'm pretty convinced that my error is here svg.selectAll('svg-path') .data(data) .enter() .append("path") .attr("x", function(d) { return x(d.Id); }) .attr("y", function(d) { return x(d.Id); }) .style("stroke-width", 10) .attr("class", "line") .attr("clip-path", "url(#clip)") .attr('stroke', 'blue') .attr("d", line); The data is being loaded correctly and the SVGs are being created (as you can see from the pictures). Any help will be appreciated. I did not add the CSS, but it should be a blue line. Thank you!
Adding tooltips to line graph data points AFTER lines animate
I have a basic line graph with two lines. When I click a button, one of the two lines will draw on the graph. I use stroke-dasharray to draw the lines. Would anyone know how I could add tooltips to my lines? Does using stroke-dasharray make it harder? Heres my code. var button=d3.select("#button"); //defines canvas (area in which graph is placed) var margin = {top: 30, right: 20, bottom: 50, left: 60}, width = 800 - margin.left - margin.right, height = 700 - margin.top - margin.bottom; var parseDate = d3.time.format("%d-%b-%y").parse; //OUTPUT RANGE var x = d3.time.scale() .range([0, width]); //OUTPUT RANGE var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis().scale(x) .orient("bottom") .ticks(5); var yAxis = d3.svg.axis().scale(y) .orient("left") .ticks(5); //assigns coordinates for each piece of data var valueline = d3.svg.line() .interpolate("interpolation") .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.close); }); //second line data var valueline2 = d3.svg.line() .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.open); }); //create area for 'area' below line var area = d3.svg.area() .x(function(d) { return x(d.date); }) .y0(height) .y1(function(d) { return y(d.close); }); //creates area to draw graph var svg = d3.select("body") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) //groups content .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); function make_x_axis() { return d3.svg.axis() .scale(x) .orient("bottom") .ticks(5) } function make_y_axis() { return d3.svg.axis() .scale(y) .orient("left") .ticks(30) } // csv callback function d3.csv("myData3.csv", function(data) { data.forEach(function(d) { d.date = parseDate(d.date); d.close = +d.close; d.open = +d.open; }); //INPUT DOMAINS //.extent() returns min and max values of argument x.domain(d3.extent(data, function(d) { return d.date; })); //returns max of whichever set of data is bigger y.domain([0, d3.max(data, function(d) { return Math.max(d.close, d.open); })]); d3.select("#button1").on("click", function(){ var path = svg.append("path") // Add the valueline path. .attr("class", "line") .attr("d", valueline(data)) .attr("stroke", "steelblue") .attr("stroke-width", "5") .attr("fill", "none"); var totalLength = path.node().getTotalLength(); path .attr("stroke-dasharray", totalLength + "30" * 30) .attr("stroke-dashoffset", totalLength) .transition() .duration(2000) .ease("linear") .attr("stroke-dashoffset", 0); }) d3.select("#button2").on("click", function(){ var path2 = svg.append("path") // Add the valueline path. .attr("class", "line2") .attr("d", valueline2(data)) .attr("stroke", "steelblue") .attr("stroke-width", "5") .attr("fill", "none"); var totalLength = path2.node().getTotalLength(); path2 .attr("stroke-dasharray", totalLength + "30" * 30) .attr("stroke-dashoffset", totalLength) .transition() .duration(2000) .ease("linear") .attr("stroke-dashoffset", 0) }) svg.append("g") // Add the X Axis .attr("class", "x axis") //moves x axis to bottom of graph .attr("transform", "translate(0," + height + ")") .call(xAxis); //text label for x-axis svg.append("text") // text label for the x axis .attr("transform", "translate(" + (width / 2) + " ," + (height + margin.bottom - 5 ) + ")") .style("text-anchor", "middle") .text("Date"); svg.append("g") // Add the Y Axis .attr("class", "y axis") .call(yAxis); //text label for y-axis svg.append("text") .attr("transform", "rotate(-90)") .attr("y", 0 - margin.left) .attr("x",0 - (height / 2)) //adds extra left padding as original y pos = 0 .attr("dy", "1em") .style("text-anchor", "middle") .text("Value"); //adding a title to the graph svg.append("text") .attr("x", (width / 2)) .attr("y", 0 - (margin.top / 2)) .attr("text-anchor", "middle") .style("font-size", "16px") .style("text-decoration", "underline") .text("Graph"); //draw x axis grid svg.append("g") .attr("class", "grid") .attr("transform", "translate(0," + height + ")") .call(make_x_axis() .tickSize(-height, 0, 0) .tickFormat("") ) //draw y axis grid svg.append("g") .attr("class", "grid") .call(make_y_axis() .tickSize(-width, 0, 0) .tickFormat("") ) });<!--d3.csv close--> Thanks in advance!
The easiest way to add a tooltip is to append an svg:title element to the elements you want to have a tooltip for. It will be displayed by the browser automatically when you hover over the element. It works for all kinds of elements as well. So your code would need to look something like var path = svg.append("path") // Add the valueline path. .attr("class", "line") .attr("d", valueline(data)) .attr("stroke", "steelblue") .attr("stroke-width", "5") .attr("fill", "none") .append("title").text("whatever"); If you need more sophisticated functionality, you could try for example tipsy, which works in a similar way.