-
2021-07-14 00:39:19
HTML
导入代码模板:
力导向图var nodes = [{
name: "桂林"
}, {
name: "广州"
}, {
name: "厦门"
}, {
name: "杭州"
}, {
name: "上海"
}, {
name: "青岛"
}, {
name: "天津"
}];
var edges = [{
source: 0,
target: 1
}, {
source: 0,
target: 2
}, {
source: 0,
target: 3
}, {
source: 1,
target: 4
}, {
source: 1,
target: 5
}, {
source: 1,
target: 6
}];
var width = 400;
var height = 400;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.nodes(nodes) //指定节点数组
.links(edges) //指定连线数组
.size([width, height]) //指定范围
.linkDistance(150) //指定连线长度
.charge(-400); //相互之间的作用力
force.start(); //开始作用
console.log(nodes);
console.log(edges);
//添加连线
var svg_edges = svg.selectAll("line")
.data(edges)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
var color = d3.scale.category20();
//添加节点
var svg_nodes = svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("r", 20)
.style("fill", function(d, i) {
return color(i);
})
.call(force.drag); //使得节点能够拖动
//添加描述节点的文字
var svg_texts = svg.selectAll("text")
.data(nodes)
.enter()
.append("text")
.style("fill", "black")
.attr("dx", 20)
.attr("dy", 8)
.text(function(d) {
return d.name;
});
force.on("tick", function() { //对于每一个时间间隔
//更新连线坐标
svg_edges.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;
});
//更新节点坐标
svg_nodes.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
//更新文字坐标
svg_texts.attr("x", function(d) {
return d.x;
})
.attr("y", function(d) {
return d.y;
});
});
更多相关内容 -
d3-Sticky-Force-Layout:使用D3实现力导向图,界面风格类似于neo4j图数据库可视化界面
2021-04-29 15:26:30d3-Sticky-Force-Layout 使用D3实现力导向图,界面风格类似于neo4j图数据库可视化界面 程序直接下载即可,无需远程连接 界面效果如下: 全屏效果如下: -
详解如何在react中搭建d3力导向图
2020-08-28 06:55:34本篇文章主要介绍了如何在react中搭建d3力导向图,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
Vite + Vue 3 + D3实现力导向图
2022-04-12 16:59:30需要展示复杂的力导向图,通过neo4j的实例代码可以知道,使用d3.js来处理相关前端渲染。这里通过集成vue3,vite来使用D3.js v7版本。 解决 Vite+Vue3 创建vue工程: npm init vue@latest 配置: Vue.js - The ...问题
需要展示复杂的力导向图,通过neo4j的实例代码可以知道,使用d3.js来处理相关前端渲染。这里通过集成vue3,vite来使用D3.js v7版本。
解决
Vite+Vue3
创建vue工程:
npm init vue@latest
配置:
Vue.js - The Progressive JavaScript Framework ✔ Project name: … vue-d3v7 ✔ Target directory "vue-d3v7" is not empty. Remove existing files and continue? … yes ✔ Add TypeScript? … No / Yes ✔ Add JSX Support? … No / Yes ✔ Add Vue Router for Single Page Application development? … No / Yes ✔ Add Pinia for state management? … No / Yes ✔ Add Vitest for Unit Testing? … No / Yes ✔ Add Cypress for both Unit and End-to-End testing? … No / Yes ✔ Add ESLint for code quality? … No / Yes Scaffolding project in /Users/zhangyalin/Downloads/vue-d3v7... Done. Now run: cd vue-d3v7 npm install npm run dev
安装依赖:
npm install
运行工程:
npm run dev
vite.config.js
import { fileURLToPath, URL } from 'url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, // 开启sourcemap配置 css:{ devSourcemap: true }, build:{ sourcemap: true } })
d3 v7
npm i d3@latest
在项目中安装d3最新版本,注意这里使用的d3的v7版本。
D3v7.vue
创建自定义vue组件
<script setup> import * as d3 from "d3"; function go() { const width = 600, height = 1000; const color = d3.scaleOrdinal(d3.schemeCategory10); const types = ["CITED_BY"] const strokeWidth = 1.5 // d3.json("/api/article/graph").then(function(data) { // let graph = data.data; let graph = { "links": [ { "source": "18470926", "target": "10097404", "type": "CITED_BY" } ], "nodes": [ { "label": "Article", "id": "18470926" }, { "label": "Article", "id": "10097404" } ] }; const simulation = d3.forceSimulation(graph.nodes) .force("charge", d3.forceManyBody().strength(-3000)) .force("x", d3.forceX(width / 2).strength(1)) .force("y", d3.forceY(height / 2).strength(1)) .force("link", d3.forceLink(graph.links).id(function(d) {return d.id; }).distance(50).strength(1)) .on("tick", ticked); const svg = d3.select("#graph").append("svg") .attr("width", width).attr("height",height) .attr("pointer-events", "all"); // Per-type markers, as they don't inherit styles. svg.append("defs").selectAll("marker") .data(types) .join("marker") .attr("id", d => `arrow-${d}`) .attr("viewBox", "0 0 10 10") .attr("refX", 10) .attr("refY", 5) .attr("markerUnits", strokeWidth) .attr("markerWidth", 10) .attr("markerHeight", 10) .attr("orient", "auto") .append("path") .attr("fill", color) .attr("d", 'M 0 0 L 10 5 L 0 10 z'); const link = svg.append("g") .selectAll("g") .data(graph.links) .enter() .append("line") .attr("stroke", d => color(d.type)) .attr("stroke-width", strokeWidth) .attr("marker-end", d => `url(${new URL(`#arrow-${d.type}`, location)})`); const node = svg.append("g") .selectAll("g") .data(graph.nodes) .enter().append("g"); node.append("circle") .attr("r", 5) .attr("fill", function(d) { return color(d.label); }) node.call( d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended) ); node.append("text") .text(function(d) { return d.id; }) .attr('x', 6) .attr('y', 3).style('fill', 'white'); node.append("title") .text(function(d) { return d.label; }); function ticked() { node.call(updateNode); link.call(updateLink); } function fixna(x) { if (isFinite(x)) return x; return 0; } function updateLink(link) { link.attr("x1", function(d) { return fixna(d.source.x); }) .attr("y1", function(d) { return fixna(d.source.y); }) .attr("x2", function(d) { return fixna(d.target.x); }) .attr("y2", function(d) { return fixna(d.target.y); }); } function updateNode(node) { node.attr("transform", function(d) { return "translate(" + fixna(d.x) + "," + fixna(d.y) + ")"; }); } function dragstarted(event, d) { event.sourceEvent.stopPropagation(); if (!event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(event, d) { d.fx = event.x; d.fy = event.y; } function dragended(event, d) { if (!event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } // }); } </script> <template> <button @click="go">Go</button> <div id="graph"> </div> </template> <style scoped> </style>
App.vue
使用自定义组件:
<script setup> import HelloWorld from './components/HelloWorld.vue' import D3v7 from './components/D3v7.vue' </script> <template> <header> <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" /> <div class="wrapper"> <HelloWorld msg="You did it!" /> </div> </header> <main> <D3v7 /> </main> </template> <style> @import './assets/base.css'; #app { max-width: 1280px; margin: 0 auto; padding: 2rem; font-weight: normal; } header { line-height: 1.5; } .logo { display: block; margin: 0 auto 2rem; } a, .green { text-decoration: none; color: hsla(160, 100%, 37%, 1); transition: 0.4s; } @media (hover: hover) { a:hover { background-color: hsla(160, 100%, 37%, 0.2); } } @media (min-width: 1024px) { body { display: flex; place-items: center; } #app { display: grid; grid-template-columns: 1fr 1fr; padding: 0 2rem; } header { display: flex; place-items: center; padding-right: calc(var(--section-gap) / 2); } header .wrapper { display: flex; place-items: flex-start; flex-wrap: wrap; } .logo { margin: 0 2rem 0 0; } } </style>
验证
npm run dev
效果:
源代码
https://github.com/fxtxz2/vue-d3v7
参考:
-
D3力导向图
2019-04-18 16:17:50力导向图非常适合于渲染关系型信息图。 二、什么是力导向图(Force-directed)? 我们可以把整张 Network 想象成一个物理仿真系统(Simulation)。系统中的每个节点(Node)都是一个带有能量的粒子,粒子与粒子之间存在...一、背景
力导向图非常适合于渲染关系型信息图。
二、什么是力导向图(Force-directed)?
我们可以把整张 Network 想象成一个物理仿真系统(
Simulation
)。系统中的每个节点(Node
)都是一个带有能量的粒子,粒子与粒子之间存在斥力(如模拟库伦斥力),而被边(Link
)所连结的粒子受到牵引力(如模拟胡克弹力)。系统中的粒子在斥力和引力的不断作用下,从随机无序的布局(Layout
)不断发生位移,逐渐趋于平衡有序的布局。同时整个仿真系统的能量也在不断消耗,经过数次迭代后,粒子之间不再发生相对位移,整个系统达到最终稳定平衡的状态。此动效实现的本质就是每一帧都重新渲染图中节点的位置(x,y), 节点的位置(x,y)是由节点上一帧所处的位置(x,y)+速度(vx,vy)所决定的。而速度就是通过力学模型所计算出来的。
关键在于力(Forces),D3.js 中内置了几种经典的力模型:
1. 中心力(Centering)
中心力可以使得节点最终布局是围绕着某个中心的。相当于某个中心点对所有的节点都有一个制约,不会让布局的中心偏离。
2. 碰撞力(Collision)
- 碰撞力为每个节点都设定一个圆形的碰撞区域,从而防止节点之间重叠。
- 关键参数:radius 碰撞半径
3. 牵引力(Links)
- 牵引力的强度与节点之间的距离成正比,类似于弹簧力。
- 关键参数:distance。影响两个节点之间的最终距离。
4. N 体力(Many-Body)
N体问题是天体力学的一种力学模型,它研究 N 个质点相互之间在万有引力作用下的运动规律。
- Many-Body 力是作用于所有节点之间的,是全局的,任何两个节点之间都将受到此力的影响。(与 牵引力 Links 不同,Links 力仅仅会影响有连接关系的两个节点)
- 它可以用来模拟引力(吸引力),只需设置的 strength 参数为正数;
- 它也可用来模拟电荷力(排斥力),只需设置的 strength 参数为负数。
- 实现算法使用了 the Barnes–Hut approximation(通过将平面不断递归地划分成四个小区域来构建一棵四叉树) 来提高性能;
5. 方向力(Positioning)
方向力分为 X 方向和 Y 方向,即将作用力限制在一个维度上( X 维度或者 Y 维度)
说明
- 以上这几个力学模型是 D3.js 封装的几个经典力学模型,开发者也可根据自身的业务场景,应用自定义的力模型;
- 力模型是可以多重复叠加的,即可同时叠加中心力、碰撞力、牵引力等等;
三、最终效果
通过控制右侧面板,所见即所得地为 Chart 添加不同的力,用户可灵活定制想要的效果。
-
D3.js实现力导向图(Dray和Zoom)
2017-03-02 21:56:43今天遇到个问题就是把json(里面nodes和edges属性)文件通过D3.js展示出来,下午... 什么是力导向图D3.js官网:http://d3js.org/ D3.js github:https://github.com/d3/d3 力导向图(Force-Directed Graph),是绘图今天遇到个问题就是把json(里面nodes和edges属性)文件通过D3.js展示出来,下午终于弄出来了,写篇博客记录一下。
先展示一下效果图:
放大后是这个效果:
什么是力导向图
D3.js官网:http://d3js.org/
D3.js github:https://github.com/d3/d3
力导向图(Force-Directed Graph),是绘图的一种算法。在二维或三维空间里配置节点,节点之间用线连接,称为连线。各连线的长度几乎相等,且尽可能不相交。节点和连线都被施加了力的作用,力是根据节点和连线的相对位置计算的。根据力的作用,来计算节点和连线的运动轨迹,并不断降低它们的能量,最终达到一种能量很低的安定状态。添加d3.js
//我使用的是v4,v3不能这样使用,具体看API <script src="https://d3js.org/d3.v4.min.js"></script>
定义canvas画板
var width = 900 , height = 600, dataset, var svg = d3.select("body").append("svg"),
构建布局
/* 相关API d3.forceSimulation - 创建一个力模拟。 simulation.restart - 重启力模拟。 simulation.stop - 停止力模拟。 simulation.tick - 将力模拟向前推进一步。 simulation.nodes - 设置力模拟的节点。 simulation.alpha - 设置当前的α值。 simulation.alphaMin -设置α最小阈值。 simulation.alphaDecay - 设置α指数衰减率。 simulation.alphaTarget - 设置目标α。 simulation.drag - 设置曳引系数。 simulation.force - 添加或移除力。 simulation.fix - 固定节点位置。 simulation.unfix - 释放固定的节点。 simulation.find - 查找给定位置最近的节点。 simulation.on - 添加或移除事件监听器。 force - 应用力模拟。 force.initialize - 使用给定的节点初始化力布局。 d3.forceCenter - 创建一个力中心。 center.x - 设置中心的x-坐标。 center.y - 设置中心的y-坐标。 d3.forceCollide - 创建一个圆碰撞力。 collide.radius - 设置圆的半径。 collide.strength - 设置碰撞检测强度。 collide.iterations - 设置迭代次数。 d3.forceLink - 创建连接力。 link.links - 设置连接数组。 link.id - 连接数组。 link.distance - 设置连接距离。 link.strength - 设置连接强度。 link.iterations - 设置迭代次数。 d3.forceManyBody - 创建多体力。 manyBody.strength - 设置力强度。 manyBody.theta - 设置Barnes-Hut近似精度。 manyBody.distanceMin - 当节点关闭限制力。 manyBody.distanceMax - 当节点太远限制力。 d3.forceX - 创建x-定位力。 x.strength - 设置力强度。 x.x - 设置目标x-坐标。 d3.forceY - 创建y-定位力。 y.strength - 设置力强度。 y.y - 设置目标y-坐标。 */ var simulation = d3.forceSimulation() .force("link", d3.forceLink().id(function(d) { return d.id; })) .force("charge", d3.forceManyBody()) .force("center", d3.forceCenter(width / 2, height / 2));
加载数据
(说明:加载数据我以实际遇到的为标准,因为在真正的项目中我们必然使用的是加载数据)
d3.json("dd.json", function(error, data) { if (error) throw error; dataset = data;
数据放入布局中
simulation .nodes(dataset.nodes) .on("tick", ticked); simulation.force("link") .links(dataset.edges);
绘制node和edge
//加载连线 var link = g.selectAll("line") .data(graph.edges) .enter().append("line") .attr("stroke",function (d) { return d.color; }) .attr("stroke-width", function(d) { return d.size; }) .call(d3.zoom() .scaleExtent([-5, 2]) .on("zoom", zoomed)); //加载圆 var node = g.selectAll("circle") .data(graph.nodes) .enter().append("circle") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .attr("r", function(d) { return d.size; }) .attr("fill", function(d) { return d.color; }) .on("click",click)//收起子节点 .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } 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; } //加载label node.append("title") .text(function(d) { return d.id; });
添加tick函数(必须)
tick函数的作用:由于力导向图是不断运动的,每一时刻都在发生更新,因此,必须不断更新节点和连线的位置。
力导向图布局 force 有一个事件 tick,每进行到一个时刻,都要调用它,更新的内容就写在它的监听器里就好。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; }); node .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }
最后
推荐几个比较的学习网站:
https://bl.ocks.org/mbostock
http://www.ourd3js.com/
https://github.com/tianxuzhang/d3.v4-API-Translation#hierarchies
http://blockbuilder.org/search#d3version=v4 -
d3.js实现力导向图
2021-05-14 16:02:544,创建力导向图布局(linkDistance表示的是点之间的距离,charge表示节点间的电荷数) 5,转换后的数据node edge转换后的数据 6,绘制图形 7,给图形添加事件 注(要给直线添加stroke不然出不来直线) 8,... -
d3.js力导向图force实现拖拽时fx和fy使用
2021-01-25 21:05:39最近在看到d3.js实现力导向图中节点的拖拽功能时,用到了下面的代码: function dragStarted(d) { d.fx = d.x; // <-E d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; // <-F d.fy = d3.... -
使用d3.js开发力导向图
2021-04-09 17:45:56最近项目需要写一个d3的力导向图,之前没接触过d3.js 所以吧这次开发的经历写一下 文章目录分配点与线创建dom线点绘制线 友情提示:不要让设计设计的华丽呼哨,点多了很卡,而且svg 有些标签是不支持css 控制 某些... -
D3——力导向图
2018-12-21 17:25:38<script type="text/javascript" src="http://d3js.org/d3.v5.min.js"></script> &... var svg = d3.select("body") .append("s -
D3.js 力导向图(气泡+线条+箭头+文字)
2021-01-13 10:21:18D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决 上一篇说了在D3.js中动态增加节点及连线的一种实现方式,但是有后添加元素遮盖原节点的现象,这一篇说一下出现这个现象的解决办法. 在D3.js中后... -
数据可视化 D3.js 力导向图右键菜单实现动态添加节点
2019-11-12 11:02:24前段时间将力导向图节点绑定上了菜单,实现了节点能够右击展开菜单功能这次更新实现动态更新节点数据。 本次使用的D3 版本是V4 -
D3.js创建力导向图(V4)附带详细的参数说明
2020-04-08 21:28:42你可以把它理解成是一个创建作用力,设置作用力阈值和计算作用力大小的高阶函数 这是github上D3.js对于forceManyBody()的解释。 简单来说,就是此函数可以创建一个带参的多体力对象,此对象中有一些函数,咱们可以... -
D3.js 力导向图的显示优化
2020-04-30 10:07:57D3.js 作为一个前端,说到可视化除了听过 D3.js 的大名,常见的可视化库还有 ECharts、Chart.js,这两个库功能也很强大,但是有一个共同特点是封装层次高,留给开发者可设计和控制的部分太少。和 EChart、Chart.js ... -
d3 v5版本绘制力导向图,点击节点绘制环形菜单,如下图所示
2021-02-01 01:29:01我是这样实现的function toggleCircle(current, d) {var currentD = dif (d.clickFlag) {removeSingle()document.getElementById('xxx').innerText = ''}d.clickFlag = truedocument.getElementById('xxx').... -
d3.js力导向图节点如何都显示在边框内
2021-01-26 21:14:41最近用到d3.js中的force力导向图,想实现效果如下,所有城市节点都在可视范围内,如果超出有滚动条也可以。遇到的问题是,当节点一多,有的节点就会跑到外面去,这边是通过加大charge相互作用力,从原本的-300改为-... -
Vue+D3实现直方图与力导向图
2022-05-12 07:54:15力导向图(可拖拽)3.结果展示 一、基础知识 Node.js :是运行在服务端的 JavaScript,Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。 Vue: ... -
d3.js多重力导向图多条关系线
2019-04-29 09:00:41d3.js实现关系图,多条关系连线,关系说明居中。根据json参数自动生成关系图谱。 -
D3实战(1):力导向图(推荐阅读)
2021-06-01 14:45:20一,D3简介 近年来,可视化越来越流行,许多报刊杂志、门户网站、新闻媒体都大量使用可视化技术,使得复杂的数据和文字变得十分容易理解,有一句谚语“一张图片价值于一千个字”。D3 正是数据可视化工具中的佼佼者... -
d3 svg path添加文本_D3.js 力导向图的显示优化
2020-11-20 00:16:16D3.js作为一个前端,说到可视化除了听过 D3.js 的大名,常见的可视化库还有 ECharts、Chart.js,这两个库功能也很强大,但是有一个共同特点是封装层次高,留给开发者可设计和控制的部分太少。和 EChart、Chart.js 等... -
d3源码解析-力导向图
2020-04-17 00:17:441 关于力导向图的源码分析 https://segmentfault.com/a/1190000008578391 https://segmentfault.com/a/1190000008914772 https://blog.csdn.net/wry2008wry/article/details/80812562 (1)需要理解的 a.布局 b.力... -
【d3.js】canvas下力导向图的缩放平移和拖拽兼容
2021-03-26 22:48:15这个周零散解决了一些的关于d3问题,算是入了门,因而写了博客,顺便也作为周报的内容,所以篇幅会比正常我平时写的周报长很多,详细到代码层面。目前除了这次代码提到的v4,也完成了v6版本对应的代码。 1 从简单做... -
d3-force:使用速度Verlet积分进行力导向的图形布局
2021-04-22 21:53:32该模块实现了数值积分器,用于模拟粒子上的物理力。 模拟得到简化:假设每个步骤的单位时间步长Δt = 1,所有粒子的单位质量m = 1。 结果,作用在粒子上的力F等于在时间间隔Δt上的恒定加速度a ,可以简单地通过将其... -
d3 力导向图 force graph
2021-01-13 10:21:19背景:项目 vue.js + d3 v4力导向图可以直观看出各个元素之间的相互作用力数据:{nodes:[{id:xxx, group: xx},{},...] // nodes 是每个节点 group 是聚类后的分组 为了让每个 circle 显示不同分组的颜色links:[{... -
D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决
2021-01-17 13:17:16上一篇说了在D3.js中动态增加节点及连线的一种实现方式,但是有后添加元素遮盖原节点的现象,这一篇说一下出现这个现象的解决办法。在D3.js中后添加的元素是会遮盖先添加的元素的,同时还有一个设定:后添加的Group2... -
d3带箭头和点击事件的力导向关系图
2019-12-17 11:14:11我一个写java的,最近要求做页面d3图,难为了半天在网上各种找资料,最后弄出来的结果如图所示: 话不多说,完整代码附上,粘贴出去即可看到运行结果,样式可根据需求自行修改: <!DOCTYPE html> <meta... -
d3.js实现力导向图圈选框选
2018-01-26 10:16:24d3.js实现力导向图圈选框选 今天给大家带来的是如何在2D可视化图形中加入通过鼠标拖动圈选功能,以力导向图为例。 最终效果 代码解析 我们是要在节点的上方绘制一个矩形覆盖节点的视觉效果,但是为了和原来的... -
用d3做两个节点间有多条关系的力导向图
2022-01-10 10:14:20产生一个2个nodes间有多个关系的力导向图