尝试使用面向对象的方法在d3中生成条形图

时间:2013-04-25 14:14:57

标签: javascript d3.js

plot我是d3的新手,也是javascript的新手(我的大部分经验都是使用python)。我最近通过Scott Murray创建条形图的书“交互式数据可视化:网络”中的教程。我没有完成本教程的任何问题,但他在本书中采用的方法似乎主要是使用全局变量的程序。我想创建一个类似的图表,但使用面向对象的方法能够封装变量并重用代码在一个脚本中生成多个图表,而不必反复重复代码。这是我到目前为止没有运气的尝试:

        function d3Chart(id, data, width, height, padding) {
            this.id = id
            this.data = data
            this.width = width
            this.height = height
            this.padding = padding
            this.svg =  d3.select("body")
                .append("svg")
                .attr("width", width)
                .attr("height", height)
                .attr("class", "chart")
                .attr("id". this.id);
            this.yscale = d3.scale.linear()
                .domain([0, d3.max(data)])
                .range([h - padding, padding])
            this.xscale = d3.scale.ordinal()
                .domain(d3.range(data.length))
                .rangeRoundBands([padding,w-padding], 0.05)
        };

        d3Chart.prototype.rect = function() {

            this.rect = this.svg.selectAll("rect")
                .data(this.data)
                .enter()
                .append("rect");
        }

        d3Chart.prototype.plot = function() {

             this.rect.attr("x", function(d, i) {
                    return this.xscale(i);
                })
                .attr("y", function (d) {
                    return this.yscale(d);
                })
                .attr("width", this.xscale.rangeBand())
                .attr("height", function(d) {
                    return this.height - this.padding - this.yscale(d);
                })
                .attr("fill", function(d) {
                    return "rgb(" + (100 - d) + ", 0, " + (d*10) + ")";
                });
            }

        var chart = new d3Chart("chart1", [5, 15, 10, 30, 20, 45, 15, 10, 5], 600, 400, 40);
        chart.rect()
        chart.plot()

我确信有一些非常简单的事我做错了,有谁知道为什么这不起作用,或者这是否是正确的方法?任何帮助将非常感激。感谢。

1 个答案:

答案 0 :(得分:1)

您的代码的第一个问题是,您有一些拼写错误,例如.代替,h代替height。第二个问题是你将所有内容都设为this的属性,这在不同的上下文中会有所不同。例如,在

this.rect.attr("x", function(d, i) {
                return this.xscale(i);
            })

两个this引用不同的对象 - 在第二种情况下this是您正在操作的实际DOM元素,并且没有您所指的属性。

因此,您需要将所有内容保存到全局对象的属性中,例如window。这当然不比使用全局变量好多少。对于更加面向对象的方法,您需要创建一个包含所有信息的对象并传递它,或者实现可以在其上调用的方法。

我已将您的固定代码放入jsfiddle here