可重复使用的D3图表,其中分隔了公共代码

时间:2014-05-15 14:01:04

标签: javascript d3.js

我使用此处概述的框架:http://bost.ocks.org/mike/chart/

,有一个工作的D3线图

由于我创建了很多图表,我希望将常用元素(例如宽度和高度)分离到一个单独的文件中,但我不确定如何在可重复使用的框架。

这是调用javascript文件:

var common = commonChart()
    .main_height(400)
    .main_width(600);

var chart = multiLineChart()
    .x(function(d) { return d.date; })
    .y(function(d) { return d.number; })
    .yLabel("Number")
    .dimKey(function(d) { return d._id.env; })
    .yTickFormat(function(d) { return d3.round(d); })
    .yScale(d3.scale.sqrt())
    .color(d3.scale.category10());

d3.json('data/datafile.json', function(data) {
    d3.select("#graph")
        .datum(data)
        .call(common)
        .call(chart);
});

通用文件是:

function commonChart() {

    var main_width, main_height;

    function chart(selection) {

        console.log(main_height);

    }

    // Get/set main_width
    chart.main_width = function(value) {
        if (!arguments.length) return main_width;
        main_width = value;
        return chart;
    }

    // Get/set main_height
    chart.main_height = function(value) {
        if (!arguments.length) return main_height;
        main_height = value;
        return chart;
    }

}

multiLineChart具有线图本身的所有核心逻辑。当我运行时,我最终得到Cannot read property 'main_height' of undefined。有没有办法用D3使用可重用的图表框架来做到这一点?

谢谢!

1 个答案:

答案 0 :(得分:1)

我最近遇到了同样的问题。建立一个图表库,在制作新类型的图表时不想复制粘贴所有常用属性。

以下是我提出的解决方案:

Chart = function module() {
        // properties
        this._width = 800;
        this._height = 600;
        this._margin = {
            top: 10,
            bottom: 10,
            left: 20,
            right: 5
        };
        this._title = '';
    }

    // doing stuff
    Chart.prototype.plot = function () {
        console.log('The plot function has not been defined.');
    }

    // setting the properties
    Chart.prototype.width = function (_x) {
        if (!arguments.length) return this._width;
        this._width = _x;
        return this;
    }
    Chart.prototype.height = function (_x) {
        if (!arguments.length) return this._height;
        this._height = _x;
        return this;
    }
    Chart.prototype.margin = function (_x) {
        if (!arguments.length) return this._margin;
        this._margin = _x;
        return this;
    }
    Chart.prototype.title = function (_x) {
        if (!arguments.length) return this._title;
        this._title = _x;
        return this;
    }

    // creating a new type of chart, which inherits from Chart.
    BarChart.prototype = new Chart(); // Here's where the inheritance occurs 
    BarChart.prototype.constructor = BarChart;
    BarChart.prototype.parent = Chart.prototype;

    function BarChart() {
    }
    // 'overriding' the .plot function
    BarChart.prototype.plot = function (_selection) {
        var myTitle = this.parent.title.call(this);
        _selection.each(function (_data) {
            console.log('Plotting ' + _data.length + ' bars of data. The chart is called: ' + myTitle);
        });
    }

    
    
    // usage
    var myBarChart1 = new BarChart();
    myBarChart1.width(250)
        .height(200)
        .title('Population Growth');
    myBarChart1.plot(d3.select("#chart").datum([1, 2, 3, 4, 5, 6])); // Plotting 6 bars of data. The chart is called: Population Growth

    var myBarChart2 = new BarChart();
    myBarChart2.width(50)
        .height(500)
        .title('Music Sales');
    myBarChart2.plot(d3.select("#chart").datum([1, 2, 3, 4])); // Plotting 4 bars of data. The chart is called: Music Sales
 <div id="chart"></div>

这意味着我只需要创建一次公共属性,例如宽度和高度,而不是我创建的每种类型的图表。生成的对象调用可以链接,如d3.js.唯一与d3.js使用不一致的是你必须调用.plot()函数来实际绘制图表。我一直无法弄清楚如何直接从BarChart函数调用它(我尝试从BarChart返回一个绘图函数,但这不起作用)。

如果你想阅读这个主题,这里有一篇关于JavaScript继承的非常棒的文章:http://phrogz.net/JS/classes/OOPinJS2.html