D3.js的v5版本入门教程(第十四章)

这一章我们来绘制一个力导向图,什么叫力导向图,通俗一点将就是有节点和线组成,当鼠标拖拽一个节点时,其他节点都会受到影响(力导向图有多种类型,本章绘制的效果就是这样,其他类型的读者可以自己去试试),还是给读者提个醒,这一章又会有很多新的知识点,请拿出的学习新东西的本领来

为了绘制一个力导向图,我们还是需要以下新的知识点

  • d3.forceSimulation() ,新建一个力导向图,
  • d3.forceSimulation().force(),添加或者移除一个力,这里给出官方示例:

这里说明一下对于d3.forceSimulation().force(name),也就是当force中只有一个参数,这个参数是某个力的名称,那么这段代码返回的是某个具体的力,(根据上面图片官方对force的说明也可以知道),例如d3.forceSimulation().force(“link”),则返回的是d3.forceLink()这个力,注意对照上面的图片,这个用法在下面会经常被用到

  • d3.forceSimulation().nodes(),输入是一个数组,然后将这个输入的数组进行一定的数据转换,例如添加坐标什么的!这里给出官方API的解释

从这里可以看出,差不多就是上面作者讲的那个意思

  • d3.forceLink.links(),这里输入的也是一个数组(边集),然后对输入的边集进行转换,等一下我们会看到,它到底被转换成什么样子的
  • tick函数,这个函数对于力导向图来说非常重要,因为力导向图是不断运动的,每一时刻都在发生更新,所以需要不断更新节点和连线的位置
  • d3.drag(),是力导向图可以被拖动

好了,有了这些基础知识后,我们开始绘制一个力导向图

1、数据准备

var marge = {top:60,bottom:60,left:60,right:60}var svg = d3.select("svg")var width = svg.attr("width")var height = svg.attr("height")var g = svg.append("g").attr("transform","translate("+marge.top+","+marge.left+")");//准备数据var nodes = [//节点集{name:"湖南邵阳"},{name:"山东莱州"},{name:"广东阳江"},{name:"山东枣庄"},{name:"泽"},{name:"恒"},{name:"鑫"},{name:"明山"},{name:"班长"}];var edges = [//边集{source:0,target:4,relation:"籍贯",value:1.3},{source:4,target:5,relation:"舍友",value:1},{source:4,target:6,relation:"舍友",value:1},{source:4,target:7,relation:"舍友",value:1},{source:1,target:6,relation:"籍贯",value:2},{source:2,target:5,relation:"籍贯",value:0.9},{source:3,target:7,relation:"籍贯",value:1},{source:5,target:6,relation:"同学",value:1.6},{source:6,target:7,relation:"朋友",value:0.7},{source:6,target:8,relation:"职责",value:2}];

2、设置一个颜色比例尺

//设置一个color的颜色比例尺,为了让不同的扇形呈现不同的颜色var colorScale = d3.scaleOrdinal().domain(d3.range(nodes.length)).range(d3.schemeCategory10);

3、新建一个力导向图

var forceSimulation = d3.forceSimulation().force("link",d3.forceLink()).force("charge",d3.forceManyBody()).force("center",d3.forceCenter());

其实上面那一段代码你就可以从官网上面复制下来(我也是这么干的)

4、生成节点数据

//生成节点数据forceSimulation.nodes(nodes).on("tick",ticked);//这个函数很重要,后面给出具体实现和说明

注意,这里出现了tick函数,我把它的实现写到了一个有名函数ticked(以前我们是不是写的都是无名函数)

5、生成边集数据

//生成边数据forceSimulation.force("link").links(edges).distance(function(d){//每一边的长度return d.value*100;}) 

注意,这里出现了forceSimulation.force(name)的用法,前面已经详细解释了它的返回值

6、设置图形中心位置

//设置图形的中心位置  forceSimulation.force("center").x(width/2).y(height/2);

这里也是forceSimulation.force(name)的用法

7、输出顶点集和边集

//在浏览器的控制台输出console.log(nodes);console.log(edges);

顶点集的样子

边集的样子

8、绘制边

//绘制边var links = g.append("g").selectAll("line").data(edges).enter().append("line").attr("stroke",function(d,i){return colorScale(i);}).attr("stroke-width",1);

这里注意一下,应该先绘制边,在绘制顶点,因为在d3中,各元素是有层级关系的,先绘制的在下面

9、边上的文字

var linksText = g.append("g").selectAll("text").data(edges).enter().append("text").text(function(d){return d.relation;})

10、老规矩,先建立用来放在每个节点和对应文字的分组<g>

var gs = g.selectAll(".circleText").data(nodes).enter().append("g").attr("transform",function(d,i){var cirX = d.x;var cirY = d.y;return "translate("+cirX+","+cirY+")";}).call(d3.drag().on("start",started).on("drag",dragged).on("end",ended));

注意,这里出现了drag函数,对于call函数大家应该比较熟悉了!我们也可以发现,这里使用了三个有名函数,具体实现后面会给出

11、节点和文字

//绘制节点gs.append("circle").attr("r",10).attr("fill",function(d,i){return colorScale(i);})//文字gs.append("text").attr("x",-10).attr("y",-20).attr("dy",10).text(function(d){return d.name;})

注意,这里的文字的到需要根据转换后数据的特点得到!!!

12、ticked函数的实现

function ticked(){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;});linksText.attr("x",function(d){return (d.source.x+d.target.x)/2;}).attr("y",function(d){return (d.source.y+d.target.y)/2;});gs.attr("transform",function(d) { return "translate(" + d.x + "," + d.y + ")"; });}

注意,可以发现,这里写的都是位置信息,所以你在绘制相应的图形元素的时候,位置信息就不那么重要的,而且,建议先写完这个函数后,在进行测试

13、drag

function started(d){if(!d3.event.active){forceSimulation.alphaTarget(0.8).restart();设置衰减系数,对节点位置移动过程的模拟,数值越高移动越快,数值范围[0,1]}d.fx = d.x;d.fy = d.y;}function dragged(d){d.fx = d3.event.x;d.fy = d3.event.y;}function ended(d){if(!d3.event.active){forceSimulation.alphaTarget(0);}d.fx = null;d.fy = null;}

drag中有三个函数,在这里进行了实现,其中d.fx和d.fy表示固定坐标,例如,现在我们看到dragged函数,我们可以发现这样的代码:d.fx = d3.event.x;  d.fy = d3.event.y;,也就是在拖动节点的时候,鼠标位置在哪里(d3.event),节点的固定位置就在哪里,再看到ended函数,也就是结束拖动的时候触发,可以发现,固定坐标都为空,也就是不固定,这样模拟的效果才好(你们也可以试试去掉ended函数会发生什么,这样可以更好的理解)

最后,附上代码运行的结果

效果还是很不错的!!是不是感觉过程很复杂!没关系,一步一步来,结果好就行

效果浏览:点击浏览效果

源码浏览:点击源码浏览

(效果浏览会出现乱码,请谅解!但是整体效果和上面的截图差不多,而且是动态的,可以鼠标拖拽!)

(翻外篇)d3.js在网页端可视化neo4j图数据库

为了让大家更好的学习d3.js,“d3.js在网页端可视化neo4j图数据库”这是一个比较综合的项目——利用neo4j的java驱动API从neo4j中取数据,并利用d3.js在网页端进行可视化。大家在学完基础课程后可以做一下这个项目,进行巩固。点击下面链接进行查看:d3.js可视化neo4j图数据库项目专栏

D3.js的v5版本入门教程(第十四章)—— 力导向图相关推荐

  1. D3.js的v5版本入门教程(第六章)——做一个简单的图表

    D3.js的v5版本入门教程(第六章) 从这一章开始,进入正式的d3,js绘图阶段,有了前面几章基本知识的积累,这样看接下来的绘图代码才不会觉得比较辛苦 做一个简单的图表 为了做一个简单的图表,我们还 ...

  2. D3.js的v5版本入门教程(第十三章)—— 饼状图

    D3.js的v5版本入门教程(第十三章) 这一章我们来绘制一个简单的饼状图,我们只绘制构成饼状图基本的元素--扇形.文字,从这一章开始,内容可能有点难理解,因为每一章都会引入比较多的难理解知识点,在这 ...

  3. D3.js的v5版本入门教程(第五章)—— 选择、插入、删除元素

    D3.js的v5版本入门教程(第五章) 1.选择元素 现在我们已经知道,d3.js中选择元素的函数有select()和selectAll(),下面来详细讲解一下 假设我们的<body>中有 ...

  4. D3.js的v5版本入门教程(第一章)—— 如何在项目中使用D3.js

    D3.js的v5版本入门教程(第一章) 1.需要的一些工具 这个其实随便!最简单的就是建一个.txt文件就可以敲起代码来!作者本人用的是myeclipse(主要需要安装tomcat),因为写的是前端, ...

  5. 可视化工具D3.js教程 入门 (第十四章)—— 中国地图

    可视化工具D3.js教程 入门 (第十四章)-- 中国地图 代码 <!DOCTYPE html> <html lang="en"><head>& ...

  6. 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  7. ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区...

    原文:ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 入门案例分析 在第一章里,我们已经对ArcGIS系列软件的体系结构有了一 ...

  8. jquery audio没有声音_Python实用案例编程入门:第十四章 通过声音控制您的计算机

    本章的主题为通过声音来控制您的电脑.当下的语音识别已经相对比较成熟,比如有的车载系统,或手机都支持语音识别,您可以通过声音来下达指令.比如您告诉导航系统"我要去北京",它会自动帮您 ...

  9. Packet Tracer 思科模拟器入门教程 之十四 路由器综合路由配置

    实验目标 掌握综合路由器的配置方法: 掌握查看通过路由重分布学习产生的路由: 熟悉广域网线缆的链接方式: 实验背景 假设某公司通过一台三层交换机连到公司出口路由器R1上,路由器R1再和公司外的另一台路 ...

最新文章

  1. SizeBasedAndTimeBasedLog
  2. 如何保证数据库服务器的安全性
  3. jsp文字上下居中显示_微信朋友圈又有骚技巧,一键设置居中签名,好友傻眼了...
  4. 小米12 Ultra相机参数曝光:1.92亿像素主摄+1英寸超大底
  5. 重要更新|《Python程序设计开发宝典》例12-7代码有bug
  6. rust腐蚀 木制窗户怎么修_潜艇围壳上的窗户为什么不会裂开?
  7. 激光雷达是什么?一文带你读懂激光雷达
  8. LINUX SHELL如何递归访问目录(处理包含空格的文件名)
  9. python 多个excel合并成多个sheet以及多个excel合并成一个sheet
  10. ISO 4217 货币(货币符号)及基金编码
  11. 土方回填施工方案范本_联投土方回填施工方案样本
  12. 解决安卓机拍照,照片显示自动旋转90度问题
  13. 关于泰勒展开的细节-《三体》读后感的读后感...
  14. linux服务器使用certbot免费安装ssl证书
  15. 面向海洋观监测传感网的移动终端位置隐私保护研究
  16. CSS3篮球场热力区域图
  17. 42个自我提升的实用技巧
  18. 用JAVA 做一个简易版的坦克大战(只实现基本功能)
  19. 【数组】雇佣 K 名工人的最低成本
  20. WIN10笔记本找不到摄像头?!

热门文章

  1. 开源sso单点登陆系统推荐
  2. 安卓修改大师揭秘Android手游破解全过程
  3. 记得常回头看看以前犯的错误,但绝不要为它们感到后悔
  4. 就是这么简单,QQ被盗了可以这样找回来!
  5. phpnow切换php,PHPNOW如何升级PHP
  6. Photoshop学习(四):为图像添加文字
  7. [从头读历史] 第268节 诗经 鄘风
  8. java 图片去除黑边,头顶黑边,求大神解决
  9. dreamweaver作业静态HTML网页设计——我的家乡海南旅游网站
  10. [SVA]SystemVerilog Assertion(SVA)編寫經驗