可视化 |【d3】力导向关系图

news2025/2/27 1:05:45

文章目录

  • 📚目标效果
  • 📚html和css
  • 📚js
    • 🐇整体框架
    • 🐇细说创建部分

📚目标效果

  • 力导向关系图
    在这里插入图片描述
  • 人物详情
    在这里插入图片描述
  • 子图高亮
    在这里插入图片描述

📚html和css

  • html放一个div框:<div class="network"></div>
  • css主要完整高亮后的透明度设置以及悬浮提示框的样式设置。
    .link.inactive,
    .linetext.inactive,
     .node.inactive image,
     .node.inactive text {
         opacity: .2;
     }
     .tooltip {
         font-family:  "KaiTi", "serif";
         font-size: 12px;
         width: 220px;
         height: auto;
         position: absolute;
         background: #fff;
         opacity: 0.5;
         border-radius: 5px;
         box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
     }
     .tooltip .title {
         color: #fff;
         padding: 5px;
         font-size: 14px;
         background-color: #d2a36c;
         border-radius: 5px 5px 0 0;
     }
     .tooltip .detail-info {
         width: 100%;
         border-collapse: collapse;
         border: 1px solid #d2a36c;
     }
     .tooltip .detail-info td {
         padding: 3px 5px;
         color: #666;
         vertical-align: middle;
     }
     .tooltip .detail-info tr:nth-of-type(odd) {
         background: #f9f9f9;
     }
     .tooltip .detail-info td.td-label {
         color: #333;
         width:60px;
     }
     .tooltip .detail-info td a {
         color: #666
     }
    

📚js


  • 外部引入js
    <script type = "text/javascript" src = "./assects/js/d3/d3.v4.js"></script>
    <script type = "text/javascript" src = "./assects/js/jquery/jquery-1.9.1.js"></script>
    
  • 下述为自定义部分⭐️

🐇整体框架

  • 分为两部分:创建 + 应用

    d3.json("./data/people.json", function(json) {
      // 创建部分
      function GroupExplorer(wrapper,config){...}
      // 实例应用
      new GroupExplorer('.network',{
          data:json
      });
    });
    
  • 数据采用外部json导入,基本格式适合桑基图的数据格式一样的。nodes放诗人具体信息,links放诗人之间的联系。

    {
      "nodes": [
         {
           "name": "元稹",
           "zihao": "字微之,别字威明",
           "dynasty": "中唐",
           "age": "52岁(779年~831年)",
           "epithet": "与白居易并称“元白”",
           "deeds": "提倡“新乐府”,倡导“古文运动”",
           "famous": "《乐府古题序》、《莺莺传》",
           "image": "元稹.png",
           "link": "https://so.gushiwen.cn/authorv_201a0677dee4.aspx"
         },
         ...
       ],
       "links": [
         {
           "source": 14,
           "target": 29,
           "value": "好友"
         },
         ...
       ]
     }
    

🐇细说创建部分

  • 准备工作:设置了初始配置,为可视化准备数据,并使用D3.js为绘制网络图设置了带有缩放功能的SVG画布。

    • 默认配置:定义了网络图的默认配置,包括初始数据、宽度、高度和节点之间的距离。
    • 配置扩展:使用jQuery的 $.extend() 方法获取数据值。
    • 数据转换: 遍历连接并检查源和目标是否不是数字(假设它们是节点的名称)。如果是,则根据名称找到相应的节点,并将它们分配为连接的源和目标。
    • 初始化: 初始化主要函数的变量,并设置初始高亮节点以及用于存储依赖节点、连接和文本的数组。
    • 缩放功能: 定义了一个缩放处理函数(zoomed)来根据缩放事件对可视化进行转换。还设置了一个具有特定缩放范围和缩放事件处理程序的d3缩放行为。
    • SVG绘制: 选择.network元素,并在其上附加一个SVG画布,设置其宽度和高度,附加缩放行为,并禁用双击缩放。然后附加一个组元素来存储所有的节点、连接和文本。
    // 默认配置对象
    var defaultConfig = {
        data:{"nodes":[],"links":[]},
        // 初始宽高为视口宽高
        width:window.innerWidth,
        height:window.innerHeight,
        distance: 96
    };
    // jQuery库中的 ​$.extend()​方法,获取数据值
    $.extend(true,defaultConfig,config);
    
    // link里不是用名字匹配而是用数字(也就是对应对象的索引,即节点数组的顺序)
    // 检查是否存在名字,进行索引转换
    defaultConfig.data.links.forEach(function (e) {
        if(typeof e.source != "number" && typeof e.target != "number"){
            var sourceNode = defaultConfig.data.nodes.filter(function (n) {
                    return n.name === e.source;
                })[0],
                targetNode = defaultConfig.data.nodes.filter(function (n) {
                    return n.name === e.target;
                })[0];
            e.source = sourceNode;
            e.target = targetNode;
        }
    });
    
    //d3画图start,首先初始化
    var _this = this,highlighted = null,dependsNode = [],dependsLinkAndText = [];
    
    // 将缩放变换应用到容器元素
    this.zoomed = function(){
        _this.vis.attr("transform", d3.event.transform);
    };
    // 设置缩放范围和缩放响应函数。
    var zoom = d3.zoom()
            .scaleExtent([0.2,10])
            .on("zoom",function(){
                _this.zoomed();
            });
    
    // 选择body元素,并创建一个SVG画布,并应用缩放功能
    this.vis = d3.select(".network").append("svg:svg")
            .attr("width", defaultConfig.width)
            .attr("height", defaultConfig.height)
            // 实现双击还原
            .call(zoom).on("dblclick.zoom", null);
    // 分组元素,用于放置所有的节点、连接线和文字
    this.vis = this.vis.append('g').attr('class','all')
            .attr("width", defaultConfig.width)
            .attr("height", defaultConfig.height)
    
  • 创建力导向布局和力模型

    this.force = d3.forceSimulation()
    	// 指定节点
    	.nodes(defaultConfig.data.nodes)
    	// 引力
    	.force("link", d3.forceLink(defaultConfig.data.links).distance(defaultConfig.distance))
    	.force("linkForce", d3.forceLink().id(function(d) { return d.id; }).distance(50))
    	// 斥力
    	.force("charge", d3.forceManyBody())
    	// 设置可视化中心。
    	.force("center", d3.forceCenter(defaultConfig.width / 2, defaultConfig.height / 2))
    	// 将碰撞力指定为 ​"collide"​ 类型的力,使节点保持至少 ​60​ 个单位的距离,碰撞的强度为 0.2,使节点之间有一定的距离。​
    	// .iterations(5)​ 设置迭代次数为 5,提高碰撞的精确度。
    	.force("collide",d3.forceCollide(61).strength(0.2).iterations(5))
    	.alphaTarget(1)
    
  • 绘制连接线并添加箭头标记及文本标记:这里对“好友”关系作特殊处理(因为data里“好友”关系占大多数,对关系图的呈现有一定影响,故作特殊处理:连接线为绿色且后续不标注value值关系描述)。

    // 创建箭头​<marker>​元素,之后可以使用该箭头标记在连接线的末端添加箭头效果。
    this.vis.append("svg:defs").selectAll("marker")   
            .data(["end"])
            // 创建一个 ​<marker>​ 元素
            .enter().append("svg:marker")
            .attr("id","arrow")
            .attr('class','arrow')
            // 定义了在通过视图呈现时,元素起始点和围绕元素的盒子的属性
            .attr("viewBox", "0 -5 10 10")
            // 在X轴、Y轴方向上的参考点
            .attr("refX", 42)
            .attr("refY", 0)
            // 宽高
            .attr("markerWidth", 7)
            .attr("markerHeight", 12)
            .attr("markerUnits","userSpaceOnUse")
            .attr("orient", "auto")
            // 添加一个 ​<path>​ 元素,用于绘制箭头的路径
            .append("svg:path")
            // 设置路径命令
            .attr("d", "M0,-5L10,0L0,5")
            .attr('fill','#666');
    
    // 绘制连接线(link)并添加箭头标记
    this.link = this.vis.selectAll("line.link")
            .data(defaultConfig.data.links)
            .enter().append("svg:line")
            .attr("class", "link")
            .attr('stroke-width',1.8)
            // 获取起始点、目标点x,y
            .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("stroke", function(d) {
                if (d.value === "好友") {
                return "#007175";  
                } else {
                return "gray";   // 其他关系为灰色或默认颜色
                }
            })
            .attr("marker-end", "url(#arrow)");
    
    // 为每条连线添加文本元素表示连线的关系描述
    this.linetext = this.vis.selectAll('.linetext')
      .data(defaultConfig.data.links)
      .enter()
      .append("text")
      .attr("class", "linetext")
      .attr("x", function(d){ return (d.source.x + d.target.x) / 2}) // 文本的水平位置为连线起点和终点x坐标的中间值
      .attr("y", function(d){ return (d.source.y + d.target.y) / 2}) // 文本的垂直位置为连线起点和终点y坐标的中间值
      .text(function (d) { 
          if (d.value !== "好友") {
              return d.value; 
          } else {
              return ""; 
          }
          // return d.value;
      })
      .call(d3.drag()) // 添加拖拽行为,使文本可以被拖动
      .style("font-family", "KaiTi, serif") 
      .style("font-size", "14px")
    
  • 拖拽功能的实现:核心是拖动后引斥力变化后的位置更新。

    // 重新计算力导向布局,并刷新可视化效果
    this.tick = function() {
      // 更新连接线的起始点 (x1, y1) 和终点 (x2, y2) 的位置
      _this.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;});
      _this.linetext.attr("x",function(d){ return (d.source.x + d.target.x) / 2})
              .attr("y",function(d){ return (d.source.y + d.target.y) / 2});
      // 更新节点的位置
      _this.node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
    };
    
    _this.force.on("tick", this.tick);
    
    // 处理节点的拖拽事件,并创建了一个用于节点拖拽的drag行为
    var dragstart = function(d, i) {
      console.info(d3.event.subject)
      _this.force.stop();
      // 阻止事件传播,以防止与其他事件冲突
      d3.event.sourceEvent.stopPropagation();
    };
    var dragmove = function(d, i) {
      d.px += d3.event.dx;
      d.py += d3.event.dy;
      d.x += d3.event.dx;
      d.y += d3.event.dy;
      // 重新计算力导向布局,并刷新可视化效果
      _this.tick();
    };
    var dragend = function(d, i) {
      d3.event.subject.fx = null;
      d3.event.subject.fy = null;
      // 重新启动力导向布局的运行
      _this.force.restart();
      _this.tick();
    };
    this.nodeDrag = d3.drag()
          .on("start", dragstart)
          .on("drag", dragmove)
          .on("end", dragend);
    
  • 悬浮框内容设置:这里的悬浮框相当于一个小html,相关样式在css中设置,这里涉及到的鼠标动作目的是确保悬浮框在使用过程中能够正确地显示、隐藏,并且在鼠标交互中具有合适的响应和延迟效果。

    // 悬停框显示
    this.highlightToolTip = function(obj){
        if(obj){
            _this.tooltip.html("<div class='title'>" + obj.name + "的详情</div>" +
                                "<table class='detail-info'><tr><td class='td-label'>字号:</td><td>" + obj.zihao + "</td></tr>" +
                                "<tr><td class='td-label'>朝代:</td><td>" + obj.dynasty + "</td></tr>" +
                                "<tr><td class='td-label'>年龄:</td><td>" + obj.age + "</td></tr>" +
                                "<tr><td class='td-label'>称号:</td><td>" + obj.epithet + "</td></tr>" + 
                                "<tr><td class='td-label'>事迹:</td><td>" + obj.deeds + "</td></tr>" +
                                "<tr><td class='td-label'>代表作:</td><td>" + obj.famous + "</td></tr>" + 
                                "<tr><td class='td-label'>链接:</td><td><a href='" + obj.link + "'>" + obj.name + "的主页</a></td></tr></table>")
                    .style("left",(d3.event.pageX+20)+"px")
                    .style("top",(d3.event.pageY-20)+"px")
                    .style("opacity",1.0);
        }else{
            _this.tooltip.style("opacity",0.0);
        }
    };
    this.tooltip = d3.select(".network").append("div")
            .attr("class","tooltip")
            .attr("opacity",0.0)
            .on('dblclick',function(){
                // 被双击时,阻止提示框冒泡,避免影响其他事件。
                d3.event.stopPropagation();
            })
            .on('mouseover',function(){
                // 悬停时,如果之前设置了鼠标移出的定时器,则清除该定时器,以防止工具提示在短时间内被误隐藏
                if (_this.node.mouseoutTimeout) {
                    clearTimeout(_this.node.mouseoutTimeout);
                    _this.node.mouseoutTimeout = null;
                }
            })
            .on('mouseout',function(){
                // 当鼠标移出工具提示时,如果之前设置了鼠标移出的定时器,则先清除该定时器。
                // 然后,设置一个新的定时器
                // 在快速移动鼠标时工具提示不会立即消失,只有在鼠标离开一段时间后才会隐藏。
                if (_this.node.mouseoutTimeout) {
                    clearTimeout(_this.node.mouseoutTimeout);
                    _this.node.mouseoutTimeout = null;
                }
                _this.node.mouseoutTimeout=setTimeout(function() {
                    _this.highlightToolTip(null);
                }, 300);
            });
    
  • 高亮功能实现:核心是找到相关节点,将不相关的节点、连接线、连接文本设置为inactive类,搭配css里的透明度设置,实现先关节点的高亮。

    • 如果传入的对象 obj 存在,该函数将根据该对象相关的节点、连接线和文本进行高亮显示,同时取消其他元素的高亮显示。
      • 首先,将传入对象 obj 的索引添加到依赖节点数组 dependsNode 和依赖连接线和文本数组 dependsLinkAndText 中。
      • 然后遍历连接线数据,确定与指定对象相关的节点索引,并将这些节点索引添加到依赖节点数组中。
      • 最后使用classed()方法来根据依赖节点数组和依赖连接线和文本数组的内容,给节点、连接线和文本添加或移除 inactive 类,从而控制它们的显示状态。
    • 如果传入的对象 obj 不存在,那么该函数将取消所有元素的高亮显示,即移除所有节点、连接线和文本的 inactive 类。(这里针对搜索框应用(挖个坑,后续补充),如果搜索对象不存在则移除所有inactive类,使图表归位)
    // 高亮显示与指定对象相关的节点、连接线和文本,并取消其他元素的高亮显示
    this.highlightObject = function(obj) {
      if (obj) {
          // 获取要高亮显示的对象的索引
          var objIndex = obj.index;
          // 添加到依赖节点数组
          dependsNode = dependsNode.concat([objIndex]);
          // 添加到依赖连接线和文本数组
          dependsLinkAndText = dependsLinkAndText.concat([objIndex]);
          
          // 遍历连接线数据,确定与指定对象相关的节点索引,并添加到依赖节点数组中
          defaultConfig.data.links.forEach(function(lkItem) {
              if (objIndex == lkItem['source']['index']) {
                  dependsNode = dependsNode.concat([lkItem.target.index])
              } else if (objIndex == lkItem['target']['index']) {
                  dependsNode = dependsNode.concat([lkItem.source.index])
              }
          });
          
          _this.node.classed('inactive', function(d) {
              return dependsNode.indexOf(d.index) == -1;
          });
          
          _this.link.classed('inactive', function(d) {
              return dependsLinkAndText.indexOf(d.source.index) == -1 && dependsLinkAndText.indexOf(d.target.index) == -1;
          });
          
          _this.linetext.classed('inactive', function(d) {
              return dependsLinkAndText.indexOf(d.source.index) == -1 && dependsLinkAndText.indexOf(d.target.index) == -1;
          });
      } else {
          _this.node.classed('inactive', false);
          _this.link.classed('inactive', false);
          _this.linetext.classed('inactive', false);
      }
    };
    
  • 创建节点元素,绑定数据,绑定鼠标动作对应的悬浮框效果高亮效果,添加图片图标

    // 创建节点元素,并绑定相关的数据和事件处理函数
    this.node = this.vis.selectAll("g.node")
        .data(defaultConfig.data.nodes)
        .enter().append("svg:g")
        .attr("class", "node")
        .call(_this.nodeDrag)
        .on('mouseover', function(d) {
            // 鼠标悬停在节点上时,悬浮框来
            if (_this.node.mouseoutTimeout) {
                clearTimeout(_this.node.mouseoutTimeout);
                _this.node.mouseoutTimeout = null;
            }
            _this.highlightToolTip(d);
        })
        .on('mouseout', function() {
            // 鼠标移出节点时,悬浮框走
            if (_this.node.mouseoutTimeout) {
                clearTimeout(_this.node.mouseoutTimeout);
                _this.node.mouseoutTimeout = null;
            }
            _this.node.mouseoutTimeout=setTimeout(function() {
                _this.highlightToolTip(null);
            }, 300);
        })
        .on('dblclick',function(d){
            // 双击节点时,高亮显示与当前节点相关的节点、连接线和连线上的文本
            _this.highlightObject(d);
            //(阻止事件冒泡)
            d3.event.stopPropagation();
        });
    
    // 为每个节点添加图片元素表示节点图标
    this.node.append("svg:image")
        .data(defaultConfig.data.nodes)
        .attr("class", "circle")
        .attr("xlink:href", function(d){ return("./assects/images/" + d.image)}) 
        //以下设置直接绝对图标和连接线箭头的“和平共处”程度
        .attr("x", "-25px") 
        .attr("y", "-25px") 
        .attr("width", "50px")
        .attr("height", "50px");
    
  • 双击空白处复原实现

    // 在整个页面上绑定双击事件处理函数
    d3.select(".network").on('dblclick',function(){
       // 当双击页面其他区域时,取消所有节点、连接线和连线上的文本的高亮显示,并重置依赖节点和连接线数组
       dependsNode = dependsLinkAndText = [];
       _this.highlightObject(null);
    }); 
    

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

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

相关文章

2023年全球软件开发大会(QCon广州站2023):核心内容与学习收获(附大会核心PPT下载)

在全球化的科技浪潮中&#xff0c;软件开发行业日新月异&#xff0c;持续推动着社会经济的飞速发展。本次峰会以“引领未来&#xff0c;探索无限可能”为主题&#xff0c;聚焦软件开发领域的最新技术、最佳实践和创新思想。来自世界各地的顶级专家、企业领袖和开发者齐聚一堂&a…

大脑的漏洞:你是如何走向狭隘和顽固的?

在这篇文章的最开始&#xff0c;我想请大家思考一个问题&#xff1a; 为什么谣言的传播总是非常容易&#xff0c;但辟谣却一点也不容易呢&#xff1f; 有一个非常简单的答案&#xff0c;你或许立刻就能想到&#xff1a;因为谣言一般都非常简单&#xff0c;但辟谣一般都不怎么简…

深度学习之处理多维特征的输入

我们首先来看一个糖尿病的数据集&#xff1a; 在数据集中&#xff0c;我们称每一行叫做sample&#xff0c;表示一个样本&#xff0c;称每一列是feature&#xff0c;也就是特征在数据库里面这就是一个关系表&#xff0c;每一行叫做记录&#xff0c;每一列叫做字段。 每一个样本都…

JS中的try...catch

一、定义和结构 作用&#xff1a;捕获同步执行代码下的异常错误 在没有使用try...catch的情况下&#xff0c;同步代码执行遇到异常会报错&#xff0c;并中断后续代码执行&#xff1b; 在使用try...catch的情况下&#xff0c;同步代码执行遇到异常会抛出异常&#xff0c;并继续…

【销售数据分析】客户画像分析之总体画像

前一段时间把财务分析的一些报表及分析场景讲得差不多了&#xff0c;接下来想和大家讲一下销售分析中的一些场景。今年看了许多企业的数据&#xff0c;发现大家2023年比疫情三年更难&#xff01;从财务的几张报表就会发现净利润亏损的居多&#xff0c;而亏损的主要原因基本上都…

MybatisPlus二级映射和关联对象ResultMap

文章目录 一、业务背景1. 数据库表结构2. 需求 二、使用映射直接得到指定结构三、其他文件1. Mapper2. Service3. Controller 四、概念理解一级映射二级映射聚合 五、标签使用1. \<collection\> 标签2. \<association\> 标签 在我们的教程中&#xff0c;我们设计了…

20240128-读书带来的影响

我本身不算是一个特别喜欢读书的人&#xff0c;更多的时候其实是为了读书而读书。在坚持每天读了一小时书之后&#xff0c;我发现自身开始慢慢有些变化。是什么时候突然有了这种感悟呢&#xff0c;是最近每周5小时左右的微信读书以及纸质书籍的阅读&#xff0c;让我体会到了读书…

文心一言情感关怀之旅

【AGIFoundathon】文心一言情感关怀之旅,让我们一起来体验吧! 上传一张照片,用ernie-bot生成专属于你的小故事! 此项目主要使用clip_interrogator获取图片的关键信息,然后将此关键信息用百度翻译API翻译成中文后,使用封装了⼀⾔API的Ernie Bot SDK(ernie-bot)生成故事…

PhpStorm调试docker容器中的php项目

背景 已经通过docker容器启动了一个web服务&#xff0c;并在宿主机可以访问http://localhost:8080访问网页。 现在想使用phpstorm打断点调试代码。 方法 1. 容器内安装xdebug 进入容器 docker exec -it <container-name> bash为php安装xdebug拓展 apt install php8…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例5-2 JavaScript 获取HTML元素对象

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>JavaScript 获取 HTML 元素对象</title> </head><body> <input type"text" value"admin" /> <br> <input …

SpringCloud--FeignGateWay

Feign 创建项目勾选web SpringWeb 1.0 创建生产者SpringCloudFeignProvider 端口号:8081 pom.xml引入依赖 <!--nacos依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery<…

###C语言程序设计-----C语言学习(5)#

前言&#xff1a;感谢您的关注哦&#xff0c;我会持续更新编程相关知识&#xff0c;愿您在这里有所收获。如果有任何问题&#xff0c;欢迎沟通交流&#xff01;期待与您在学习编程的道路上共同进步&#xff01; 一. 主干知识的学习 1.switch语句 switch语句可以处理多分支选…

《HelloGitHub》第 94 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …

Python根据Excel表进行文件重命名

一、问题背景 在日常办公过程中&#xff0c;批量重命名是经常使用的操作。之前我们已经进行了初步探索&#xff0c;主要是通过批处理文件、renamer软件或者Python中的pathlib等模块对当前目录下的文件进行批量重命名。 而今天我们要使用的是PythonExcel的方法对指定目录下的文…

翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一 GPT-4 Vision 的 7 个实际用例 Pre-requisites:先决条件&#xff1a; 订阅 ChatGPT Plus 以访问 GPT-4 Vision。如果您不熟悉 Streamlit&#xff0c;请按照安装步骤操作。 1. 绘制您的应…

机器学习周报第30周

目录 摘要Abstract一、文献阅读1 论文标题2 论文摘要3 过去方案4 论文方案5 相关代码 摘要 Abstract 一、文献阅读 1 论文标题 Accurate one step and multistep forecasting of very short-term PV power using LSTM-TCN model - ScienceDirect 2 论文摘要 准确的光伏功…

洛谷P5735 【深基7.例1】距离函数(C语言)

首先&#xff0c;三角形周长为 其次(x1,x2)和 &#xff08;y1,y2&#xff09;的距离 然后就可以为所欲为 #include <stdio.h> #include <math.h>double distance(double a1, double b1, double a2, double b2) {return sqrt((a1 - a2) * (a1 - a2) (b1 - b2) * …

新建一个springboot 项目

1&#xff09;第一步&#xff1a; 2&#xff09;第二步&#xff1a; 3&#xff09;第三步&#xff0c;点击File&#xff0c;Settings 4&#xff09;请求页面结果显示如下&#xff1a; 修改端口如下&#xff1a;在application.properties中 添加server:port 9090

【幻兽帕鲁】开服务器,高性能高带宽(100mbps),免费!!!【学生党强推】

【幻兽帕鲁】开服务器&#xff0c;高性能高带宽&#xff08;100mbps&#xff09;&#xff0c;免费&#xff01;&#xff01;&#xff01;【学生党强推】 教程相关视频地址&#xff1a;https://www.bilibili.com/video/BV16e411Y7Fd/ 目前幻兽帕鲁开服务器有以下几套比较性价比的…

CUDA下载安装教程,新手详细

目录 一、下载二、安装三、 设置环境变量四、补丁安装 由于项目需要安装特定版本的CUDA&#xff0c;现记录安装过程。 一、下载 进入官方下载地址&#xff1a;https://developer.nvidia.com/cuda-toolkit-archive 选择自己需要的版本。如果没有明确要求版本号&#xff0c;那么…