0

plot我是 d3 的新手,对 javascript 也很陌生(我的大部分经验都是使用 python)。我最近学习了 Scott Murray 所著的Interactive Data Visualization: for the web一书中关于创建条形图的教程。我在完成本教程时没有任何问题,但他在书中采用的方法似乎主要是使用全局变量的程序化方法。我想创建一个类似的图表,但使用面向对象的方法能够封装变量并重用代码以在一个脚本中生成多个图表,而无需一遍又一遍地重复代码。这是我到目前为止没有任何运气的尝试:

        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()

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

4

1 回答 1

1

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

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

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

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

我已将您的固定代码放在此处的 jsfiddle 中。

于 2013-04-25T14:29:27.933 回答