Reputation: 95
I keep getting the error: Error: attribute transform: Expected number, "translate(,)rotate(0)" when the word cloud tries to update. All the words then stack on top of each other. Any reason it would work on the first pass but not the second?
var words = [{"text" : "One", "size" : 10}, {"text" : "Two", "size" : 10},
{"text" : "Three", "size" : 10}, {"text" : "Four", "size" : 10}, {"text" : "Five", "size" : 10},
{"text" : "Six", "size" : 10}, {"text" : "Seven", "size" : 10}, {"text" : "Eight", "size" : 10},
{"text" : "Nine", "size" : 10}, {"text" : "Ten", "size" : 10}, {"text" : "Eleven", "size" : 10},
{"text" : "Twelve", "size" : 10}, {"text" : "Thirteen", "size" : 10}, {"text" : "Fourteen", "size" : 10},
{"text" : "Fifteen", "size" : 10}, {"text" : "Sixteen", "size" : 10}, {"text" : "Seventeen", "size" : 10},
{"text" : "Eighteen", "size" : 10}, {"text" : "Nineteen", "size" : 10}, {"text" : "Twenty", "size" : 10}];
localStorage.setItem('words', JSON.stringify(words));
var duration = 50;
var cloudGroup = d3.select("#d3").append("svg")
.attr("width", 1000)
.attr("height", 1000)
.append("g")
.attr("transform", "translate(500,500)");
d3.layout.cloud()
.size([1000, 1000])
.words(words.map(function(d) {
var result = {text: d.text, size: d.size};
return result;
}))
.padding(0)
.rotate(0)
.font("Impact")
.fontSize(function(d) { return 10; })
.on("end", draw)
.start();
function draw(words) {
cloudData = cloudGroup
.selectAll("text")
.data(words);
// This part should deal with (newly) entering data
cloudData.enter().append("text")
.style("font-size", "0px")
.style("font-family", "Impact")
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.attr("class", "word")
.attr("id", function(d){
return d.text
})
.text(function(d) { return d.text; })
.transition().duration(duration).style("font-size", function(d) { return d.size + "px"; });
// This with updating existing data
cloudData
.transition().duration(duration).style("font-size", "0px")
.remove()
.style("font-size", "0px")
.text(function(d) { return d.text; })
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(0)";
})
.transition().duration(duration).style("font-size", function(d) { return d.size + "px"; });
cloudData.exit()
.transition()
.duration(200)
.style('fill-opacity', 1e-6)
.attr('font-size', 1)
.remove();
}
$('.word').on({
'click' : function(){
var clickedWord = this.id;
var words = JSON.parse(localStorage.getItem('words'));
for(var i in words){
if(words[i].text == clickedWord){
words[i].size += 1;
}
}
localStorage.setItem('words', JSON.stringify(words));
update();
}
});
function update() {
words = JSON.parse(localStorage.getItem('words'));
draw(words);
}
Upvotes: 4
Views: 638
Reputation: 2229
Wouldn't you have to update the cloud.layout
at your update function? I altered your code in order to get the following result.
var words = [{
"text": "One",
"size": 10
}, {
"text": "Two",
"size": 10
}, {
"text": "Three",
"size": 10
}, {
"text": "Four",
"size": 10
}, {
"text": "Five",
"size": 10
}, {
"text": "Six",
"size": 10
}, {
"text": "Seven",
"size": 10
}, {
"text": "Eight",
"size": 10
}, {
"text": "Nine",
"size": 10
}, {
"text": "Ten",
"size": 10
}, {
"text": "Eleven",
"size": 10
}, {
"text": "Twelve",
"size": 10
}, {
"text": "Thirteen",
"size": 10
}, {
"text": "Fourteen",
"size": 10
}, {
"text": "Fifteen",
"size": 10
}, {
"text": "Sixteen",
"size": 10
}, {
"text": "Seventeen",
"size": 10
}, {
"text": "Eighteen",
"size": 10
}, {
"text": "Nineteen",
"size": 10
}, {
"text": "Twenty",
"size": 10
}];
var duration = 50;
var cloudGroup = d3.select("#d3").append("svg")
.attr("width", 500)
.attr("height", 500)
.append("g")
.attr("transform", "translate(150,150)");
d3.layout.cloud()
.size([500, 500])
.words(words.map(function(d) {
var result = {
text: d.text,
size: d.size
};
return result;
}))
.padding(0)
.rotate(0)
.font("Impact")
.fontSize(function(d) {
return 10;
})
.on("end", draw)
.start();
function draw(words) {
cloudData = cloudGroup.selectAll("text").data(words);
// This part should deal with (newly) entering data
cloudData.enter().append("text")
.style("font-size", "0px")
.style("font-family", "Impact")
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.attr("class", "word")
.attr("id", function(d) {
return d.text
})
.text(function(d) {
return d.text;
})
.transition().duration(duration).style("font-size", function(d) {
return d.size + "px";
});
// This with updating existing data
cloudData
.transition().duration(duration).style("font-size", "0px")
.remove()
.style("font-size", "0px")
.text(function(d) {
return d.text;
})
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(0)";
})
.transition().duration(duration).style("font-size", function(d) {
return d.size + "px";
});
cloudData.exit()
.transition()
.duration(200)
.style('fill-opacity', 1e-6)
.attr('font-size', 1)
.remove();
}
$('.word').on({
'click': function() {
var clickedWord = this.id;
for (var i in words) {
if (words[i].text === clickedWord) {
words[i].size += 4;
}
}
update(words);
}
});
function update() {
d3.layout.cloud()
.size([500, 500])
.words(words.map(function(d) {
var result = {
text: d.text,
size: d.size
};
return result;
}))
.padding(0)
.rotate(0)
.font("Impact")
.fontSize(function(d) {
return d.size;
})
.on("end", draw)
.start();
}
<div id="d3">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://code.jquery.com/jquery-2.2.3.min.js" integrity="sha256-a23g1Nt4dtEYOj7bR+vTu7+T8VP13humZFBJNIYoEJo=" crossorigin="anonymous"></script>
<script src="https://www.jasondavies.com/wordcloud/cloud.min.js"></script>
Upvotes: 1