2013-04-25 48 views
0

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

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

我敢肯定有一些非常简单的,我做错了,没有人知道这是为什么不工作,或者如果这是连采取正确的方法?任何帮助将非常感激。谢谢。

+0

梅德Soshnikov写了一个非常[简短但甜美的描述](http://dmitrysoshnikov.com/ecmascript/javascript-the-core/)的Javascript的机制值得一读。大部分面向对象的需求可能可以通过在函数中返回一个函数来解决,该函数具有在闭包,封装中设置和捕获的变量。如果您需要扩展基础对象,请查看[Object.create](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create)和Object.defineProperty方法。 – 2013-04-25 14:48:27

回答

1

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

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

两个this引用不同的对象 - 在第二种情况下this是你在工作,没有你指的是该属性的实际DOM元素。

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

我把你的固定代码放在jsfiddle here

+0

谢谢,这是非常有帮助的。正如我所说,我是JavaScript的新手,所以我仍然有困难的时间围绕“这个”关键字。 – 2013-04-25 15:06:01

+0

你会说:“对于更加面向对象的方法,你需要创建一个包含所有信息的对象并传递它,或者实现可以调用的方法。”你有更具体的例子吗?我可以将变量绑定到svg元素而不是“窗口”吗? – 2013-04-25 15:07:17

+0

我在说的是你会创建一个用于属性的自定义对象(也就是通用对象)。将变量绑定到SVG元素不是一个好主意。 – 2013-04-25 15:09:00