D3+mysql 画Force图
来源:互联网 发布:origin点显示数据 编辑:程序博客网 时间:2024/06/11 17:41
先上图再解释。
所谓力学图(Force),就是用点和线来表示各点之间的关系。比如上面这张错综复杂的关系,就是由一个json数组,然后利用D3画图来得到的。
之前学D3,一直停留在给他数据,然后用layout布局,再用不同的图表的格式来画图就好了。而数据,不是自己写死的,就是从一个json文件或者csv文件读出来的。这样显然不实用,我们实际用到的数据,多数是从数据库读出来的。于是上周就接到了任务,用动态数据来画D3的Force图。
做之前思考了一下,任务的重点就是构造数据。把数据库中读出来的数据构造为标准的json格式提供给D3的接口。说白了,就是字符串的拼接。
还有一个问题是根据要求,从数据库中查数据。这个就需要一定的mysql基础,这里不详细说了。
下面看一下我纠结了很久的代码吧。
<?php $con= mysql_connect("localhost","root","root"); if(!$con) { die('Could not connect: ' . mysql_error()); } mysql_select_db("test", $con); mysql_query('set names utf8'); $des = isset($_REQUEST['Target'])?($_REQUEST['Target']):""; $sql = "select distinct Target,IPaddress from tknifelog where Target= '{$des}' "; $query = mysql_query($sql); while($result= mysql_fetch_assoc($query)){ $data[]=$result; } //一层关系 $p=0; $source = 0; $source1 = 0; foreach ($data as $row ){ $Target = $row['Target']; $IPaddress = $row['IPaddress']; //nodes0 if($p++==0){ $node[]= '{"name":"'.$Target.'","group":1}'; } $node[]= '{"name":"'.$IPaddress.'","group":1}'; //links0 $source++; $link .= '{"source":'.$source.',"target":0,"value":'.rand(1,10).'},'; $target = $source; $source1= $source; //二层关系 $sql1 = "select distinct Target,IPaddress from tknifelog where IPaddress = '{$IPaddress}'"; $query1 = mysql_query($sql1); while ($result1 = mysql_fetch_assoc($query1)) { $data1[] = $result1; } foreach ($data1 as $row1) { $Target1 = $row1['Target']; $IPaddress1 = $row1['IPaddress']; //nodes1 if (!in_array('{"name":"'.$Target1.'","group":2}',$node)) { $node[]= '{"name":"'.$Target1.'","group":2}'; //links1 $source1++; $link .= '{"source":'.$source1.',"target":'.$target.',"value":'.rand(1,10).'},'; $source++; } } } $json_n = json_encode($node); $nodes = '{"nodes":'. $json_n ; $json_l= json_encode($link); $links = '"links":['.$json_l.']}'; $json_f = $nodes.$links; $new1 = str_replace('\"','"',$json_f); $new2 = str_replace('"{','{',$new1); $new3 = str_replace('}"','}',$new2); $new4 = str_replace('}]"','}],"', $new3); $json = str_replace('},"]}','}]}', $new4);file_put_contents("force.json",$json); // echo "json文件已生成"; ?><html><head> <meta charset="utf-8"> <title>Force</title> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"><style>.link { stroke: #666;}.node text { pointer-events: none; font: 10px sans-serif;.container { margin-top: 30px;}}</style></head><body> <div class="container"> <div class="row"> <div class="col-md-3"> <table class="table"> <thead> <tr> <th>Target</th> <th>Source</th> </tr> </thead> <tbody> <?php foreach($data as $row){ ?> <tr> <td><a href="test.php?Target=<?php echo $row['Target']?>"><?php echo $row['Target']; ?></a></td> <td><?php echo $row['IPaddress']; ?></td> </tr> <?php } ?> </tbody> </table> </div> <div class="col-md-9 graph"></div> </div></div><script src="js/d3.v3.js" charset="utf-8"></script> <script> var width = 800; var height = 600; var img_w = 17; var img_h = 17; var color = d3.scale.category20(); var zoom = d3.behavior.zoom() .scaleExtent([1, 10]) .on("zoom", zoomed); var root = d3.select(".graph").append("svg") .attr("width", width) .attr("height", height) .call(zoom);var svg = root.append('svg:g'); var force = d3.layout.force() .gravity(.05) .distance(100) .charge(-100) .size([width, height]);d3.json("force.json", function(error, json) { if (error) throw error; force .nodes(json.nodes) .links(json.links) .start(); var link = svg.selectAll(".link") .data(json.links) .enter().append("line") .attr("class", "link"); var node = svg.selectAll(".node") .data(json.nodes) .enter().append("g") .attr("class", "node") .call(force.drag); node.append("circle") .attr("r", 5) .style("fill", function(d) { return color(d.group); }); node.append("text") .attr("dx", 12) .attr("dy", ".35em") .text(function(d) { return d.name }); var drag =force.drag() .on("dragstart",function(d,i){ d3.event.sourceEvent.cancelBubble = true; d.fixed = true; //拖拽开始后设定被拖拽对象为固定 }); force.on("tick", function() { 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; }); //限制结点的边界 json.nodes.forEach(function(d,i){ d.x = d.x - img_w/2 < 0 ? img_w/2 : d.x ; d.x = d.x + img_w/2 > width ? width - img_w/2 : d.x ; d.y = d.y - img_h/2 < 0 ? img_h/2 : d.y ; d.y = d.y + img_h/2 > height ? height - img_h/2 : d.y ; }); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .on("dblclick",function(d,i){ d.fixed = false; }) .call(drag); });}); function zoomed () { svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } ; </script> </body> </html>
首先,我用的数据源,是一些源和目的地址,第一层关系是查数据库中有多少不同的目标地址,列出来。(代码中没有显示这一部分)点击相应的目标地址,可以展示出数据库中和他有关联的源地址,然后以该目标地址为中心,源地址为他的下一层关系连接。第二层关系是查出源地址有关的目标地址(去重)。
画出的图是这样的:
前面的php代码是用来查数据,然后看到查出的数据构造出了nodes和links,这是force图要求的数据格式。构造的过程中可能会遇到很多问题,用字符串替换等函数来变换到需要的格式。
在第二层关系时,要注意links中target和source的关系,和他们与第一层的关系。(脑袋不好想了半天才理清楚啊真是要被自己蠢哭了)
最后把构造好的字符串生成一个json文件备用。
接下来就是重点,用D3画图了。
前面介绍过,引入D3的库就可以用D3的函数画图了!
先定义一些必要的参数,宽高什么的。(这里图片的宽高是这样的,第一版代码的时候节点是一个小爱心的图片,在限制节点边界的时候为了让图整个都在页面内,就要用到图片的宽高。但是为了更清楚的显示节点的层级,后来就用了不同group不同颜色的点点来表示。懒了就没有改图片宽高这里。)
接着定义颜色,用D3中定义好的20中随机的颜色组。
zoom是一个放大平移的函数。
接下来开始画图。
在html代码中有一个class是graph的div,我们的svg就要画在这上面。接着添加属性。重点:要再嵌套一层svg:g,因为在zoom起作用的时候,为了让他对整体放大或者平移而不是只对其中的点或者线作用,就要把点线这些元素放在一个容器中,然后对这个容器调用zoom。
d3.layout.force()是力学图的布局,下面的参数根据需要填写就是了。
接下来导入数据,把php生成的json数据导入。注意:接下来画图的时候就要把下面的内容放在数据的作用域中。
force的nodes和links是json中的nodes和links。接下来就是画边和点,注意到点还调用了drag。
节点用circle表示,填充定义好的颜色。
在节点上添加文字,就是节点中的name。
再然后就是拖拽函数。这里有一句是防止冒泡事件。也就是拖拽这件事节点也有,zoom事件也有,单击时就会有问题。所以用这句代码来防止冒泡事件。
下一句是拖拽结束后固定顶点位置。
下面是更新图的位置。就是在拖拽之后。还要限制节点的边界。最后是双击固定的节点之后可以解除固定。
在数据作用域的外面是zoom函数。
这样就画出了如上的D3图。
对了,展示一下json的格式。
{"nodes":[{"name":"180.149.153.216:443","group":1},{"name":"3062634345","group":1},{"name":"180.149.153.216:443","group":2},{"name":"3062635806","group":1},{"name":"3723292305","group":1},{"name":"1987589676","group":1},{"name":"1987589733","group":1},{"name":"1987591229","group":1},{"name":"3062644032","group":1},{"name":"1987584314","group":1},{"name":"1987585124","group":1},{"name":"3062640123","group":1},{"name":"1857966460","group":1},{"name":"1857967040","group":1},{"name":"1987771852","group":1},{"name":"3723291694","group":1},{"name":"2101543622","group":1},{"name":"180.149.139.248:443","group":2}],"links":[{"source":1,"target":0,"value":9},{"source":2,"target":1,"value":7},{"source":3,"target":0,"value":8},{"source":4,"target":0,"value":10},{"source":5,"target":0,"value":1},{"source":6,"target":0,"value":2},{"source":7,"target":0,"value":4},{"source":8,"target":0,"value":6},{"source":9,"target":0,"value":1},{"source":10,"target":0,"value":9},{"source":11,"target":0,"value":6},{"source":12,"target":0,"value":3},{"source":13,"target":0,"value":4},{"source":14,"target":0,"value":8},{"source":15,"target":0,"value":7},{"source":16,"target":0,"value":8},{"source":17,"target":16,"value":1}]}
嗯,先写到这吧。以后有什么再补充。
- D3+mysql 画Force图
- d3 force
- d3力学图(force layout)更新
- D3.js学习笔记十二:D3.js构图(d3.layout)——力学(Force)图
- d3力场Force Layout
- 【d3.js教程06】force 力导向图
- d3.js——关于力学图d3.layout.force的参数
- d3 Force-Directed Graph example
- D3 force(力导向图)研究之一:完美融合拖拽与缩放
- D3 force(力导向图)研究之二:如何布局超过十万个节点的图谱
- D3.js中Force-Directed Graph详解
- d3画树形图
- D3.js画折线图
- d3画力导向图
- mysql 操作索引FORCE INDEX
- d3利用弦生成器画折线图
- --force
- d3.js检索mysql数据
- NULL与三值逻辑
- 一件程序猿T恤的故事
- [POJ_1054]LETTERS
- MathType中关于平行且相等符号的编辑方法
- arcgis server发布时遇到的问题
- D3+mysql 画Force图
- setContentView 设置布局文件时,cannot be resolved or is not a field
- notepad++多行标签设置方法
- Notepad++输入模式之修改模式、插入模式
- ruby redis使用
- Linux strsep() 用法
- 2012年5月SAT香港真题解析
- 3.创建一个20个大小的随机数组,找出这组数组的最大值和最小值, 并且标出最大数和最小值的位置
- 利用Dummynet模拟恶劣网络环境