绘制力导向图的时候通常节点都是圆形,但也会遇到公司节点绘制成圆型,人绘制成方形的情况,那我们怎么依据数据绘制不同的形状。

你可能首先会想到,这很简单啊,是公司的时候append circle,是人的时候append rect。但是append并没有提供回调也就是说我们不能这样做

node.append((data)=>{
   return data.type === 'person'  ? 'rect' : 'circle';
});

下面介绍两种方案:

 第一种,先append一个g然后根据数据设置不同的类名

var nodeGUpdate = this.nodeG
                  .selectAll('g')
                  .data(this.nodesData, (data) => data.id);

var nodeGEnter = nodeGUpdate.enter(); var nodeGExit = nodeGUpdate.exit(); // 更新 nodeGUpdate
.transition() .attr('class', (data) => {   return (data.hide && 'hide') || (data.nodeStatus < 0 && 'noActive') || (data.cateType === 0 && 'mainCompany') || (data.cateType === 1 && 'relativeCompany') || (data.cateType === 2 && 'relativePerson'); }) nodeGEnter.append('g')
.attr('class', (data)=> {   return data.cateType === 2 ? 'person' : 'company'; })

然后依据类名append不同形状

添加矩形

this.nodeG
.selectAll('.person')
.append('rect')
.attr('class', (data) => {
  return (data.hide && '.hide') || (data.cateType === 0 && 'mainCompany') || (data.cateType === 1 && 'relativeCompany') || (data.cateType === 2 && 'relativePerson');
 })
.attr('width', 20)
.attr('height', 20);

添加圆形

this.nodeG
.selectAll('.company')
.append('circle')
.attr('class', (data) => {
   return (data.hide && '.hide') || (data.cateType === 0 && 'mainCompany') || (data.cateType === 1 && 'relativeCompany') || (data.cateType === 2 && 'relativePerson');
 })
.attr('r', 20);

最后效果

这有点尴尬,矩形是以它自身的左上角的为基点,所以你可能还需要根据象限进行平移。

上面这种思路是我从其它文章看来的,但出处忘了,但是由于还要将矩形的中心移到线的端点太麻烦,所以最终没有采用这种方法。

下面来讲另外一种方法

整体思路是统一append circle 但是当是人的时候填充圆形。就是可以想象append的这个circle相当于一个透明的画布,如果fill的值是颜色,那就是用这个颜色去填充这个圆。如果fill的是一个形状,就是用这个形状填充,由于背景是透明的,所以看起来好像append了其它形状上去。

首先在svg中定义一个矩形,defs简单来说就是一个容器,在这个元素里面你可以定义一些元素供你重复使用,例如箭头和这里定义的矩形。

这里有几个地方需要注意:

矩形 x,y的值

x,y是矩形的左上角相对于圆形的位置,设置x,y的值将矩形移至圆的中心,这样才能确保线的端点指向矩形的中心。

计算公式是 x=y = r  - 矩形宽度 / 2

确保矩形小于圆的内切正方形

打个比方,如果你透过一个圆形孔看一个较小的红色正方形,你会看到一个个完整的正方形,但如果正方形过大,你可能就只能看到一个红色的圆形了。

所以正方形宽度推导公式就是 width < 2*r / √2

<svg width="1000" height="1000">
  <defs>
     <pattern id="person" patternUnits="objectBoundingBox" width="1" height="1">
         <rect x="10" y="10" width="20" height="20" fill="#7FBBA1" stroke="#5CA083"/>
       </pattern>
    </defs>
 </svg>

确保圆是透明的

通俗点讲就是用于填充矩形的圆的样式中不能在设置fill和stroke了

然后在绘制圆形的地方引用

nodeEnter
  .append('circle')
    .attr('class', (data) => {
       return (data.hide && '.hide') || (data.cateType === 0 && 'mainCompany') || (data.cateType === 1 && 'relativeCompany') || (data.cateType === 2 && 'shape-relativePerson');
    })
    .attr('r', 20)
    .attr('fill', (data)=>{
        return data.cateType === 2 ? 'url(#person)' : '';
     })

下面是结果图

当然你可以扩展,例如如果是人的话绘制一个人的图片

<pattern id="person" patternUnits="objectBoundingBox" width="1" height="1">
  <image href={user} width="20" height="20" x="10" y="10"/>
</pattern>

效果如图

d3根据数据绘制不同的形状的更多相关文章

  1. d3 根据数据绘制svg

    , , , , ]; var circles = svg.selectAll("circle") .data(dataset) .enter() .append("cir ...

  2. d3.js:数据可视化利器之快速入门

    hello,data! 在进入d3.js之前,我们先用一个小例子回顾一下将数据可视化的基本流程. 任务 用横向柱状图来直观显示以下数据: var data = [10,15,23,78,57,29,3 ...

  3. 如何将内存中的位图数据绘制在DC上

    假如你定义了一个位图类,里面包含位图头,位图信息头,调色板,位图数据.然后你按照位图的格式将位图文件读入你的类中,现在你知道了位图的全部信息了.主要信息包含在位图信息头里面,数据则在位图数据缓冲里面. ...

  4. Highcharts使用CSV格式数据绘制图表

    Highcharts使用CSV格式数据绘制图表 CSV(Comma-Separated Values,逗号分隔值文本格式)是採用逗号切割的纯文本数据.通常情况下.每一个数据之间使用逗号切割,几个相关数 ...

  5. linux环境安装nagiosgraph将nagios的性能数据绘制成动态图表?

    需求描述: 在安装完成nagios之后,比如有监控磁盘负载信息的,连接数的,进程数的,可以通过安装nagiosgraph软件, 将nagios的性能数据绘制成图表,可以看到一段时间内数据的变化 环境说 ...

  6. Highcharts使用表格数据绘制图表

    Highcharts使用表格数据绘制图表 在Highcharts中,同意用户使用网页中现有的表格数据作为数据来源,然后依据该数据来源绘制图表.对于一个典型的HTML表格.当中,第一列的数据会作为x轴刻 ...

  7. WPF 自定义的图表(适用大量数据绘制)下

    原文:WPF 自定义的图表(适用大量数据绘制)下 上一篇文章中讲了WPF中自定义绘制大量数据的图标,思路是先将其绘制在内存,然后一次性加载到界面,在后续的调试过程中,发现当数据量到达10W时,移动鼠标 ...

  8. WPF 自定义的图表(适用大量数据绘制)

    原文:WPF 自定义的图表(适用大量数据绘制) 在WPF中绘制图表比较简单,有很多的第三方控件,但是在绘制大量数据的时候,就显得有些吃力,即便是自己用StreamGeometry画也达不到理想的效果, ...

  9. 使用d3.v3插件绘制出svg图

    众所周知,这个插件使用的svg技术,而IE8(包括IE8)之前的浏览器是不支持svg的 接下来看代码吧 从后台获取到带id和父id的目录数据[json格式] var module = requestU ...

随机推荐

  1. SQL 谜题(父亲的邮票)

    问题:父亲需要些1分,2分,3分,5分,10分的邮票, 其中两种各买四张,另外的三种各买三张 我忘记是哪几种了?他给了我一些10分硬币,金额刚好买这些邮票 计算及分析过程: --通过极限算法,若都是3 ...

  2. RapidJSON 代码剖析(四):优化 Grisu

    我曾经在知乎的一个答案里谈及到 V8 引擎里实现了 Grisu 算法,我先引用该文的内容简单介绍 Grisu.然后,再谈及 RapidJSON 对它做了的几个底层优化. (配图中的<Grisù& ...

  3. JMeter学习-011-JMeter 后置处理器实例之 - 正则表达式提取器(三)多参数获取进阶引用篇

    前两篇文章分表讲述了 后置处理器 - 正则表达式提取器概述及简单实例.多参数获取,相应博文敬请参阅 简单实例.多参数获取. 此文主要讲述如何引用正则表达式提取器获取的数据信息.其实,正则表达式提取器获 ...

  4. ubuntu-E:Encountered a section with no Package: header的解决办法

    刚才打开ubuntu,我的版本是12.04.正想使用sudo apt-get install build-essential 时,出现了如下错误: E:Encountered a section wi ...

  5. JavaScript之作用域与作用域链

    今天是2016的第一天,我们得扬帆起航踏上新的征程了.此篇阐述JavaScript中很重要的几个概念:作用域与作用域链及相关知识点. 我们先从变量与作用域的行为关系开始讨论. 变量作用域 JavaSc ...

  6. Judge Route Circle

    Initially, there is a Robot at position (0, 0). Given a sequence of its moves, judge if this robot m ...

  7. Job 失败了怎么办?- 每天5分钟玩转 Docker 容器技术(133)

    上一节讨论了 Job 执行成功的情况,如果失败了会怎么样呢? 修改 myjob.yml,故意引入一个错误: 先删除之前的 Job: 如果将 restartPolicy 设置为 OnFailure 会怎 ...

  8. Apache Hadoop 2.9.2 的YARN High Available 模式部署

    Apache Hadoop 2.9.2 的YARN High Available 模式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.环境准备 1>.官方文档(htt ...

  9. [并查集][NOIP2015]信息传递

    信息传递 题目描述 有 N 个同学( 编号为 1 到 N) 正在玩一个信息传递的游戏. 在游戏里每人都有一个固定的信息传递对象, 其中,编号为i的同学的信息传递对象是编号为ti的同学. 游戏开始时, ...

  10. Java 中常见的数据结构

    1.数据结构有什么作用? 当使用 Java 里面的容器类时,你有没有想过,怎么 ArrayList 就像一个无限扩充的数组,也好像链表之类的.很好使用,这就是数据结构的用处,只不过你在不知不觉中使用了 ...