use img instead of text label in d3.js line chart - javascript
Fiddle Example
I couldn't get ordinal scales to work with zooming and panning to achieve horizontally scroll-able effect so I have settled for scale.linear() to use numeric values for axis ticks. I was wondering if it is possible to superimpose the text label in g.tick with an image element. I have come up with this code after .call(xAxis)
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis)
.selectAll(".tick text").each(function(k,i){
console.log(data[k]["img"]);
var r = document.createElement('image')
r.setAttribute('x',0)
r.setAttribute('y',9)
r.setAttribute('xlink:href',data[k]["img"])
r.setAttribute('width',50)
r.setAttribute('height',50)
this.parentNode.insertBefore(r,this);
})
I saw that the elements are prepended in g.tick but the images are nowhere to be seen. Is it because of the x and y values? Also, how can I bind the image links from the JSON data to the image element? I have tried data[k]["img"] but it gave me Cannot read property 'img' of undefined.
var img = "https://www.gravatar.com/avatar/904fd39461599f72d580fadf3a73115b?s=128&d=identicon&r=PG&f=1";
var data = [{"item":1,"diameter":"15.00","img":img},{"item":2,"diameter":"10.00","img":img},
{"item":3,"diameter":"25.00","img":img},{"item":4,"diameter":"7.00","img":img},
{"item":5,"diameter":"35.00","img":img},{"item":6,"diameter":"15.00","img":img},
{"item":7,"diameter":"12.00","img":img},{"item":8,"diameter":"10.00","img":img},
{"item":9,"diameter":"17.00","img":img},{"item":10,"diameter":"13.00","img":img},
{"item":11,"diameter":"5.00","img":img},{"item":12,"diameter":"10.00","img":img},
];
function line_chart(field,el){
margin = {
top: 20,
right: 20,
bottom: 20,
left: 45
},
tickno = 10,
width = 960 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom,
x = d3.scale.linear().domain(d3.extent(data, function (d) {
return d.item;
})).range([0, width]),
ymax = d3.max(data,function(d){
return (parseInt(d[field])+1);
}),
ymin = d3.min(data,function(d){
return d[field];
}),
xmax = d3.max(data,function(d){
return d.name;
}),
y = d3.scale.linear()
.domain([ymin,ymax])
.range([height, 0]);
var line = d3.svg.line()
.x(function (d) {
return x(d.item);
})
.y(function (d) {
return y(d[field]);
});
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([1, 1])
.y(y)
.on("zoom", zoomed);
svg = d3.select(el)
.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(tickno);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(y)
.orient("left")
.ticks(tickno);
};
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(tickno);
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis)
.selectAll(".tick text").each(function(data){
var r = document.createElement('image')
r.setAttribute('x',0)
r.setAttribute('y',9)
r.setAttribute('xlink:href','https://www.gravatar.com/avatar/904fd39461599f72d580fadf3a73115b?s=32&d=identicon&r=PG&f=1')
r.setAttribute('width',50)
r.setAttribute('height',50)
this.parentNode.insertBefore(r,this);
})
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(tickno);
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(""));
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);
svg.append('g').attr('class','dots').selectAll(".dot").data(data).enter().append("circle").attr("r",3.5)
.attr("cx",function(d){return x(d.item);})
.attr("cy",function(d){return y(d[field]);})
function zoomed() {
console.log(d3.event.translate);
console.log(d3.event.scale);
svg.select(".dots")
.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
svg.selectAll(".dots circle").attr("r", function(){
return (3.5 * 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);
svg.selectAll(".dots circle").attr("r", function(){
return (3.5 * d3.event.scale);
});
}
}
line_chart('diameter','#area')
Your image doesn't display because your width is too small.
Also, it's a bit cleaner if you append the images the d3 way:
.selectAll(".tick").each(function(d,i){
d3.select(this)
.append('image')
.attr('xlink:href', data[i].img)
.attr('x',0)
.attr('width',128)
.attr('height',128);
})
Updated fiddle.
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.js: Changing the tick values on x-axis based on the screen width
I am making a responsive D3.js Bar Chart, by setting the height to clientWidth. Though the chart resizes after reloading in a new size, when the size is small the x-axis values overlap. I need to avoid this, how can i do it? Script: clientw = document.body.clientWidth; var margin = {top: 40, right: 20, bottom: 30, left: 40}, width = clientw - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1); 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") .ticks(10) .tickFormat(d3.format("s")); var tip = d3.tip() .attr('class', 'd3-tip') .offset([-10, 0]) .html(function(d) { return "<strong>Hola:</strong> <span style='color:red'>" + d.hola+ "°C"+"</span>"; }) 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 + ")"); svg.call(tip); d3.tsv("data.tsv", type, function(error, data) { x.domain(data.map(function(d) { return d.hermanos; })); y.domain([0, 45]); 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("Hola"); svg.selectAll(".bar") .data(data) .enter().append("rect") .attr("width", x) .attr("fill","grey") .attr("class", "bar") .attr("x", function(d) { return x(d.hermanos); }) .attr("width", x.rangeBand()) .attr("y", function(d) { return y(d.hola); }) .attr("height", function(d) { return height- y(d.hola); }) .on('mouseover', tip.show) .on('mouseout', tip.hide) }); function type(d) { d.hola= +d.hola; return d; }
D3js Zoom lines and points from csv file won't work for points
I'm trying to modify Zoomable area from http://bl.ocks.org/mbostock/4015254 with adding data points from csv file in it, but couldn't get things right. Only lines can be zoomed and moved but not points. My guess is I need to put circle's .attr("transform", function(d){ return "translate("+x(d[key0])+","+y(d[key1])+")";}); within function draw, but then it cannot recognize key0 and key1 (I have multiple columns in the csv file). The following is the code I modified. Any idea how to fix this? <script> var margin = {top: 20, right: 60, bottom: 30, left: 20}, width = 960 - margin.left - margin.right, height = 800 - margin.top - margin.bottom;` var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse, formatDate = d3.time.format("%Y"); 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("right") .tickSize(-width) .tickPadding(6); var xGrid = d3.svg.axis() .scale(x) .orient("bottom") .tickSize(-height,0) .ticks(5) .tickPadding(1) .tickFormat(""); var line = d3.svg.line(); var zoom = d3.behavior.zoom() .scaleExtent([1,128]) .on("zoom", draw); var zoom2 = d3.behavior.zoom() .scaleExtent([1,128]) 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 + ")") .call(zoom); svg.append("g") .attr("class", "y axis") .attr("transform", "translate(" + width + ",0)"); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height/2 + ")"); svg.append("g") .attr("class", "x line") .attr("transform", "translate(0," + height/2 + ")") .append("svg:line") .attr("x1",x(0)) .attr("y1",-y(0)) .attr("x2",x(width)) .attr("y2",-y(0)); svg.append("g") .attr("class", "grid") .attr("transform", "translate(0,"+ height + ")"); svg.append("path") .attr("class", "line"); svg.append("rect") .attr("class", "pane") .attr("width", width) .attr("height", height); circle = svg.selectAll("circle"); d3.csv("encounter.csv", function(error, data) { key0 = Object.keys(data[0])[1]; key1 = Object.keys(data[0])[3]; data.forEach(function(d,i) { d[key0] = parseDate(d[key0]); d[key1] = +d[key1]; }); x.domain([new Date(2014, 0, 1), new Date(2015, 0, 1)]); y.domain(d3.extent(data, function(d){return d[key1];})).nice(); zoom.x(x); svg.select("path.line").data([data]); line.x(function(d) { return x(d[key0]); }) .y(function(d) { return y(d[key1]); }); circle.data(data) .enter().append("circle") .attr("class", "dot") .attr("r", 5) .attr("transform", function(d){ return "translate("+x(d[key0])+","+y(d[key1])+")";}); draw(); }); function draw() { svg.select("g.x.axis").call(xAxis); svg.select("g.y.axis").call(yAxis); svg.select("g.grid").call(xGrid); svg.select("path.line").attr("d", line); }
My d3 scatterplot doesn't show on the graph
I have tried to work on my D3 scatter plot. And it seems like my data isn't showing on the graph itself. Any reasons why? And also.. i have set my x and y domain to certain limit. But when i zoom in, out.. it will still go beyond the limit. Here is my codes... var margin = { top: 20, right: 20,bottom: 20, left: 45 }, width = 900 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S").parse; 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") .ticks(5); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(5); var zoom = d3.behavior.zoom() .x(x) .on("zoom", zoomed); var svg = d3.select('.graph') .append("svg") .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top + margin.bottom) .call(zoom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 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)"); 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); }; 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(".dot") .attr("class", "circle") .attr("r", 5) .attr("cx", function(d) { return x(d.ArtDateTime);}) .attr("cy", function(d) { return y(d.Ranking * 3); }) } d3.csv("FinalCSVFile.csv", function(error, data) { data.forEach(function(d) { d.ArtDateTime = parseDate(d.ArtDateTime); d.Ranking = +d.Ranking; }); x.domain(d3.extent(data, function(d) { return d.ArtDateTime; })); y.domain([0, 5]); 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", "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("")); chartBody.append("svg:path") .selectAll(".dot") .data(data) .enter().append("circle") .attr("class", "dot") .attr("r", 5) .attr("cx", function(d) { return x(d.ArtDateTime);}) .attr("cy", function(d) { return y(d.Ranking); }); }); Enlighten me please? NEED HELP AND ADVICE! I AM very new to D3.js
D3: Panning along date x axis
I'm trying to display dates in the x axis and at the same time zoom it when you scroll. So, I have this code: <script type="text/javascript"> var data = [ [{'x':20111001,'y':1},{'x':20111002,'y':6},{'x':20111003,'y':11},{'x':20111004,'y':1},{'x':20111005,'y':2},{'x':20111006,'y':12},{'x':20111007,'y':2},{'x':20111008,'y':3},{'x':20111009,'y':13},{'x':20111010,'y':3}], [{'x':20111001,'y':2},{'x':20111002,'y':2},{'x':20111003,'y':12},{'x':20111004,'y':2},{'x':20111005,'y':3},{'x':20111006,'y':1},{'x':20111007,'y':2},{'x':20111008,'y':7},{'x':20111009,'y':2},{'x':20111010,'y':7}], [{'x':20111001,'y':3},{'x':20111002,'y':10},{'x':20111003,'y':13},{'x':20111004,'y':3},{'x':20111005,'y':12},{'x':20111006,'y':14},{'x':20111007,'y':6},{'x':20111008,'y':1},{'x':20111009,'y':7},{'x':20111010,'y':9}], [{'x':20111001,'y':4},{'x':20111002,'y':4},{'x':20111003,'y':14},{'x':20111004,'y':14},{'x':20111005,'y':10},{'x':20111006,'y':15},{'x':20111007,'y':3},{'x':20111008,'y':0},{'x':20111009,'y':3},{'x':20111010,'y':12}] ]; var colors = [ 'steelblue', 'green', 'red', 'purple' ] var b =[]; var parseDate = d3.time.format("%Y%m%d").parse; data.forEach(function (d) { f = d; f.forEach(function(f){ b.push(parseDate(String(f.x))); }) }) var margin = {top: 20, right: 30, bottom: 30, left: 50}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.time.scale() .domain([d3.extent(b)]) .range([0, width]); var y = d3.scale.linear() .domain([-1, 16]) .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .tickSize(-height) .tickPadding(10) .tickSubdivide(true) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .tickPadding(10) .tickSize(-width) .tickSubdivide(true) .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 + ")"); 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) .style("text-anchor", "end") .text("Ventas (Miles €)"); 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.x); }) .y(function(d) { return y(d.y); }); svg.selectAll('.line') .data(data) .enter() .append("path") .attr("class", "line") .transition() .attr("clip-path", "url(#clip)") .attr('stroke', function(d,i){ return colors[i%colors.length]; }) .attr("d", line); var div = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); var points = svg.selectAll('.dots') .data(data) .enter() .append("g") .attr("class", "dots") .attr("clip-path", "url(#clip)"); points.selectAll('.dot') .data(function(d, index){ var a = []; d.forEach(function(point,i){ a.push({'index': index, 'point': point}); }); return a; }) .enter() .append('circle') .attr('class','dot') .attr("r", 2.5) .attr('fill', function(d,i){ return colors[d.index%colors.length]; }) .attr("transform", function(d) { return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; } ).on("mouseover", function(d) { div.transition() .duration(200) .style("opacity", .9); div .html(d.point.x + "K<br/>" + d.point.y) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY) + "px"); }) .on("mouseout", function(d) { div.transition() .duration(500) .style("opacity", 0); }) function zoomed() { svg.select(".x.axis").call(xAxis); svg.select(".y.axis").call(yAxis); svg.selectAll('path.line').attr('d', line); points.selectAll('circle').attr("transform", function(d) { return "translate(" + x(d.point.x) + "," + y(d.point.y) + ")"; } ); } </script> I can make it with numbers but can't implement it with dates. I've checked other examples and how they make it but can't find the way to code it in my chart. I'd like to know how to display dates on x axis.
Is your question how to make the axis dates instead of just numbers? Or is it how to make the axis pannable? If it's the first, use code like this: var x=d3.time.scale() .domain([minDate,maxDate]) The minDate and maxDate have to be javascript Date objects.