codycodes
codycodes

Reputation: 95

D3 Word Cloud Error upon Refresh

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

Answers (1)

torresomar
torresomar

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

Related Questions