上一篇: 仪表盘图 https://blog.csdn.net/zjw_python/article/details/98596174

下一篇: 旭日图 https://blog.csdn.net/zjw_python/article/details/98613674

代码结构和初始化画布的Chart对象介绍,请先看 https://blog.csdn.net/zjw_python/article/details/98182540

本图完整的源码地址: https://github.com/zjw666/D3_demo/tree/master/src/sanKeyChart/basicSanKey

1 图表效果

2 数据

桑基图的数据需要符合一定的规则,即包含nodes和links两个部分

{"nodes": [{"id": "a"},{"id": "b"},{"id": "c"},{"id": "d"},{"id": "e"},{"id": "f"},{"id": "g"},{"id": "h"},{"id": "i"}],"links": [{"source": "a", "target": "d", "value": 10},{"source": "a", "target": "i", "value": 2},{"source": "b", "target": "d", "value": 8},{"source": "b", "target": "e", "value": 6},{"source": "c", "target": "e", "value": 5},{"source": "b", "target": "e", "value": 2},{"source": "b", "target": "i", "value": 4},{"source": "d", "target": "f", "value": 3},{"source": "d", "target": "g", "value": 4},{"source": "d", "target": "h", "value": 5},{"source": "e", "target": "g", "value": 7},{"source": "e", "target": "f", "value": 3},{"source": "e", "target": "h", "value": 5}]
}

3 关键代码

导入数据

d3.json('./data.json').then(function(data){....

一些样式配置参数

const config = {margins: {top: 80, left: 50, bottom: 50, right: 50},textColor: 'black',title: '基础桑基图'}

桑基图主要由d3.sankey计算布局,但这个API没有原生包含在d3里,而是一个插件,需要额外引入,例如

<script src="https://unpkg.com/d3-sankey@0"></script>

引入插件后,方法自动挂载在d3对象上,就可以直接调用了

/* ----------------------------数据转换------------------------  */const sankey = d3.sankey().nodeWidth(50).nodePadding(30).size([chart.getBodyWidth(), chart.getBodyHeight()]).nodeId((d) => d.id);const {nodes, links} = sankey({nodes: data.nodes,links: data.links});

经布局函数计算返回后的数据就可以直接绘制节点了,桑基图的节点是矩形,这里用rect元素渲染

/* ----------------------------渲染节点------------------------  */chart.renderNodes = function(){const rects = chart.body().append('g').attr('class', 'rects').selectAll('.node').data(nodes);rects.enter().append('g').attr('class', 'node').attr('index', (d)=> d.id).attr('linkNodes', (d)=> {const nextNodes = d.sourceLinks.map((link) => link.target.id).join('');const prevNodes = d.targetLinks.map((link) => link.source.id).join('');return nextNodes + d.id + prevNodes;}).append('rect').merge(rects).attr('x', (d) => d.x0).attr('y', (d) => d.y0).attr('width', (d) => d.x1 - d.x0).attr('height', (d) => d.y1 - d.y0).attr('fill', (d) => chart._colors(d.index % 10));rects.exit().remove();}

渲染连线则直接调用d3.sankeyLinkHorizontal,非常方便

/* ----------------------------渲染连线------------------------  */chart.renderLines = function(){const lines = chart.body().append('g').attr('class', 'lines').selectAll('path').data(links);lines.enter().append('path').merge(lines).attr('linkNodes', (d) => d.source.id + '-' + d.target.id).attr('d', d3.sankeyLinkHorizontal()).attr('stroke', (d) => chart._colors(d.source.index % 10)).attr('stroke-width', (d) => d.width).attr('stroke-opacity', '0.4').attr('fill', 'none');lines.exit().remove();}

渲染文本标签

/* ----------------------------渲染文本标签------------------------  */chart.renderTexts = function(){d3.selectAll('.text').remove();chart.body().selectAll('.node').append('text').attr('class', 'text').attr('x', (d) => (d.x0 + d.x1)/2).attr('y', (d) => (d.y0 + d.y1)/2).attr('stroke', config.textColor).attr('text-anchor', 'middle').attr('dy', 6).text((d) => d.id);}

绑定鼠标交互事件,当鼠标悬停在某个节点上时,突出显示与该节点相连的边和节点;当鼠标悬停在某个边上时,则突出显示在这条边上的两个节点

/* ----------------------------绑定鼠标交互事件------------------------  */chart.addMouseOn = function(){// 悬停在节点上d3.selectAll('.node').on('mouseover', function(d){d3.selectAll('.node, path').attr('fill-opacity', '0.1').attr('stroke-opacity', '0.1');d3.selectAll('[linkNodes*=' + d.id + ']').attr('fill-opacity', '1').attr('stroke-opacity', '0.4');}).on('mouseleave', function(){d3.selectAll('.node, path').attr('fill-opacity', '1').attr('stroke-opacity', '0.4');})// 悬停在连线上d3.selectAll('path').on('mouseover', function(){d3.selectAll('.node, path').attr('fill-opacity', '0.1').attr('stroke-opacity', '0.1');const e = d3.event;const hoverNodes = d3.select(e.target).attr('stroke-opacity', '0.4').attr('linkNodes').split('-');hoverNodes.forEach((id) => {d3.selectAll('[index=' + id + ']').attr('fill-opacity', '1')});}).on('mouseleave', function(){d3.selectAll('.node, path').attr('fill-opacity', '1').attr('stroke-opacity', '0.4');})}

大功告成!!!


如果觉得这篇文章帮助了您,请打赏一个小红包鼓励作者继续创作哦!!!

D3 二维图表的绘制系列(二十二)桑基图sankey相关推荐

  1. D3 二维图表的绘制系列(十五)雷达图

    上一篇: 气泡图 https://blog.csdn.net/zjw_python/article/details/98485368 下一篇: 矩形树状图 https://blog.csdn.net/ ...

  2. D3 二维图表的绘制系列(六)基础折线图

    上一篇: 横向柱状图 https://blog.csdn.net/zjw_python/article/details/98209333 下一篇: 堆叠面积图 https://blog.csdn.ne ...

  3. D3 二维图表的绘制系列(十四)气泡图

    上一篇: 多符号散点图 https://blog.csdn.net/zjw_python/article/details/98483989 下一篇: 雷达图 https://blog.csdn.net ...

  4. D3 二维图表的绘制系列(七)堆叠面积图

    上一篇: 基础折线图 https://blog.csdn.net/zjw_python/article/details/98210977 下一篇: 曲线图 https://blog.csdn.net/ ...

  5. D3 二维图表的绘制系列(一)介绍

    1 介绍 D3 (或者叫 D3.js )是一个基于 web 标准的 JavaScript 可视化库. D3 可以借助 SVG, Canvas 以及HTML 将你的数据生动的展现出来. D3 结合了强大 ...

  6. D3 二维图表的绘制系列(二十三)旭日图

    上一篇: 桑基图 https://blog.csdn.net/zjw_python/article/details/98611559 下一篇: 力导向图 https://blog.csdn.net/z ...

  7. D3 二维图表的绘制系列(二十六)盒须图

    上一篇: 中国地图 下一篇: 日历热力图 代码结构和初始化画布的Chart对象介绍,请先看 这里 本图完整的源码地址:这里 1 图表效果 2 数据 {"data": [{" ...

  8. D3 二维图表的绘制系列(二十七)日历热力图

    上一篇: 盒须图 下一篇: 弦图 代码结构和初始化画布的Chart对象介绍,请先看 这里 本图完整的源码地址: 这里 1 图表效果 2 数据 {"2018-01-01": 2,&q ...

  9. D3 二维图表的绘制系列(八)曲线图

    上一篇: 堆叠面积图 https://blog.csdn.net/zjw_python/article/details/98214359 下一篇: 基础饼图 https://blog.csdn.net ...

最新文章

  1. 十七、生产者消费者问题
  2. 牙齿矫形教训和洗牙知识
  3. OpenCV imwrite
  4. cas java单点登录_java单点登录系统CAS的简单使用
  5. 《Java从小白到大牛精简版》之第6章 运算符(上)
  6. 更改JENKINS主目录
  7. 如何做好产品需求设计和开发
  8. 计算机视觉入门大全:基础概念、运行原理、应用案例详解
  9. 2020-03-13 MySQL 8 绿色安装
  10. ipad 的android模拟器,苹果IPAD模拟器(iPadian)
  11. 十分钟django后台 simpleui -含自定义后台首页
  12. 牛客小白月赛2 H 武 【Dijkstra】
  13. quarz定时任务 spring整合quartz
  14. ZYNQ启动流程之分析BootRoM
  15. 2018拼多多校招【最大乘积】Python解法
  16. 【笔记】操作系统(六)——进程同步
  17. Qemu虚拟化PowerPc
  18. Adobe国际认证|3D产品可视化:赢得内容竞赛的关键
  19. C#编程第四季高级篇
  20. 非线性方程求解 不动点迭代法

热门文章

  1. HTML学习笔记整理(二)
  2. 牛牛爱奇数 来源:牛客网
  3. vector函数用法全解
  4. vector类常用的函数
  5. Yuppie 雅皮士
  6. 各种浏览器的USERAGENT格式(useragent)
  7. 外贸建站多少钱?不同预算对应的建站方案!
  8. 我又一个朋友辞掉了公务员
  9. 解决:mode, rawmode = _fromarray_typemap[typekey]KeyError: ((1, 1, 9), ‘|u1‘)问题
  10. oracle查询最大并发数,oracle最大并发数查看