I found this snippet in someone else's question which does exactly what I want - a line chart with a dropdown box for switching between multiple datasets. The thing is, I want to load externally from a php generated JSON file instead but I'm really not sure how I can do that.
d3.taos = function (config) {
// Margins and graph formatting.
var margin = {
top: 20,
right: 20,
bottom: 20,
left: 60 },
width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
x = d3.time.scale(), // different scaling.
y = d3.scale.linear(),
xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5),
yAxis = d3.svg.axis().scale(y).orient("left").ticks(5),
line = d3.svg.line(),
color = d3.scale.category10(),
zoom = d3.behavior.zoom().scaleExtent([0.5, 50]);
// The chart itself.
var chart = function (selection) {
dataset = selection.data()[0];
// Select the svg element, if it exists.
var svg = selection.selectAll("svg").data([dataset])
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Rendering both axes.
gEnter.append("g").attr("class", "x axis");
gEnter.append("g").attr("class", "y axis");
gEnter.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("id", "clip-rect")
.attr("x", "0")
.attr("y", "0")
.attr("width", width)
.attr("height", height);
x.range([0, width])
.domain(d3.extent(d3.merge(dataset), function (d) {
return d.x;
}))
y.range([height, 0])
.domain(d3.extent(d3.merge(dataset), function (d) {
return d.y;
}))
var g = svg.select("g");
// Update the x-axis.
g.select(".x.axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Update the y-axis.
g.select(".y.axis")
.call(yAxis);
// Define lines
line = d3.svg.line()
.x(function (d) {
return x(d.x);
})
.y(function (d) {
return y(d.y);
})
var path = g.selectAll(".line")
.data(dataset)
.enter().append("path")
.style("stroke", function (d, i) {
return color(i)
});
path.attr("class", "line")
.attr("d", line)
.attr("clip-path", "url(#clip)");
// Update the clip rectangle
g.select("#clip-rect")
.attr("width", width)
.attr("height", height);
// Update the line path.
g.selectAll(".line")
.attr("d", line);
zoom.x(x).y(y)
.on("zoom", draw);
// Rect for zoom.
gEnter.append("rect")
.attr("class", "rectzoom")
.attr("width", width)
.attr("height", height)
.call(zoom);
function draw() {
g.select(".x.axis").call(xAxis);
g.select(".y.axis").call(yAxis);
g.selectAll("path.line").attr("d", line);
//g.select("#clip-rect").attr("width",width).attr("height",height);
}
/*
* Methods
*/
chart.width = function (w) {
if (!arguments.length) return width;
width = w;
return this;
};
chart.height = function (h) {
if (!arguments.length) return height;
height = h;
return this;
};
return chart
} // chart
return chart
}; // d3.taos
/*
* Main
*/
// for json:
// New instance
var t = d3.taos();
var f = function () {}
var data = d3.json("api.json?id=1", function(error, data) {
if (error) return console.warn(error);
// Creation
d3.select("svg#chart")
.datum(data)
.attr("x", function(d) { x(d.x) })
.call(t);
});
// Update
d3.select("select").on("change", function () {
var val = $("select#dataset").val();
val == "dataset1" ? dataset = dataset1 : dataset = dataset2;
console.log("Dataset changed: " + val);
d3.select("svg#chart")
.datum(dataset)
.call(t.width(800));
});
And the HTML code...
<select id="dataset">
<option value="1" selected>Dataset 1</option>
<option value="2">Dataset 2</option>
<option value="3">Dataset 3</option>
</select>
Sample JSON dataset from e.g. api.json?id=1
{
"usability_index": [
{"x": 1397220093000, "y": 7},
{"x": 1397222093000, "y": 21},
{"x": 1397224093000, "y": 13},
{"x": 1397226093000, "y": 23}
]
}
I explored with d3.json()
but I'm not quite sure how to go about loading it dynamically when e.g. the default dataset option is changed to Dataset 3, from api.json?id=1
to api.json?id=3
.
I'm really new to d3.js and would really appreciate some guidance here!
You could try something like this, but instead using a library that makes reusable charts based on d3.js.
The following is an example on how you could load data via API calls
var chart = c3.generate({
data: {
url: 'api.json?id=1',
mimeType: 'json'
}
});
Note that c3.js requires you to have your JSON in the format:
{
"line1": [220, 240, 270, 250, 280],
"line2": [180, 150, 300, 70, 120],
"line3": [200, 310, 150, 100, 180]
}
Therefore, you need to parse and re-format your JSON data before you can load it in.
And attach event handlers which you can choose to regenerate or load more lines into the chart.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With