2016-10-23 216 views
2

我創造這基於以下數據定義的散點圖的每個點(注意,只有前兩個領域目前正在使用的繪圖):繪製wordcloud在散點圖

var data = [[5,3,"{'text':'word1',size:4},{'text':'word2','size':1}"], 
      [3,5,"{'text':'word3',size:5},{'text':'word4','size':4}"], 
      [1,4,"{'text':'word1',size:3},{'text':'word2','size':5},{'text':'word3','size':2}"], 
      [2,3,"{'text':'word2',size:1},{'text':'word3','size':5}"]]; 

接下來,當我們點擊每個特定指向散點圖,應用程序應該附加一個wordcloud,該變量是從存儲在data變量的第3個字段中的單詞中定義的。我使用Jason Davies的實現wordcloud。目前(爲了演示目的),wordcloud僅由存儲在變量frequency_list中的靜態數據生成。當前的代碼也存儲在JSFiddle

任何想法如何進行?

var data = [[5,3,"{'text':'word1',size:4},{'text':'word2','size':1}"], 
      [3,5,"{'text':'word3',size:5},{'text':'word4','size':4}"], 
      [1,4,"{'text':'word1',size:3},{'text':'word2','size':5},{'text':'word3','size':2}"], 
      [2,3,"{'text':'word2',size:1},{'text':'word3','size':5}"]]; 

var margin = {top: 20, right: 15, bottom: 60, left: 60}, 
    width = 500 - margin.left - margin.right, 
    height = 250 - margin.top - margin.bottom; 

var x = d3.scale.linear() 
    .domain([0, d3.max(data, function(d) { return d[0]; })]) 
    .range([ 0, width ]); 

var y = d3.scale.linear() 
    .domain([0, d3.max(data, function(d) { return d[1]; })]) 
    .range([ height, 0 ]); 

var chart = d3.select('body') 
    .append('svg:svg') 
    .attr('width', width + margin.right + margin.left) 
    .attr('height', height + margin.top + margin.bottom) 
    .attr('class', 'chart') 

var main = chart.append('g') 
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') 
    .attr('width', width) 
    .attr('height', height) 
    .attr('class', 'main') 

// Draw the x axis 
var xAxis = d3.svg.axis() 
    .scale(x) 
    .orient('bottom'); 

main.append('g') 
    .attr('transform', 'translate(0,' + height + ')') 
    .attr('class', 'main axis date') 
    .call(xAxis); 

// draw the y axis 
var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient('left'); 

main.append('g') 
    .attr('transform', 'translate(0,0)') 
    .attr('class', 'main axis date') 
    .call(yAxis); 

var g = main.append("svg:g"); 

g.selectAll("scatter-dots") 
    .data(data) 
    .enter().append("svg:circle") 
    .attr("cx", function (d,i) { return x(d[0]); }) 
    .attr("cy", function (d) { return y(d[1]); }) 
    .attr("r", 5) 
    .on("mouseover", function(){d3.select(this).style("fill", "red")}) 
    .on("mouseout", function(){d3.select(this).style("fill", "black")}); 

// FUNCTION TO DISPLAY CIRCLE 
g.on('mouseover', function(){ 
    div.style("display", "block") 
    d3.select("krog").style("fill", "orange"); 
    generate(); 
}); 

g.on('mouseout', function(){ 
    //div.style("display", "none") 
    div.select("svg").remove(); 
}); 

var div = d3.select("body") 
    .append("div") 
    .attr("class", "tooltip") 
    .style("display", "none"); 


// Functions to draw wordcloud 
var frequency_list = [{"text":"study","size":40},{"text":"motion","size":15},{"text":"forces","size":10},{"text":"electricity","size":15},{"text":"movement","size":10},{"text":"relation","size":5},{"text":"things","size":10},{"text":"force","size":5},{"text":"ad","size":5}]; 

var color = d3.scale.linear() 
      .domain([0,1,2,3,4,5,6,10,15,20,100]) 
      .range(["#ddd", "#ccc", "#bbb", "#aaa", "#999", "#888", "#777", "#666", "#555", "#444", "#333", "#222"]); 

// Generates wordcloud 
function generate(){ 
    d3.layout.cloud().size([800, 300]) 
    .words(frequency_list) 
    .rotate(0) 
    .fontSize(function(d) { return d.size; }) 
    .on("end", draw) 
    .start(); 
} 

function draw(words) { 
    d3.select("div").append("svg") 
    .attr("width", 850) 
    .attr("height", 350) 
    .attr("class", "wordcloud") 
    .append("g") 
    // without the transform, words words would get cutoff to the left and top, they would 
    // appear outside of the SVG area 
    .attr("transform", "translate(320,200)") 
    .selectAll("text") 
    .data(words) 
    .enter().append("text") 
    .style("font-size", function(d) { return d.size + "px"; }) 
    .style("fill", function(d, i) { return color(i); }) 
    .attr("transform", function(d) { 
     return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; 
    }) 
    .text(function(d) { return d.text; }); 
} 

回答

3

這裏有幾個問題。

首先,您的數據包含單詞的字符串。我改變了對對象的數組:

var data = [[5,3,[{'text':'word1',size:4},{'text':'word2','size':1}]], 
     [3,5,[{'text':'word3',size:5},{'text':'word4','size':4}]], 
     [1,4,[{'text':'word1',size:3},{'text':'word2','size':5},{'text':'word3','size':2}]], 
     [2,3,[{'text':'word2',size:1},{'text':'word3','size':5}]]]; 

在那之後,我改變了功能draw:不是每次盤旋了一圈的時間追加一個新的div,它只是改變了DIV內容:

div.append("svg") 
    .attr("width", 300) 
    .attr("height", 300) 
    .attr("class", "wordcloud") 
    .append("g") 

但是現在發生了最重要的變化:

每當用戶將鼠標懸停在圓上,但您正在爲組元素調用鼠標懸停時,您正在顯示wordcloud。這樣,我們無法訪問綁定到每個特定圓的數據。

取而代之的是,我們將設置一個變量的圓圈:

var circle = g.selectAll("scatter-dots") 
    .data(data) 
    .enter() 
    .append("svg:circle"); 

因此,我們可以得到數據爲每個盤旋循環,這是陣列中的第三個元素:

circle.on('mouseover', function(d){ 
    div.style("display", "block") 
    d3.select("krog").style("fill", "orange"); 
    generate(d[2]);//here, d[2] is the third element in the data array 
}); 

而且我們經過了第三個要素(d[2])的功能generate爲名爲thisWords參數:

function generate(thisWords){ 
    d3.layout.cloud().size([800, 300]) 
    .words(thisWords) 
    .rotate(0) 
    .fontSize(function(d) { return d.size; }) 
    .on("end", draw) 
    .start(); 
} 

這裏是你的小提琴:https://jsfiddle.net/jwrbps4j/

PS:你將不得不改善translate這個詞。