過去一段時間曾兩次使用了 D3 力導向圖來描繪族羣關係。node
http://bl.ocks.org/mbostock/1062288git
第一次用的時候不求甚解,交差了事。當時點也很少,很順利完成了任務。這一次確不一樣,每一個圖裏要渲染的有成千上萬個點,每次渲染都死慢死慢,一大堆點動來動去,動半天才穩定下來,這一晃幾分鐘過去了。github
閱讀了一下官方文檔 ,發現問題出來 tick
上。post
force.start() 後,有一個計時器不停地觸發 tick 直到全部節點最終受力平衡穩定下來。this
能夠理解爲,有個計時器不停在打點,每打一次點須要觸發一次 tick() 裏的動做。而 tick() 的默認動做是重繪全部節點和連線位置。由於圖形渲染須要時間長,渲染的次數又多,因此須要等很長時間。spa
function tick() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }
怎樣加快出圖的速度呢?或者說,能不能不看中間複雜的變化過程,只看最終穩定的結果?rest
從官方文檔裏查到 alpha 參數。這個值最開始是 1,隨着圖形趨於穩定,它也會逐漸趨近 0。code
force.alpha([value])ci
Gets or sets the force layout's cooling parameter, alpha. If value is specified, sets alpha to the specified value and returns the force layout. If value is greater than zero, this method also restarts the force layout if it is not already running, dispatching a "start" event and enabling the tick timer. If value is nonpositive, and the force layout is running, this method stops the force layout on the next tick and dispatches an "end" event. If value is not specified, this
method returns the current alpha value.文檔
因而,對原來的代碼稍做修改:
force.on("tick", function () { if(force.alpha()<=0.05){ // 足夠穩定時,才渲染一次 link.attr("x1", function (d) { return d.source.x; }) .attr("y1", function (d) { return d.source.y; }) .attr("x2", function (d) { return d.target.x; }) .attr("y2", function (d) { return d.target.y; }); node.attr("cx", function (d) { return d.x; }) .attr("cy", function (d) { return d.y; }); force.stop(); // 渲染完成後當即中止刷新 } });
這樣修改以後,一個上萬節點的圖,一般在幾秒內就能夠繪製完成了。好比出這麼個圖,幾秒鐘就搞定了。