2014-03-19 23 views
1

平滑过渡我有一个d3.js树形图,每次服务器发出更新时都会ping通。更新内容来自twitter流;有很多更新。因此,treemap在动画中非常生涩,因为它在1500 ms转换完成之前已经更新了多次。如何使用d3 + socket.io

是否可以将更新节点值的代码与更新视图的代码分开?我希望能够找到一个解决方案,不断更新树形图的值,但只是每1500到2000毫秒更新一次视图。

请参阅我的全部d3 script

var socket = io.connect(); 

var margin = {top: 40, right: 10, bottom: 10, left: 10}, 
    width = 1000 - margin.left - margin.right, 
    height = 650 - margin.top - margin.bottom; 

var color = d3.scale.category20c(); 

var treemap = d3.layout.treemap() 
    .size([width, height]) 
    .sticky(false) 
    .value(function(d) { return d.size; }); 

var div = d3.select("body").append("div") 
    .style("position", "relative") 
    .style("width", (width + margin.left + margin.right) + "px") 
    .style("height", (height + margin.top + margin.bottom) + "px") 
    .style("left", margin.left + "px") 
    .style("top", margin.top + "px"); 

var root; 

socket.on('update', function(stream) { 
    console.log('tweets') 

    div.datum(root).selectAll(".node").remove(); 

    root = stream.masterlist; 

    var node = div.datum(root).selectAll(".node") 
     .data(treemap.nodes) 
    .enter().append("div") 
     .attr("class", "node") 
     .call(position) 
     .style("background", function(d) { return d.children ? color(d.name) : null; }) 
     .text(function(d) { return d.children ? null : d.name; }); 

    d3.selectAll("input").on("change", function change() { 
    var value = this.value === "count" 
     ? function() { return 1; } 
     : function(d) { return d.size; }; 

    node 
     .data(treemap.value(value).nodes) 
     .transition() 
     .duration(1500) 
     .call(position); 
    }); 
}); 

function position() { 
    this.style("left", function(d) { return d.x + "px"; }) 
     .style("top", function(d) { return d.y + "px"; }) 
     .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; }) 
     .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; }); 
} 

此代码是从treemap example优秀bl.ocks.org网站上取出,用细微的变化(我的数据来自一个回调,而不是一个JSON)。我试图从视图逻辑中将setInterval()的值逻辑拆分为socket.on()之外,但是我的尝试要么不能减慢转换速度,要么完全破坏树形图。

d3.selectAll("input").on("change", function change() { 
    var value = this.value === "count" 
     ? function() { return 1; } 
     : function(d) { return d.size; }; 

    }); 
}); // end socket.on(); 

setInterval(function() { 
    node 
     .data(treemap.value(value).nodes) 
    .transition() 
     .duration(1500) 
     .call(position); 
    }, 2000); 

非常感谢任何见解!

回答

0

你想要做的就是所谓的去抖动。有几个JavaScript库有你可以使用的(我使用下划线)。你也可以自己写一个。我发现这是在a blog post

function debounce(fn, delay) { 
    var timer = null; 
    return function() { 
    var context = this, args = arguments; 
    clearTimeout(timer); 
    timer = setTimeout(function() { 
     fn.apply(context, args); 
    }, delay); 
    }; 
} 

一旦你有你实现或者偷了去抖动功能,剩下的就是简单:你只是包装可以满足您的更新与防抖动功能:

socket.on('update', debounce(function(stream) { 
    console.log('tweets') 
    ... 
}));