Edited: added zooming.
I'm getting data from php function (just sql request) to js variable, so js variable is json data. I need to build zoomable d3 line chart based on this json.
Json variable looks like this:
[{temp: "5", created_at: "2017-03-19"},
{temp: "5", created_at: "2017-03-19"},
{temp: "26", created_at: "2018-04-20"}]
Error is: Error: <path> attribute d: Expected number, "MNaN,NaNLNaN,NaNL…"
Line_chart.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line); ///One error is on this line
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2); ///Second error is on this line
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 110, left: 40},
margin2 = {top: 430, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var parseDate = d3.timeParse("%Y-%M-%D");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var line = d3.line()
.x(function (d) { return x(d.Date); })
.y(function (d) { return y(d.Air_Temp); });
var line2 = d3.line()
.x(function (d) { return x2(d.Date); })
.y(function (d) { return y2(d.Air_Temp); });
var clip = svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", width)
.attr("height", height)
.attr("x", 0)
.attr("y", 0);
var Line_chart = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("clip-path", "url(#clip)");
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
var data = jsonfile
x.domain(d3.extent(data, function(d) { return d.created_at; }));
y.domain([0, d3.max(data, function (d) { return d.temp; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
Line_chart.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
console.log(data);
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
Line_chart.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
Line_chart.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
function type(d) {
d.Date = parseDate(d.created_at);
d.Air_Temp = +d.temp;
return d;
}
jsonfile in d3.json is this json variable.
I have problem with dislaying data. I have x and y axis but no displayed data.
---------Reason of the error is incorrectly parsed data, still don't know where code goes wrong.-----------
I added: after var data = jsonfile
data.forEach(function(d){
d.created_at = parseDate(d.created_at);
d.temp = +d.temp;
});
And it worked. Graph builds using console. Don't why and where json strings parsed incorrectly.
Related
I downloaded the javascript code from this page https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172. I would like to make a change, in fact the html page takes data from a csv file, while I wanted to take data directly from an array on the same html page.
That is, I would like to create a simple array of numbers and an array of months within index.html and from there to take data.
This is the piece where the data are taken:
d3.csv("sp500.csv", type, function(error, data) {
if (error) throw error;
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.price; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
});
While I would like to have an array of numbers and an array di months on the html page, without using the csv:
var price = [9, 6, 2];
var date = [Jan 2000, Feb 2000, Mar 2000]
How can I do? Thanks
Here's a bl.ock that takes an array as an input.
var data = [{date: 'Jan 2000', price: 9}, {date: 'Feb 2000', price:6},{date: 'Mar 2000', price: 2}];
data.forEach(function (d) {
d.date = parseDate(d.date);
d.price = +d.price;
});
A snippet for the same:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.area {
fill: steelblue;
clip-path: url(#clip);
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 110, left: 40},
margin2 = {top: 430, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var parseDate = d3.timeParse("%b %Y");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var area = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
var area2 = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) { return x2(d.date); })
.y0(height2)
.y1(function(d) { return y2(d.price); });
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
var data = [{date: 'Jan 2000', price: 9}, {date: 'Feb 2000', price:6},{date: 'Mar 2000', price: 2}];
data.forEach(function (d) {
d.date = parseDate(d.date);
d.price = +d.price;
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.price; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
</script>
Hope this helps.
you can just skip the csv function and use your own data
instead of
d3.csv("sp500.csv", type, function(error, data) {
if (error) throw error;
x.domain(d3.extent(data, function(d) { return d.date; }));
//...
})
you can do:
var data = [{date:'Jan 2000', price: 9}, {}, {}, ...];
x.domain(d3.extent(data, function(d) { return d.date; }));
//...
if you want to keep it a function you can also:
var process = function(data) {
x.domain(d3.extent(data, function(d) { return d.date; }));
//...
})
process({date:'Jan 2000', price: 9}, {}, {}, ...]); // <-- the data
Small problems are difficult to identify. I am using example to create a linechart using d3 v4. I'm using d3.line() rather than d3.area(). Also drawing circles on the line peak points. Things are working fine.
Problem is with the drawn circles. They are not moving to the correct position when i'm zooming the graph.
Here is the complete code:
.area {
fill: none;
stroke: #a2dced;
stroke-width: 2;
clip-path: url(#clip);
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
rect.selection
{
fill:green;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="960" height="500"></svg>
<script>
var data = [{date: "10:30:00", price: 36000},
{date: "11:00:20", price: 40000},
{date: "12:00:00", price: 38000},
{date: "14:20:00", price: 50400}];
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 110, left: 40},
margin2 = {top: 430, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var parseDate = d3.timeParse("%H:%M:%S");//"%b %Y");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var area = d3.line()
//.curve(d3.curveMonotoneX)
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.price);
});
var area2 = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) {
return x2(d.date);
})
.y(function (d) {
return y2(d.price);
});
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
function update(){
for(var k in data)
{
type(data[k]);
}
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.price; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
focus.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("class","circle")
.attr("r", 5)
.style("fill", 'orange')
.style("stroke", 'red')
.style("stroke-width", "2")
.attr("cx", function(d) { return x(d.date) })
.attr("cy", function(d) { return y(d.price); });
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("class","circle")
.attr("r", 1)
.style("fill", 'blue')
.style("stroke", 'red')
.style("stroke-width", "2")
.attr("cx", function(d) { return x(d.date) })
.attr("cy", function(d) { return y(d.price); });
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
}
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.select(".area").attr("d", area);
focus.selectAll('.circle').attr("transform", function(d) {
return "translate(" + x(d.date) + "," + y(d.price) + ")";
});
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.select(".area").attr("d", area);
focus.selectAll('.circle').attr("transform", function(d) {
return "translate(" + x(d.date) + "," + y(d.price) + ")";
});
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
context.selectAll('.circle').attr("transform", function(d) {
return "translate(" + x2(d.date) + "," + y2(d.price) + ")";
});
}
function type(d) {
d.date = parseDate(d.date);
d.price = +d.price;
return d;
}
update();
</script>
JSFiddle link.
I updated you jsfiddle by replacing all transformattributes by changing it to cx and cy, e.g.:
before
focus.selectAll('.circle').attr("transform", function(d) {
return "translate(" + x(d.date) + "," + y(d.price) + ")";
});
after
focus.selectAll('.circle')
.attr("cx", function(d) { return x(d.date) })
.attr("cy", function(d) { return y(d.price); });
Otherwise, you will translate with your other coordinates, which might lead to hard to find problems
clipPath in a d3-project don't clips: the graph overflows the chart window on the left.
I followed several examples available online, but I don't see, why my clipPath don't works.
Working example can be found here: https://phinetwork.ch/wolf/dynamicgraph.html
Code:
<style>
.area {
fill: darkorange;
}
.bgrect {
background-color:#999;
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
background-color:grey;
}
.grid line{
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid text {
display:none;
}
.grid path, .xgrid path{
stroke-width: 0;
}
</style>
<svg width="900" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 0, bottom: 110, left: 40},
margin2 = {top: 430, right: 0, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
height2 = +svg.attr("height") - margin2.top - margin2.bottom;
var parseDate = d3.timeParse("%Y-%m-%d");
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x)
.ticks(10),
yAxis = d3.axisLeft(y)
.ticks(7),
xgAxis = d3.axisBottom(x)
.ticks(10)
.tickSize(-height),
ygAxis = d3.axisLeft(x)
.ticks(10)
.tickSize(-width - margin.left),
xAxis2 = d3.axisBottom(x2);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var area = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.rz); });
var area2 = d3.area()
.curve(d3.curveMonotoneX)
.x(function(d) { return x2(d.date); })
.y0(height2)
.y1(function(d) { return y2(d.rz); });
//svg.append("defs").append("clipPath")
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("x", 40)
.attr("y", 0)
.attr("width", width-margin.left)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.csv("files/institute/testdat.csv", type, function(error, data) {
if (error) throw error;
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.rz; })]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("rect")
.attr("class", "bgrect")
.attr("width", width)
.attr("height", height)
//.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
focus.append("path")
.datum(data)
.attr("class", "area")
.attr("clip-path", "url(#clip)")
.attr("d", area);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis grid")
.attr("transform", "translate(0," + height + ")")
.call(xgAxis);
focus.append("g")
.attr("class", "axis grid")
.attr("transform", "translate(0," + -margin.top + ")")
.call(ygAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "area")
.attr("d", area2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width - margin.left)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
});
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
focus.select(".grid").call(xgAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.select(".area").attr("d", area);
focus.select(".axis--x").call(xAxis);
focus.select(".grid").call(xgAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
function type(d) {
d.date = parseDate(d.date);
d.rz = +d.rz;
return d;
}
</script>
Any suggestions for this problem?
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.
i am trying to visualize some data using Focus + Context via brushing using D3. I am having some problems with the data. I have just changed the data fetch lines of code since i am fetching 2 values using d3.json. Here is my code -
<script type="text/javascript">
var margin = {top: 10, right: 10, bottom: 100, left: 40},
margin2 = {top: 430, right: 10, bottom: 20, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
height2 = 500 - margin2.top - margin2.bottom;
var parseDate = d3.time.format("%a %e %H %M").parse;
var x = d3.time.scale().range([0, width]),
x2 = d3.time.scale().range([0, width]),
y = d3.scale.linear().range([height, 0]),
y2 = d3.scale.linear().range([height2, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
xAxis2 = d3.svg.axis().scale(x2).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("left");
var brush = d3.svg.brush()
.x(x2)
.on("brush", brushed);
var area = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x(d.receiveddate); })
.y0(height)
.y1(function(d) { return y(d.gtse); });
var area2 = d3.svg.area()
.interpolate("monotone")
.x(function(d) { return x2(d.receiveddate); })
.y0(height2)
.y1(function(d) { return y2(d.gtse); });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
d3.json("rest.php/lastweek"+"/"+"dibya", function(error, data) {
var allData = data.records;
allData.forEach(function(d) {
var formattedDate = new Date(+d.receiveddate).toString();
d.receiveddate = parseDate(d3.time.format("%a %e %H %M")(new Date(formattedDate)));
d.gtse = +d.gtse;
});
x.domain(d3.extent(allData.map(function(d) { return d.receiveddate; })));
y.domain([0, d3.max(allData.map(function(d) { return d.gtse; }))]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("clip-path", "url(#clip)")
.attr("d", area);
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
context.append("path")
.datum(data)
.attr("d", area2);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y", -6)
.attr("height", height2 + 7);
});
function brushed() {
x.domain(brush.empty() ? x2.domain() : brush.extent());
focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
}
Here the received date is fetched as date in Millis and converted accordingly. The received date is in the frequency of 10 mins. The browser loads the x and y axes according to the values passed but no graph is plotted. Neither do i get any error in console. What am i missing?