当前位置: 首页 > article >正文

d3.js: Relation Graph

d3.js  Tags · d3/d3 · GitHub

D3 by Observable | The JavaScript library for bespoke data visualization

下载或<!-- 引入 D3.js 库 --><!-- 引入 D3.js 库 -->
    <script src="https://d3js.org/d3.v7.min.js"></script>

<!-- 引入 D3.js 库 -->
    <script src="https://d3js.org/d3.v7.js"></script>

geovinu.json:

{
    "nodes": [
        {
            "id": 0,
            "name": "贾宝玉",
            "image": "1.jpg",
            "group": 1,
            "description": "贾国府衔玉而生的公子。"
        },
        {
            "id": 1,
            "name": "林黛玉",
            "image": "lin.jpg",
            "group": 1,
            "description": "贾亲密女友。"
        },
        {
            "id": 3,
            "name": "薛宝钗",
			 "image": "bao.jpg",
            "group": 1,           
            "description": "贾府中意女子。"
        },
        {
            "id": 4,
            "name": "王熙凤",
            "image": "wan.jpg",
            "group": 2,
            "description": "贾琏的妻子"
        }
    ],
    "links": [
        { "source": 0, "target": 1, "value": 8, "relation": "女友" },
        { "source": 0, "target": 3, "value": 7, "relation": "女友" },
		{ "source": 1, "target": 3, "value": 7, "relation": "情敌" },
        { "source": 4, "target": 3, "value": 5, "relation": "婶侄" },
		 { "source": 4, "target": 1, "value": 5, "relation": "婶妹" },
		{ "source": 4, "target": 0, "value": 5, "relation": "婶侄" }
    ]
}

geovindu.js

// JavaScript Document geovindu.js
const svg = d3.select("#chart")
           .attr("width", 800)
           .attr("height", 500);

        const width = +svg.attr("width");
        const height = +svg.attr("height");

        const simulation = d3.forceSimulation()
   .force("link", d3.forceLink().id(d => d.id).distance(150)) // 调整链接距离
   .force("charge", d3.forceManyBody().strength(-300)) // 调整电荷力强度
   .force("center", d3.forceCenter(width / 2, height / 2));

        const descriptionDiv = d3.select("#description");

        d3.json("geovindu.json").then(data => {
            console.log("Loaded data:", data);
    		console.log("Links:", data.links);

           // 创建连接线
			const link = svg.append("g")
			   .attr("class", "links")
			   .selectAll("line")
			   .data(data.links)
			   .enter().append("line")
			   .attr("stroke-width", d => Math.sqrt(d.value));
				//先隐藏
			link.style("opacity", 0);

            // 创建关系标签文字
            const linkLabels = svg.append("g")
               .attr("class", "link-labels")
               .selectAll("text")
               .data(data.links)
               .enter().append("text")
               .text(d => d.relation)
               .attr("font-size", "10px")
               .attr("fill", "#333999");

            	// 创建节点
			const node = svg.append("g")
			   .attr("class", "nodes")
			   .selectAll("g")
			   .data(data.nodes)
			   .enter().append("g");

            const circles = node.append("circle")
               .attr("r", 5)
               .attr("fill", d => {
                    if (d.group === 1) return "red";
                    else return "blue";
                });

            const images = node.append("image")
               .attr("href", d => d.image)
               .attr("x", -5)
               .attr("y", -5)
               .attr("width", 50)
               .attr("height", 50)
			   .on("mouseover", (event, d) => {
                    // 显示描述信息
                    descriptionDiv.style("display", "block")
                       .style("left", (event.pageX + 10) + "px")
                       .style("top", (event.pageY + 10) + "px")
                       .html(d.description);
				   
						// 显示与该节点相关的线条和关系名称标签
						link.style("opacity", l => l.source === d || l.target === d ? 1 : 0);
						linkLabels.style("opacity", l => l.source === d || l.target === d ? 1 : 0);
				   
                })
               .on("mouseout", () => {
                    // 隐藏描述信息
                    descriptionDiv.style("display", "none");

                    // 隐藏所有线条和关系名称标签
                    link.style("opacity", 0);
                    linkLabels.style("opacity", 0);
                })	
			
			
               .on("error", (error, d) => {
                    console.error(`Error loading image for ${d.name}:`, error);
                });

            const labels = node.append("text")
               .text(d => d.name)
               .attr('x', 6)
               .attr('y', 3)
               .on("mouseover", (event, d) => {
                    // 显示描述信息
                    descriptionDiv.style("display", "block")
                       .style("left", (event.pageX + 10) + "px")
                       .style("top", (event.pageY + 10) + "px")
                       .html(d.description);
				   
						// 显示与该节点相关的线条和关系名称标签
						link.style("opacity", l => l.source === d || l.target === d ? 1 : 0);
						linkLabels.style("opacity", l => l.source === d || l.target === d ? 1 : 0);
				   
                })
               .on("mouseout", () => {
                    // 隐藏描述信息
                    descriptionDiv.style("display", "none");

                    // 隐藏所有线条和关系名称标签
                    link.style("opacity", 0);
                    linkLabels.style("opacity", 0);
                });

            const drag = d3.drag()
               .on("start", dragstarted)
               .on("drag", dragged)
               .on("end", dragended);

            node.call(drag);

            simulation
               .nodes(data.nodes)
               .on("tick", ticked);

            simulation.force("link")
               .links(data.links);

            function ticked() {
                link
                   .attr("x1", d => d.source.x)
                   .attr("y1", d => d.source.y)
                   .attr("x2", d => d.target.x)
                   .attr("y2", d => d.target.y);

                // 更新关系标签文字的位置
                linkLabels
                   .attr("x", d => (d.source.x + d.target.x) / 2)
                   .attr("y", d => (d.source.y + d.target.y) / 2);

                node
                   .attr("transform", d => `translate(${d.x},${d.y})`);
            }

            function dragstarted(event, d) {
                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;
            }
        }).catch(error => {
            console.error("Error loading data:", error);
        });
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
       <title>简单人物关系图谱 Relation Graph </title>
	 <link rel="shortcut icon" href="/favicon.ico">
<meta content="Relation Graph  涂聚文,Geovin Du,塗聚文,geovindu,捷为工作室" name="keywords">
<meta content="Relation Graph 涂聚文,Geovin Du,塗聚文,geovindu,捷为工作室" name="description">
	   <script src="./d3/7.9.0/d3.js"></script>
    <style>
        .node circle {
            fill: #cccccc;
            stroke: steelblue;
            stroke-width: 3px;
        }

        .node text {
            font: 12px sans-serif;
            cursor: pointer;
        }

        .links {
            fill: none;
            stroke: #999fff;
            stroke-width: 2px;
            opacity: 1; /* 初始时连接线隐藏 */
            transition: opacity 0.3s;
        }

        .link-labels text {
            font-size: 10px;
            fill: #333999;
            opacity: 0; /* 初始时关系名称标签隐藏 */
            transition: opacity 0.3s;
        }

        #description {
            position: absolute;
            background-color: white;
            border: 1px solid black;
            padding: 10px;
            display: none;
        }
    </style>
</head>

<body>
    <svg id="chart" width="800" height="600"></svg>
    <div id="description"></div>
    <script type="text/javascript" src="geovindu.js">    
    </script>
</body>

</html>

输出:


http://www.kler.cn/a/525582.html

相关文章:

  • 关于产品和技术架构的思索
  • 创作三载·福启新章2025
  • 在无sudo权限Linux上安装 Ollama 并使用 DeepSeek-R1 模型
  • 视频拼接,拼接时长版本
  • redis缓存和springboot缓存包冲突怎么办
  • Winform如何取消叉号,减号和放大(两种)
  • 「AI学习笔记」深度学习进化史:从神经网络到“黑箱技术”(三)
  • 使用Python将Excel文件转换为PDF格式
  • Spring WebFlux揭秘:下一代响应式编程框架,与Spring MVC有何不同?
  • ROS_noetic-打印hello(√)
  • 你了解哪些Java限流算法?
  • 深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据(基础语法版)
  • 基于微信小程序的辅助教学系统的设计与实现
  • 【Linux】--- 制作一个简易的shell
  • 4.用户 组
  • 代码随想录|动态规划 322. 零钱兑换 279.完全平方数 139.单词拆分
  • Java实现LFU缓存策略实战
  • 31. C语言 命令行参数
  • 剑指 Offer II 011. 0 和 1 个数相同的子数组
  • 【开源免费】基于SpringBoot+Vue.JS公交线路查询系统(JAVA毕业设计)
  • unity使用AVpro插件播放视频,打包安卓系统总是失败
  • R语言统计分析——ggplot2绘图4——刻面
  • 21.2-工程中添加FreeRTOS(掌握) 用STM32CubeMX添加FreeRTOS
  • H3CNE-31-BFD
  • WEB集群6-10天
  • 深入解析 C++17 中的 std::not_fn