2017-05-03 31 views
8

我在使用RequireJS加載D3 v4.8和文字雲佈局組件(https://github.com/jasondavies/d3-cloud)時遇到問題。雖然D3.js和d3.layout.cloud.js都正在下載到瀏覽器,但正在拋出異常,表明d3.layout.cloud不是函數。使用RequireJS加載D3和Word Cloud佈局

這裏是我正在配置RequireJS:

require.config({ 
    waitSeconds: 10, 

    baseUrl: './scripts', 

    paths: { 
     d3: 'd3.min', 
     jquery: 'jquery-2.1.0.min', 
     cloud: 'd3.layout.cloud' 
    }, 

    shim: { 


    cloud: { 
     deps:['jquery', 'd3'] 
    } 

} 

}); 

的代碼拋出異常該生產線是d3.layout.cloud()的大小([寬度,高度]),並且可以在被發現。下面的功能:

function wordCloud(selector) { 

    var width = $(selector).width(); 
    var height = $(selector).height(); 

    //var fill = d3.scale.category20(); 

    //Construct the word cloud's SVG element 
    var svg = d3.select(selector).append("svg") 
     .attr("width", width) 
     .attr("height", height) 
     .append("g") 
     .attr("transform", "translate("+ width/2 +","+ height/2 +")") 

    var fill = d3.scale.category20(); 

    //Draw the word cloud 
    function draw(words) { 
     var cloud = svg.selectAll("g text") 
      .data(words, function(d) { return d.text; }) 

     //Entering words 
     cloud.enter() 
      .append("text") 
      .style("font-family", "Impact") 
      .style("fill", function(d, i) { return fill(i); }) 
      .attr("text-anchor", "middle") 
      .attr('font-size', 1) 
      .style("cursor", "hand") 
      .text(function(d) { return d.text; }) 
      .on("click", function (d, i){ 
       window.open("http://www.google.com/?q=" + d.text, "_blank"); 
      }); 

     //Entering and existing words 
     cloud 
      .transition() 
      .duration(600) 
      .style("font-size", function(d) { return d.size + "px"; }) 
      .attr("transform", function(d) { 
       return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
      }) 
      .style("fill-opacity", 1); 

     //Exiting words 
     cloud.exit() 
      .transition() 
      .duration(200) 
      .style('fill-opacity', 1e-6) 
      .attr('font-size', 1) 
      .remove(); 
    } 


    //Use the module pattern to encapsulate the visualisation code. We'll 
    // expose only the parts that need to be public. 
    return { 

     //Recompute the word cloud for a new set of words. This method will 
     // asycnhronously call draw when the layout has been computed. 
     //The outside world will need to call this function, so make it part 
     // of the wordCloud return value. 
     update: function(words) { 

      // min/max word size 
      var minSize = d3.min(words, function(d) { return d.size; }); 
      var maxSize = d3.max(words, function(d) { return d.size; }); 

      var textScale = d3.scale.linear() 
       .domain([minSize,maxSize]) 
       .range([15,30]); 

      d3.layout.cloud().size([width, height]) 
       .words(words.map(function(d) { 
        return {text: d.text, size: textScale(d.size) }; 
       })) 
       .padding(5) 
       .rotate(function() { return ~~(Math.random() * 2) * 90; }) 
       .font("Impact") 
       .fontSize(function(d) { return d.size; }) 
       .on("end", draw) 
       .start(); 
     } 
    } 

} 
+1

謝謝@GerardoFurtado,我會盡快在D3 v3.x上運行我的一個例子。我會讓你知道它是怎麼回事......感謝關於賞金的建議。 – UncleZen

+0

我認爲d3-cloud對d3v4的依賴並不存在問題。查看整個d3-cloud的源代碼[here](https://github.com/jasondavies/d3-cloud/blob/master/index.js),你可以看到唯一的依賴是'd3-dispatch',它我猜想加載就好了。我相信問題在於你試圖將它放入'd3.layout.cloud',因爲在d3v4中'd3.layout'是'undefined'。嘗試將所有對'd3.layout.cloud'的引用更改爲'd3.cloud'(即在require的配置和源代碼中)。 – meetamit

+0

@UncleZen我刪除了我的評論,因爲d3-cloud與D3 v4.x協同工作。 –

回答

3

D3雲的最新版本只依賴於D3-調度,因此能很好地工作D3的任何版本。我認爲這裏的問題是你使用RequireJS(AMD)引用d3.layout.cloud.js文件,但是你沒有使用RequireJS到使用庫(在你的例子中配置爲cloud)。請參閱以下example

requirejs.config({ 
    baseUrl: ".", 
    paths: { 
    cloud: "d3.layout.cloud" // refers to ./d3.layout.cloud.js 
    } 
}); 

requirejs(["cloud"], function(cloud) { // depends on "cloud" defined above 
    cloud() 
    .size([100, 100]) 
    .words([{text: "test"}]) 
    .on("word", function() { 
     console.log("it worked!"); 
    }) 
    .start(); 
}); 

如果你喜歡使用CommonJS的風格require(…)你可以RequireJS如果您在本quick example使用適當的define(…)語法一樣,也用這個。

+0

但'var cloud = require(「cloud」);'不是AMD語法,不會與RequireJS一起使用,會嗎? –

+0

我簡單地調整了我可以找到的第一個RequireJS例子, 它使用'require(...)'[here](https://github.com/volojs/create-template/blob/master/www/app/main。 JS#L9)。 –

+0

啊,我明白了。這個例子不適用於瀏覽器JS運行時,它適用於節點。 –

2

雖然d3-cloud本身與D3 V3和V4兼容,但您會發現大多數示例都不是,而且您的當前代碼不是,它只能與V3一起使用。

要使其與V4一起使用,您需要替換所有對d3.scale的引用。例如,d3.scale.category20()變成d3.scaleOrdinal(d3.schemeCategory20)。 有關與兩者兼容的小型可運行示例,請參見Fiddle #1。它使用RequireJS來加載d3,d3-cloud和jQuery。嘗試更改JS部分頂部的require config中的D3版本。

現在讓我們來看看V3,因爲你的代碼依賴於它。還有幾個問題:

您必須使用d3的對象& d3cloud & jQuery通過調用require獲得。對於RequireJS,這是異步的(因爲它需要以編程方式獲取JS腳本,並且只能在異步執行的瀏覽器中)。你把你的代碼放在一個回調函數中(更多信息請參閱RequireJS文檔):

[編輯:參見Jason的替代語法的答案。 ]

​​

在此情況下(和版本)D3雲的主要功能是不是d3.layout.cloud()下,所以你需要更換與d3cloud(),假設這是回調傳遞給require參數的名稱。

您必須確保您的從未通過寬度或高度0到d3cloud.size([width, height]),否則它將進入無限循環。不幸的是,如果您使用$(selector).height(),這取決於您的頁面內容以及可能的「意外」,很容易發生。例如,我建議var height = $(selector).height() || 10;

不是一個編程問題,但你傳遞給.rotate()的函數取自一個例子,也許你想改變它:它只產生兩個可能的值,0或90,我覺得這是單調的,默認的是漂亮。所以我在下面的例子中完全刪除了這一行。也許你會想要它,只需添加您的.rotate(...)線。

Fiddle #2:一個基於你的代碼段的完整工作示例。