Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3.js: loading different JSON datasets on dropdown change

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!

like image 835
Jia Jian Goi Avatar asked Nov 01 '22 01:11

Jia Jian Goi


1 Answers

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.

like image 97
Jiawei Tan Avatar answered Nov 10 '22 19:11

Jiawei Tan