1. 程式人生 > >D3.js建立力導向圖(V4)附帶詳細的引數說明

D3.js建立力導向圖(V4)附帶詳細的引數說明

一.程式碼示例

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>D3 test</title>
</head>

<
body> <div class="container"> <div id="graph"></div> </div> </body> </html> <script src="/static/js/d3-v4.js"></script> <script> var nodes = [ { name: "桂林" }, { name: "廣州" }, { name: "廈門" }, { name: "杭州" }, {
name: "上海" }, { name: "青島" }, { name: "天津" } ]; var links = [ { source : 0 , target: 1 } , { source : 0 , target: 2 } , { source : 0 , target: 3 } , { source : 1 , target: 4 } , { source : 1 , target: 5 } , { source : 1 , target: 6 } ]; var width =
800; var height = 600; var svg = d3.select("#graph") .append("svg") .attr("width", width) .attr("height", height) .call(d3.zoom() //建立縮放行為 .scaleExtent([-5, 2]) .on('zoom',zoom_actions)); //設定縮放範圍 //初始化力學模擬器,通過佈局函式格式化資料 var simulation = d3.forceSimulation(nodes) .force("link", d3.forceLink(links).distance(100)) //distance設定連線距離 .force("charge", d3.forceManyBody().strength(-100)) //注1> .force("center", d3.forceCenter(width / 2, height / 2)) //設定力學模擬器的中心 .on("tick", ticked); //佈局函式格式化後的資料,注2> console.log('nodes', nodes); console.log('links', links); var color = d3.scaleOrdinal(d3.schemeCategory20); //生成顏色選擇器函式,此函式返回顏色陣列 (string []) //新增group包裹svg元素以進行縮放,目的是在縮放時不會影響整個容器的位置 var g = svg.append("g") .attr("class", "everything"); // 繪製連線 var svg_links = g.append('g') .selectAll("line") .data(links) .enter() .append("line") .style("stroke", "#ccc") .style("stroke-width", 3) // 繪製節點 var svg_nodes = g.append('g') .selectAll("circle") .data(nodes) .enter() .append("circle") .attr("r", '20') .style("fill", function (d, i) { return color(i); }).call(d3.drag().on("start", dragstarted) //d3.drag() 建立一個拖曳行為 .on("drag", dragged) .on("end", dragended)); //繪製描述節點的文字 var svg_texts = g.append('g') .selectAll("text") .data(nodes) .enter() .append("text") .style("fill", "black") .attr("dx", 20) .attr("dy", 8) .text(function (d) { return d.name; }); //監聽拖拽開始 function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); //alpha是動畫的冷卻係數,運動過程中會不斷減小,直到小於0.005為止,此時動畫會停止。 d.fx = d.x; //fx為固定座標,x為初始座標 注3> d.fy = d.y; } //監聽拖拽中 function dragged(d) { d.fx = d3.event.x; //fevent.x為拖拽移動時的座標 d.fy = d3.event.y; } //監聽拖拽結束 function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; //固定座標清空 d.fy = null; } function zoom_actions() { g.attr("transform", d3.event.transform) } //拖拽時的事件監聽器 以實時更新座標 function ticked() { svg_links.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; }); svg_nodes.attr("cx", function (d) { return d.x; }) .attr("cy", function (d) { return d.y; }); svg_texts.attr("x", function (d) { return d.x; }) .attr("y", function (d) { return d.y; }); } </script>

二.註釋詳解

相關函式的說明在程式碼的註釋中已經寫的很清楚了,下面我針對以上註釋中的注1>,2>,3>做一些詳細的解釋。

1> forceManyBody()函式為建立多體力函式,strength為相互作用力,正的為吸力,負的為斥力,何為多體力?你可以把它理解成是一個建立作用力,設定作用力閾值和計算作用力大小的高階函式

這是github上D3.js對於forceManyBody()的解釋。

在這裡插入圖片描述

簡單來說,就是此函式可以建立一個帶參的多體力物件,此物件中有一些函式,咱們可以呼叫,具體有如下幾個函式:

在這裡插入圖片描述 strength,distanceMindistanceMax都是字面意思,無需多說,我稍微解釋下theta函式。

我先放上github官網上對於此manyBody.theta()函式的解釋。 在這裡插入圖片描述 什麼意思呢?簡單來說,就是這個函式用來計算你每個節點所受到的其他所有節點的合力的近似值,而theta函式就是用來設定此近似值的精度,官方給了一個預設值是0.9。

我們可以看到,這個函式依賴的是Barnes-Hut演算法,那麼何為Barnes-Hut?

Barnes-Hut演算法是一種用於實現N體問題(n-body)模擬的近似演算法。

以下是維基百科的解釋在這裡插入圖片描述 上面那一堆東西就是說,這個演算法是從節點的根資料開始遞迴,並遵循一定的原則,最終計算出合力。具體規則如下:

1.如果當前節點是一個外部節點(而且它不是物體bb),計算當前節點施加在物體bb上的力,並將其加到bb的合力上。 2.計算商s/ds/d的值。如果s/d<θs/d<θ,將這個內部節點看成一個單獨的物體 3.計算其施加在物體bb上的力,並將其加到bb的合力上。否則,在當前節點的每個孩子節點上遞迴地執行上述步驟。

三.參考文章