可重复使用的D3图表,带有公共代码分离出来 [英] Reusable D3 chart with common code separated out

查看:119
本文介绍了可重复使用的D3图表,带有公共代码分离出来的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有效的D3线图,使用的框架如下所示: http://bost.ocks。 org / mike / chart /



由于我创建了很多图表,我想分离出公共元素(例如宽度和高度)到一个单独的文件,但我不是真的确定如何在可重用的框架内这样做。



这是调用的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;

功能图(选择){

console.log(main_height);

}

//获取/设置main_width
chart.main_width = function(value){
if(!arguments.length)return main_width;
main_width = value;
return chart;
}

//获取/设置main_height
chart.main_height = function(value){
if(!arguments.length)return main_height;
main_height = value;
return chart;
}

}

multiLineChart具有所有核心逻辑为线图本身。当我运行这个我最终以无法读取属性'main_height'未定义。有没有办法用D3使用可重用的图表框架?



谢谢!

解决方案

我最近遇到了同样的问题。构建一个图表库,并且不想复制并粘贴所有常见的属性,当我制作一种新的图表类型。



这里是我已经提出的解决方案与:



< pre =snippet-code-js lang-js prettyprint-override> Chart = function module(){// properties this._width = 800; this._height = 600; this._margin = {top:10,bottom:10,left:20,right:5}; this._title =''; } //做东西Chart.prototype.plot = function(){console.log('plot函数还没有被定义。 } //设置属性Chart.prototype.width = function(_x){if(!arguments.length)return this._width; this._width = _x;返回这个; } Chart.prototype.height = function(_x){if(!arguments.length)return this._height; this._height = _x;返回这个; } Chart.prototype.margin = function(_x){if(!arguments.length)return this._margin; this._margin = _x;返回这个; } Chart.prototype.title = function(_x){if(!arguments.length)return this._title; this._title = _x;返回这个; } //创建一个新类型的图表,它继承自Chart。 BarChart.prototype = new Chart(); //这里是继承发生的地方BarChart.prototype.constructor = BarChart; BarChart.prototype.parent = Chart.prototype;函数BarChart(){} //覆盖.plot函数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);}); } //用法var myBarChart1 = new BarChart(); myBarChart1.width(250).height(200).title('Population Growth'); myBarChart1.plot(d3.select(#chart)。datum([1,2,3,4,5,6])); //绘制6条数据。图表被称为:Population Growth var myBarChart2 = new BarChart(); myBarChart2.width(50).height(500).title('Music Sales'); myBarChart2.plot(d3.select(#chart)。datum([1,2,3,4])); //绘制4条数据。音乐销售

 < div id = chart>< / div>  



我只需要创建公共属性,如宽度和高度,一次,而不是在我创建的每一种类型的图表。生成的对象调用可以链接,如d3.js。唯一不符合d3.js用法的是,你必须调用.plot()函数来绘制图表。我一直无法弄清楚如何直接从BarChart函数调用(我试过从BarChart返回一个plot函数,但是没有工作)。



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


I have a working D3 line graph using the framework outlined here: http://bost.ocks.org/mike/chart/

Since I am creating a lot of charts I'd like to separate out the common elements (width and height for example) into a separate file, but I'm not really sure how to do that within the re-usable framework.

Here is the calling javascript file:

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);
});

The common file is this:

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;
    }

}

The multiLineChart has all the core logic for the line graph itself. When I run this I end up with Cannot read property 'main_height' of undefined. Is there a way to do this with D3 using the reusable chart framework?

Thanks!

解决方案

I've had the exact same problem recently. Building a library of charts and not wanting to copy-paste all of the common properties when I make a new type of chart.

Here is the solution that I have come up with:

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>

It means that I only have to create common properties, such as width and height, once, rather than in every single type of chart that I create. The resulting object calls can be chained, like d3.js. The only thing that isn't consistent with d3.js usage is that you have to call the .plot() function to actually draw the chart. I've been unable to figure out how to call this directly from the BarChart function (I've tried returning a plot function from BarChart, but that didn't work).

If you want to read around the subject, here is a really great article on inheritance in JavaScript: http://phrogz.net/JS/classes/OOPinJS2.html

这篇关于可重复使用的D3图表,带有公共代码分离出来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆