2013-04-25 47 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