D3 Library — How To Access Data from JSON in this example
d3.js
Solution
I suggest you should use the built-in import function for json instead of php. I think that the problem you have is that the reading of the data is asynchronous, so `words` is not filled before using it in clouds.
The principle behind `d3.json()` is to do everything in this function, which will be executed when the json is loaded:
var data; // a global
d3.json("path/to/file.json", function(error, json) {
if (error) return console.warn(error);
data = json;
visualizeit();
});
EDIT
Here is an example of the code that should work, I just added the d3 cloud example inside the json function.
d3.json("../../../assets/json/tweetTags.json", function(error, json) {
if (error) return console.warn(error);
var fill = d3.scale.category20();
d3.layout.cloud().size([300, 300])
.words([ // To be replaced with data
"Hello", "world", "normally", "you", "want", "more", "words",
"than", "this"].map(function(d) {
return {text: d, size: 10 + Math.random() * 90};
}))
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size; })
.on("end", draw)
.start();
function draw(words) {
d3.select("body").append("svg")
.attr("width", 300).attr("height", 300)
.append("g").attr("transform", "translate(150,150)")
.selectAll("text").data(words)
.enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.text; });
}
})
Then, when this version works you can just replace the `.words()` by:
.words(json.map(function(d) {
return {text: d.word, size: d.sentiment * 40, tweet: d.tweet};
}))
Problem
I didn't explain the issue properly in the title... Sorry. I'm following the D3 Tag Cloud Simple example https://github.com/jasondavies/d3-cloud/blob/master/examples/simple.html I have a JSON file that consists of tweet tags, sentimental values and tweet text; (excerpt) ``` var words = [{"word":"disgrace","sentiment":"0.975","tweet":"Wheres Fred the weatherman? \nIn jail #disgrace #dirtyman @MrJimmyCorkhill"},{"word":"dirtyman","sentiment":"0.975","tweet":"Wheres Fred the weatherman? \nIn jail #disgrace #dirtyman @MrJimmyCorkhill"}]; ``` I want to use the "tweet" value as a 'title' element of each 'text' element. I tried doing this by putting my tweet in the .words function (or .map, I don't know :s), as other data is accessed that way, but I can't extract my 'tweet' data; ``` var fill = d3.scale.category20(); var words = <?php echo $tweets->getTweetTags(); ?>; d3.layout.cloud().size([1000, 1000]) .words(words.map(function(d) { return {text: d.word, size: d.sentiment * 40, tweet: d.tweet}; })) .rotate(function() { return ~~(Math.random() * 2) * Math.random() * 1; }) .font("Impact") .fontSize(function(d) { return d.size; }) .on("end", draw) .start(); function draw(words) { d3.select("#vis").append("svg") .attr("width", 1000) .attr("height", 1000) .append("g") .attr("transform", "translate(500,400)") .selectAll("text") .data(words) .enter().append("text") .style("font-size", function(d) { return d.size + "px"; }) .style("font-family", "Impact") .style("fill", function(d, i) { return fill(i); }) .attr("text-anchor", "middle") .attr("transform", function(d) { return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; }) .text(function(d) { return d.text; }) .append("svg:title").text(function(d) { return d.tweet; } ); } ``` d.tweet returns undefined I can probably understand why I can't use my tweet in the .words or .map function, as they only expect certain parameters, but I don't know how else to get the 'tweet' data into the 'title' tags of each 'text' element. Can anyone help me with this? Edit: Code with inside d3.json function; ``` var data; // a global d3.json("../../../assets/json/tweetTags.json", function(error, json) { if (error) return console.warn(error); data = json; var fill = d3.scale.category20(); d3.layout.cloud().size([1000, 1000]) .words(data.map(function(d) { return {text: d.word, size: d.sentiment * 40, tweet: d.tweet}; })) .rotate(function() { return ~~(Math.random() * 2) * Math.random() * 1; }) .font("Impact") .fontSize(function(d) { return d.size; }) .on("end", draw) .start(); function draw(data) { d3.select("#vis").append("svg") .attr("width", 1000) .attr("height", 1000) .append("g") .attr("transform", "translate(500,400)") .selectAll("text") .data(words) .enter().append("text") .style("font-size", function(d) { return d.size + "px"; }) .style("font-family", "Impact") .style("fill", function(d, i) { return fill(i); }) .attr("text-anchor", "middle") .attr("transform", function(d) { return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; }) .text(function(d) { return d.text; }) .append("svg:title").text(function(d) { return d.tweet; } ); } d3.layout.cloud().size([300, 300]) .data.map(function(d) { return {text: d, size: 10 + Math.random() * 90}; }) .rotate(function() { return ~~(Math.random() * 2) * 90; }) .font("Impact") .fontSize(function(d) { return d.size; }) .on("end", draw) .start(); }); ``` I don't know how to get it working in like that. I have made the json file but now I can't access the data or run the cloud. Edit: The text elements are appending outside of the closing body tag now :( ``` var data; // a global d3.json("../../../assets/json/tweetTags.json", function(error, json) { if (error) return console.warn(error); data = json; var fill = d3.scale.category20(); d3.select("#vis").append("svg") .attr("width", 1000) .attr("height", 1000) .append("g") .attr("transform", "translate(500,400)") .data(json) .enter().append("text") .style("font-size", function(d) { return d.sentiment * 40 + "px"; }) .style("font-family", "Impact") .style("fill", function(d, i) { return fill(i); }) .text(function(d) {return d.word;}) .append("svg:title").text(function(d) { return d.tweet; } ); }); ``` Edit: @Chris This is your exampled code in the D3 json function and with my customisations ``` d3.json("../../../assets/json/tweetTags.json", function(error, json) { if (error) return console.warn(error); var fill = d3.scale.category20(); d3.layout.cloud().size([600, 500]) .words(json.map(function(d) {; return {text: d.word, size: d.sentiment * 40, tweet: d.tweet}; })) .rotate(function(d) { return ~~(Math.random() * 2) * 90; }) .font("Impact") .fontSize(function(d) { return d.size; }) .on("end", draw) .start(); function draw(words) { d3.select("body").append("svg") .attr("width", 600).attr("height", 500) .append("g").attr("transform", "translate(350,350)") .selectAll("text").data(words) .enter().append("text") .style("font-size", function(d) { return d.size + "px"; }) .style("font-family", "Impact") .style("fill", function(d, i) { return fill(i); }) .attr("text-anchor", "middle") .attr("transform", function(d) { return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")"; }) .text(function(d) { return d.text; }).append("svg:title") .text(function(d) { return d.tweet; } ); } }) ``` But I can't access d.tweet from the draw function :s