分享一个D3.js v7 基础力导图

D3.js官网

一个小小的练习效果

效果图

在这里插入图片描述

源码

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta http-equiv="X-UA-Compatible" content="ie=edge" />
		<title>Static Template</title>
		<script src="https://d3js.org/d3.v7.min.js"></script>
		<style>
			svg{
				border:1px solid #000;
			}
		</style>
	</head>
	<body>
		<script>
			// 定义画布大小
			const width = 600;
			const height = 600;

			// 创建画布
			const svg = d3
				.select("body")
				.append("svg")
				.attr("id", "svg")
				.attr("width", width)
				.attr("height", height);
				// .attr('border',"1px solid #000")

			// 节点数据
			const nodes = [{
					index: 0,
					name: "张三",
					"fx": "225",
					"fy": "225",
					type: 'circle',

				},
				{
					index: 1,
					name: "李四",
					"fx": "300",
					"fy": "400",
					type: 'circle',
				},
				{
					type: 'circle',
					name: "王二",
					"fx": "300",
					"fy": "100"
				},
				{
					type: 'circle',
					name: "小李",
					"fx": "400",
					"fy": "100"
				},
				{
					type: 'circle',
					name: "陈二",
					"fx": "200",
					"fy": "100"
				},
				{
					name: "某人",
					"fx": "300",
					"fy": "200"
				},
				{
					type: 'circle',
					name: "小二",
					"fx": "200",
					"fy": "500"
				},
				{
					type: 'diamond',
					name: "郭靖",
					"fx": "100",
					"fy": "200"
				}
			];

			// 节点关系 source 和 target 不能变
			const links = [{
					source: 0,
					target: 1,
					relation: "关系1"
				},
				{
					source: 0,
					target: 2,
					relation: "关系2"
				},
				{
					source: 0,
					target: 3,
					relation: "关系3"
				},
				{
					source: 0,
					target: 4,
					relation: "关系4"
				},
				{
					source: 0,
					target: 5,
					relation: "关系5"
				},
				{
					source: 0,
					target: 6,
					relation: "关系6"
				},
				{
					source: 0,
					target: 7,
					relation: "关系7"
				}
			];

			// 随机颜色
			const color = d3.scaleOrdinal(d3.schemeCategory10);

			// 新建一个力导向图
			let simulation = d3
				.forceSimulation(nodes)
				.force("charge", d3.forceManyBody().strength(-200)) // 电荷力 相互之间的作用力
				.force("center", d3.forceCenter(width / 2, height / 2)) // 用指定的x坐标和y坐标创建一个居中力
				.force("link", d3.forceLink(links).distance(200)) //
				.on("tick", ticked);
			let xy = simulation.find(50, 10)

			// 画线
			function drawLine() {
				let lines = svg
					.append("g")
					.selectAll(".force-line")
					.data(links)
					.enter()
					.append("line")
					.attr("class", "line")
					.attr("stroke", "#999")
					.attr("stroke-width", "1px");
				return lines;
			}
			let lines = drawLine();

			// 画节点节点盒子
			function drawCircle() {
				let nodeGroups = svg
					.append("g")
					.attr("class", "nodes-box")
					.selectAll(".force-node")
					.data(nodes)
					.enter()
					.append("g")
					.attr("class", "force-node")
					.call(
						d3.drag().on("start", started).on("drag", dragged).on("end", ended)
					);
				nodeGroups.select(function(d) {
					console.log(d)
				});

// 生成不同需求的图元
				const even = nodeGroups.filter((d, i) => i % 2 == 0)
				const sven = nodeGroups.filter((d, i) => i % 2 !== 0)
				even
					.append("circle")
					.attr("class", "force-circle")
					.attr("r", 20)
					.style("fill", function(d, i) {
						return color(i);
					});
				sven
					.append("rect") //添加一个矩形
					.attr("x", -25)
					.attr("y", -25)
					.attr("width", 50)
					.attr("height", 50)
					// .attr("fill","red")
					.style("fill", function(d, i) {
						return color(i);
					});


				nodeGroups
					.append("text")
					.attr("class", "force-text")
					.attr("dy", ".33em")
					.attr("font-size", "12px")
					.attr("text-anchor", "middle")
					.style("fill", "#eee")
					.text(function(d) {
						return d.name;
					});

				return nodeGroups;
			}
			let nodesCircle = drawCircle();

			function ticked() {
				lines
					.attr("x1", (d) => {
						return d.source.x;
					})
					.attr("y1", (d) => {
						return d.source.y;
					})
					.attr("x2", (d) => {
						return d.target.x;
					})
					.attr("y2", (d) => {
						return d.target.y;
					});
				nodesCircle.attr("transform", function(d) {
					// d.fx=d.x;d.fy=d.y; 固定位置
					return "translate(" + d.fx + ", " + d.fy + ")";
				});



			}

			// 拖拽
			function started(event) {
				if (!event.active) simulation.alphaTarget(0.3).restart();
				event.subject.fx = event.subject.x;
				event.subject.fy = event.subject.y;
			}

			function dragged(event) {
				event.subject.fx = event.x;
				event.subject.fy = event.y;
			}

			function ended(event) {
				if (!event.active) simulation.alphaTarget(0);
				// event.subject.fx = null;
				// event.subject.fy = null;
			}
			
			// 创建一个缩放 ===========
			
			var zoom = d3.zoom()
			.scaleExtent([0.1 ,10])
			.on('start',()=>{
				console.log('start')
				svg.style('cursor','pointer')
			})
			.on('zoom',(e)=>{
				console.log(e)
				svg.selectAll('g').attr('transform','translate('+ e.transform.x+','+e.transform.y +') scale('+ e.transform.k + ')')
				// svg.selectAll('g').attr('transform','translate('+ e.transform.x+','+e.transform.y +') scale('+ e.transform.k + ')')
			})
			.on('end',()=>{
				svg.style('cursor','default')
			})
			console.log(zoom)
		svg.call(zoom).call(zoom.transform , d3.zoomIdentity.scale(1))
		</script>
	</body>
</html>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值