使用d3.js开发力导向图

本文介绍了使用D3.js库进行数据可视化,包括配置基本力导向图模型、处理点与线关系、创建DOM结构(线和点)、动态路径绘制、节点拖拽和缩放功能。详细讲解了如何分配关系编号、箭头样式和缩略图逻辑。
1. 基本配置
// 生成力
const force = d3
        .forceSimulation()
        .force('link',d3.forceLink().id((d) => d.id),)
        .force('collide', d3.forceCollide(72).strength(0.1))
        .force('charge',d3.forceManyBody().strength(-400),)
        .force('center', d3.forceCenter());
2. 分配点与线

处理一下线的数据, 两个点可能出现多条线的情况

export const setLinkNumber = (group, type) => {
  if (group.length === 0) return;
  const linksA = [];
  const linksB = [];
  for (let i = 0; i < group.length; i++) {
    const link = group[i];
    // 对该分组内的关系按照方向进行分类,此处根据连接的实体ASCII值大小分成两部分
    if (link.source.id < link.target.id) {
      linksA.push(link);
    } else {
      linksB.push(link);
    }
  }
  // 确定关系最大编号。为了使得连接两个实体的关系曲线呈现对称,根据关系数量奇偶性进行平分。
  // 特殊情况:当关系都是连接到同一个实体时,不平分
  let maxLinkNumber = 0;
  if (type === 'self') {
    maxLinkNumber = group.length;
  } else {
    maxLinkNumber = group.length % 2 === 0 ? group.length / 2 : (group.length + 1) / 2;
  }
  // 如果两个方向的关系数量一样多,直接分别设置编号即可
  if (linksA.length === linksB.length) {
    let startLinkNumber = 1;
    for (let i = 0; i < linksA.length; i++) {
      linksA[i].linknum = startLinkNumber++;
    }
    startLinkNumber = 1;
    for (let i = 0; i < linksB.length; i++) {
      linksB[i].linknum = startLinkNumber++;
    }
  } else {
    // 当两个方向的关系数量不对等时,先对数量少的那组关系从最大编号值进行逆序编号,然后在对另一组数量多的关系从编号1一直编号到最大编号,再对剩余关系进行负编号
    // 如果抛开负号,可以发现,最终所有关系的编号序列一定是对称的(对称是为了保证后续绘图时曲线的弯曲程度也是对称的)
    let biggerLinks;
    let smallerLinks;
    if (linksA.length > linksB.length) {
      biggerLinks = linksA;
      smallerLinks = linksB;
    } else {
      biggerLinks = linksB;
      smallerLinks = linksA;
    }
    let startLinkNumber = maxLinkNumber;
    for (let i = 0; i < smallerLinks.length; i++) {
      smallerLinks[i].linknum = startLinkNumber--;
    }
    const tmpNumber = startLinkNumber;
    startLinkNumber = 1;
    let p = 0;
    while (startLinkNumber <= maxLinkNumber) {
      biggerLinks[p++].linknum = startLinkNumber++;
    }
    // 开始负编号
    startLinkNumber = 0 - tmpNumber;
    for (let i = p; i < biggerLinks.length; i++) {
      biggerLinks[i].linknum = startLinkNumber++;
    }
  }
};

function getKey(target, source) {
  const result = target > source ? `${target}:${source}` : `${source}:${target}`;
  return result;
}

export const operationData = (chartData, clickType) => {
  const linkmap = {};
  const link
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值