使用D3绘制力导向图遇到的坑

news2024/11/16 10:54:26

目录

  • 1. 不同D3版本差异
  • 2. D3 V4版本绘制力导向图基本流程
  • 3. 跨域问题
    • 现象
    • 原因
    • 解决办法
  • 4. 异步赋值
    • 现象
    • 原因
    • 解决办法

1. 不同D3版本差异

V3:通过d3.layout.force()将节点、连接线的数据转换成d3力导向图能够使用的数据结构

var force = d3.layout.force().nodes(nodes)
        .links(lines)
        .size([width, height])
        .linkDistance(100)
        .charge(-1200)
        .start()
        .on("tick", function () {
			//具体的方法
        });

V4:通过 d3.forceSimulation()定义关系图,包括设置边link、排斥电荷charge、关系图中心点

var simulation = d3.forceSimulation(nodes)
        .force("link", d3.forceLink(links).distance(200))
        .force("charge",d3.forceManyBody().strength(-100))
        .force("center",d3.forceCenter(width/2, height/2));
        
simulation.on("tick",function(){
	//具体的方法
});

// 生成节点
simulation.nodes(nodes).on("tick", ticked);
//生成边
simulation.force("link")
    .links(links)
    .distance(d => { return 200 });     //每一边的长度

2. D3 V4版本绘制力导向图基本流程

  1. 创建svg绘图:svg是一种矢量图格式,相当于创建一个画图的容器,图中的所有内容都在这个svg中
var svg = d3.select("#svg1")	//select中的内容是需要绑定的html标签
  1. 创建节点、连线、文字、箭头等图形元素:前提是已经导入了节点和边的数据,以数组的形式分别记录
//绘制边
var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links)			//边数组
    .enter()
    .append("line")
    .attr("stroke-width", 2)	//线段宽度,需要再加一个线段颜色
    .style("stroke", '#000000');	//设置填充颜色
//绘制边上文字
var linksText = svg.append("g")
    .selectAll("text")
    .data(links)
    .enter()
    .append("text")
    .text(function(d){return d.type;})	//显示内容是边的类型属性
//箭头
var marker = svg.append("marker")
    .attr("id", "resolved")
    .attr("markerUnits","userSpaceOnUse")
    .attr("viewBox", "0 -5 10 10")//坐标系的区域
    .attr("refX",34)//箭头坐标
    .attr("refY", -1)
    .attr("markerWidth", 12)//标识的大小
    .attr("markerHeight", 12)
    .attr("orient", "auto")//绘制方向,可设定为:auto(自动确认方向)和 角度值
    .attr("stroke-width",2)//箭头宽度
    .append("path")
    .attr("d", "M0,-5L10,0L0,5")//箭头的路径
    .attr('fill','#000000');//箭头颜色

// 绘制节点
var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(nodes)			//节点数组
    .enter()
    .append("circle")
    .attr("r", function(d) {return 15})	// 设置圆圈半径
    .attr("fill", '#000000')	//设置填充颜色
    .attr("stroke", "none")
    .attr("id", d => d.id)		//设置id
    .call(d3.drag()				//设置拖拽
        .on("start", dragstarted)
        .on("drag", dragged)
        .on("end", dragended)
    );

//绘制描述节点的文字
var nodesText = svg.append('g')
    .selectAll("text")
    .data(nodes)
    .enter()
    .append("text")
    .style("fill", "black")
    .attr("dx", 20)
    .attr("dy", 8)
    .text(function (d) {return d.name;});	//设置节点文字是节点的名字属性
  1. 创建力导向图对象:使用d3.forceSimulation()定义力导向图,包括设置边link、排斥电荷charge、关系图中心点
var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(d => {return d.id}))
    .force("charge", d3.forceManyBody().strength(-30))	//电荷排斥,strength为负是排斥,为正是吸引
    .force("center", d3.forceCenter(width / 2, height / 2))	//中心位置
    .force("collision", d3.forceCollide(20))    // 碰撞检测
  1. 将节点、关系元素导入力导向图中
// 生成节点
simulation.nodes(nodes).on("tick", ticked);
//生成边
simulation.force("link")
    .links(links)
    .distance(d => { return 200 });     //每一边的长度
  1. 确定节点、边、文字、箭头的位置
// ticked()函数确定link线的起始点x、y坐标 node确定中心点 文本通过translate平移变化
function ticked() {
    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;})
        .attr("marker-end", "url(#resolved)");

    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;});

    node
        .attr("cx", function(d) {return d.x;})
        .attr("cy", function(d) {return d.y;});

    nodesText
        .attr("x", function (d) {return d.x;})
        .attr("y", function (d) {return d.y;});
}
  1. 设置拖拽,鼠标移动等事件
// 拖动函数代码
var dragging = false;
// 开始拖动并更新相应的点
function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
    dragging = true;
}
// 拖动进行中
function dragged(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
}
// 拖动结束
function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
    dragging = false;
}

// 鼠标选中节点事件
$('#svg1').on('mouseenter', '.nodes circle', function(event) {
    //添加事件内容
});

// 鼠标移开节点事件
$('#svg1').on('mouseleave', '.nodes circle', function(event) {
    //添加事件内容
});

3. 跨域问题

现象

使用d3.json()读取json文件数据时,直接用浏览器运行的话会报跨域错误

原因

跨域指的是不同域之间互相请求资源,比如a.com无法操作b.com下的内容。常规来说写了一个前端页面直接就用默认浏览器打开运行了,此时浏览器的地址栏显示的是你的html文件在你电脑上的地址。需要用一个服务器来存放json文件,通俗说就说要用localhost这样的地址去运行你的程序。

解决办法

整体的思路都是将文件和代码放在一个服务器中去请求,以下提供两个思路:

  • 使用nodejs提供本地服务器
  • IDE可能会存在自带的本地服务器,通过该方式运行程序。以vs code为例,可以下载一个叫做Live Server的插件,通过右键选择Open with Live Server.即可
    在这里插入图片描述

4. 异步赋值

现象

使用d3.json()读取数据时,将数据内容赋值到变量中,在d3.json()函数内能正常赋值,函数结束后变量值为undefined或默认值

原因

d3.json()采用异步的方式读取数据,导致赋值了但没有更新,从而在函数外没有赋值成功

解决办法

采用JQuery读取json文件,并且设置参数async为false,这样便是采用同步的方式读取数据。

$.ajax({
    url: path,			//json文件的地址
    type: "GET",
    dataType: "json",
    async: false,		//不采用异步方式
    success: 
    function (data) {	//进行赋值操作
        nodeConfig = data.node
        relationshipConfig = data.relationship
        dataPath = data.dataPath
    }
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/381391.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

哪些工具可以实现在线ps的需求

在线Photoshop有哪些工具可以选择?在 Adobe 的官网上就能够实现,很惊讶吧,其实 Adobe 官方推出了在线版本的 Photoshop 的,尽管目前还是 Beta版本,但其实也开放了蛮久了。编辑切换为居中添加图片注释,不超过…

安卓手机用WIFI无线调试adb

1、准备连接 1、首先将电脑和手机连接同一个WIFI,并插上数据线 2、打开电脑CMD,输入命令adb start-server开启adb服务 3、输入adb devices 查询已连接的设备 List of devices attached 505e894 device 这样代表已连接成功, 505e894 。 505e894是udid&…

蓝桥杯真题(JAVA)--分巧克力

题目描述儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有 NN 块巧克力,其中第 i块是HiWi 的方格组成的长方形。为了公平起见,小明需要从这 NN 块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足&…

SiC MOSFET驱动电压的分析

SiC MOSFET驱动电压的分析 tips:资料来自富昌电子,及各个模块数据手册。 1.常见的Vgs与Vgs(th),以及对SiC MOSFET应用的影响 驱动电压Vgs和栅极电压阈值Vgs(th)关系到SiC MOSFET在应用过程中的可靠性,功率损耗(导通电阻),以及驱…

极光笔记 | 极光PUSH服务助力企业提升抢单速度

随着硬件、软件、网络等不断发展、完善,互联网已经渗透到了日常生活中的方方面面,在直接赋能原有行业服务的同时也带来了很多新的服务模式,给人们日常生活带来了极大便利。例如:外卖、快递、跑腿等相关业务更是在我们日常生活中随…

CHAPTER 2 Web HA集群部署 - Heartbeat

Web HA集群部署 - Heartbeat1. Heartbeat 概述1.1 Heartbeat主要组成部分2. 环境依赖2.1 环境及组件软件2.2 关闭firewalld & selinux2.3 配置双机互信,SSH密钥登录​​2.4 同步时间(以主节点时间为准)2.5 配置域名解析3 安装软件3.1 安装…

你有“ChatGPT综合征”吗:想搞钱,或是失业焦虑?

最近互联网圈里有一个“顶流”,ChatGPT上线仅5天,注册用户数就突破100万,今年2月的月活跃用户已经突破了1亿。ChatGPT的热度有增无减,过不了多久,ChatGPT这个词就会从一线城市的写字楼席卷到农村老家的饭桌上。 互联网…

自动化测试难点案例分析,其实自动化你用错方向还不如不用

随着国内企业软件开发及测试水平的提升,许多企业开始尝试开展自动化测试的应用,以提高测试效率和测试质量。虽然在国外自动化测试工具应用已经很普遍,但国内许多企业对于软件自动化测试的理解还停留在表面上,没有深入的理解到企业…

SpringMVC的常用组件和工作流程及部分注解解析

一丶SpringMVC常用的组件 1.前端控制器DispatcherServlet 作用:统一处理请求和响应。除此之外还是整个流程控制的中心,由 DispatcherServlet 来调用其他组件,处理用户的请求 接收请求,响应结果,相当于转发器&#xff…

参考 Promise/A+ 规范和测试用例手写 Promise

前言 这可能是手写promise较清晰的文章之一。 由浅至深逐步分析了原生测试用例,以及相关Promise/A规范。阅读上推荐以疑问章节为切入重点,对比Promise/A规范与ECMAScript规范的内在区别与联系,确定怎样构建异步任务和创建promise实例。然后开…

JavaSE18-面向对象-内部类

文章目录一、局部内部类二、成员内部类三、静态内部类四、匿名内部类一、局部内部类 把类定义在方法中。对象创建格式:直接在定义内部类的方法中创建。如果在该方法外就不能使用该局部内部类了。应用场景:如果需要定义一个在方法中临时使用的类可以使用…

SpringCloud(微服务)学习篇(一)

SpringCloud(微服务)学习篇(一) 1 nacos的下载和配置 1.1 进入官网 nacos官网 1.2 点击nacos➡点击最新稳定版本 1.3 往下翻并点击nacos-server-2.2.0.zip,此时就已经开始下载了 1.4 把下载好的压缩包解压到没有中文路径的目录里面 1.5 修改application.properties文件 1.…

Testlink相关功能使用部分总结

1.首页面(普通用户,测试用例创建用户的权限) 右上角切换具体的项目;页面上方包含主页、用例、测试执行、测试结果;左侧包含测试项目管理、关键字管理、编辑测试用例、搜索测试用例、每用户创建的测试用例;…

Element UI的基本使用

学习来源,传送门 目录创建vue项目Element UI主要的标签Vue router 来动态创建左侧导航栏为何会发生嵌套menu与router的绑定设置默认展开设置默认打开页面创建vue项目 以管理员身份,在选定目录下,使用vue ui 按照正常配置配好,可…

Linux(ubuntu)系统搭建docker下的LNMP环境

系统环境 系统:Ubuntu 18.04.4 LTS x86_64 管理面板:宝塔面板7.9.8 下载镜像 通过面板下载docker和docker-compose 下载完毕后通过docker->镜像->从仓库拉取拉取镜像ubuntu:20.04 或者通过docker pull ubuntu:20.04拉取镜像 通过docker->容…

代码随想录算法训练营第四十一天 | 01背包问题-二维数组滚动数组,416. 分割等和子集

一、参考资料01背包问题 二维 https://programmercarl.com/%E8%83%8C%E5%8C%85%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%8001%E8%83%8C%E5%8C%85-1.html 视频讲解:https://www.bilibili.com/video/BV1cg411g7Y6 01背包问题 一维 https://programmercarl.com/%E8%83%8C%E5…

大功率分流电阻器产品阵容进一步扩大,助力大功率应用小型化

全球知名半导体制造商ROHM(总部位于日本京都市)面向车载、工业设备及白色家电等大功率应用,开发出大功率低阻值分流电阻器“GMR 系列”中额定功率最大的、10W 电阻器“GMR320”。近年来,在车载领域和工业设备领域中,应…

什么是敏捷测试

敏捷 反应快速灵敏。 在敏捷软件开发领域,更注重的以人为核心,迭代,循序渐进的开发方法。相比传统的开发方法,这种方法能更快速的开发,上线,反馈,调整、迭代。以敏捷的姿态去发展产品。 敏捷与…

基于java+swing+mysql员工工资管理系统

基于javaswingmysql员工工资管理系统一、系统介绍二、功能展示1.用户登陆2.员工主要功能3.管理员主要功能三、系统实现1.StudentFrame .java四、其它1.其他系统实现2.获取源码一、系统介绍 该项目功能相对完善,有管理员和普通用户两个角色,分别实现了一…

磷脂酰丝氨酸的作用;CAS:383907-32-2;磷脂酰丝氨酸(phosphatidylserine,PS)

磷脂酰丝氨酸(phosphatidylserine,PS)又称丝氨酸磷脂,二酰甘油酰磷酸丝氨酸,简称PS,是一类普遍存在的磷脂,通常位于细胞膜的内层,磷酯化合物中的磷酸甘油酯类,是细胞膜组…