使用新数据更新/修改d3字云

时间:2016-06-01 14:50:12

标签: javascript d3.js word-cloud

我正试图弄清楚如何使用d3.js wordcloud从一系列数据中修改和更新。

目前,我根据索引键显示选择数据的前10个结果。我希望能够根据键切换这些数据,或者如果我想要前10个或后10个单词。

这是迄今为止的一个方面;

http://plnkr.co/edit/cDTeGDaOoO5bXBZTHlhV?p=preview

我一直在尝试引用这些指南,General Update Pattern, IIIAnimated d3 word cloud。但是,我很难理解如何引入最终更新功能,因为几乎所有引用它的指南通常都使用setTimeout来演示如何更新,而我的大脑只是不会建立连接。

欢迎任何建议!

干杯,

(此处为代码)

var width = 455;
var height = 310;
var fontScale = d3.scale.linear().range([0, 30]);
var fill = d3.scale.category20();

var svg = d3.select("#vis").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")")
    // .selectAll("text")

d3.json("data.json", function(error, data) {
    if (error) {
        console.log(error)
    }
    else {
        data = data
    }

    function sortObject(obj) {
        var newValue = [];
        var orgS = "MC";
        var dateS = "Jan";
        for (var question = 0; question < data.questions.length; question++) {
            var organization = data.organizations.indexOf(orgS);
            var date = data.dates.indexOf(dateS);
            newValue.push({
                label: data.questions[question],
                value: data.values[question][organization][date]
            });
        }
        newValue.sort(function(a, b) {
            return b.value - a.value;
        });
        newValue.splice(10, 50)
        return newValue;
    }
    var newValue = sortObject();


    fontScale.domain([
        d3.min(newValue, function(d) {
            return d.value
        }),
        d3.max(newValue, function(d) {
            return d.value
        }),
    ]);

    d3.layout.cloud().size([width, height])
        .words(newValue)
        .rotate(0)
        .text(function(d) {
            return d.label;
        })
        .font("Impact")
        .fontSize(function(d) {
            return fontScale(d.value)
        })
        .on("end", draw)
        .start();

    function draw(words) {
        var selectVis = svg.selectAll("text")
            .data(words)
        selectVis
            .enter().append("text")
            .style("font-size", function(d) {
                return fontScale(d.value)
            })
            .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.label;
            })

        selectVis
            .transition()
            .duration(600)
            .style("font-size", function(d) {
                return fontScale(d.value)
            })
            .attr("transform", function(d) {
                return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
            })
            .style("fill-opacity", 1);

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

1 个答案:

答案 0 :(得分:4)

我没有在您的代码中看到任何更新功能,因此我添加了该功能,以便了解更新的工作原理。

// Add a select elemnt to the page
var dropDown = d3.select("#drop")
    .append("select")
    .attr("name", "food-venues");
// Join with your venues
var foodVenues = data.organizations.map(function(d, i) {
    return d;
})
// Append the venues as options
var options = dropDown.selectAll("option")
    .data(foodVenues)
    .enter()
    .append("option")
    .text(function(d) {
        return d;
    })
    .attr("value", function(d) {
        return d;
    })
// On change call the update function
dropDown.on("change", update);

为了使d3字云正确更新,您需要再次使用所需数据计算布局

function update() {
  // Using your function and the value of the venue to filter data
  var filteredData = sortObject(data, this.value);
  // Calculate the new domain with the new values
  fontScale.domain([
    d3.min(newValue, function(d) {
      return d.value
    }),
    d3.max(newValue, function(d) {
      return d.value
    }),
  ]);
  // Calculate the layout with new values
  d3.layout.cloud()
    .size([width, height])
    .words(filteredData)
    .rotate(0)
    .text(function(d) {
      return d.label;
    })
    .font("Impact")
    .fontSize(function(d) {
      return fontScale(d.value)
    })
    .on("end", draw)
    .start();
}

我修改了你的sortObject函数以接收一个额外的参数,这是一个理想的场所:

function sortObject(obj, venue) {
  var newValue = [];
  var orgS = venue || "MC";
  // ....
}

这是工作的plnkr:http://plnkr.co/edit/B20h2bNRkyTtfs4SxE0v?p=preview

您应该可以使用此方法更新所需的限制。您可以添加一个带有事件侦听器的复选框,该事件侦听器将触发更新功能。

在你的HTML中:

<input checked type="checkbox" id="top" value="true"> <label for="top">Show top words</label>

在你的javascript中:

var topCheckbox = d3.select('#top')
  .on("change", function() {
    console.log('update!')
  });