d3.js 实现企业图谱(基于vue)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了d3.js 实现企业图谱(基于vue)相关的知识,希望对你有一定的参考价值。

参考技术A 前段时间接到公司需求,参考企查查开发=>企业图谱。最开始定的是使用 Relation Graph 实现,用了一段时间后发现这个插件对于一些个性化的需求支持不足,无奈只能另辟新径,后来发现了 d3.js 这个新大陆。
由于这是第一次接触d3,刚开始真是一脸懵,后来通过翻阅资料,先是了解了一下 svg ,然后又把 d3.js 常用的一些api看了看算是有个初步的了解。

使用d3主要需要掌握svg,jquery和d3这几个知识点。
本次使用的是 d3.v5版本的。

html

JS

style

本次开发使得对于d3有一个进一步的了解,虽然主要复杂的功能是参考别人的,但是通过此次使用过后对于一些细枝末节的地方还是可以持续更新优化!
写这个文档主要是为了记录一下过程,并且日后也方便查看。
持续更新。。。

svg
d3中文网站

百度地图标注及结合ECharts图谱数据可视化

本示例中根据企业位置经纬度,在页面右侧百度地图中标注企业名称。同时页面左侧ECharts图谱饼状图用于统计企业行业与注册资本。当右侧百度地图缩放拖拽,左侧ECharts图谱根据右侧地图上出现的企业动态变化。详细过程如下两图所示:

技术分享图片

 

 

技术分享图片

 

 

本示例中有用到Vue.js,以及一个JQuery的表格插件DataTable。详细代码如下所示。

 

一、JSP代码

JSP中注意需要引用相关JS文件,如下所示:

1 <script src="js/jquery-3.2.1.js"></script>
2 <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=q7IDDpeG6pBgm2vRYOCLyI9phWdUD6jY"></script>
3 <script src="js/echarts.js"></script>
4 <script type="text/javascript" src="js/jquery.dataTables.min.js"></script>
5 <script src="https://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.js"></script>
6 <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
7 <script type="text/javascript" src="js/map-vue.js"></script>

 

前端代码仅供参考,如下所示:

 1 <!--左侧信息展示、右侧地图-->
 2 <div id="wholeDiv">
 3     <!--企业信息区域-->
 4     <div id="mapinfo_div" style="position: absolute;top: 61px;left: 0px;width: 35%;height: 86%;">
 5         <div class="innerbox" style="position: absolute;top: 0px;left: 2px;width: 100%;height: 44%;border: 1px solid darkgray;overflow-x: auto">
 6             <div id="mapCorp1" style="position: absolute;left: 0px;top: 0px;width: 420px;height: 100%;float: left;"></div>
 7             <div id="mapCorp2" style="position: absolute;left: 450px;top: 0px;width: 420px;height: 100%;float: left;"></div>
 8             <font class="mapMessage" size="3" color="#808080" style="position: absolute;left: 33%;top: 45%;display: none">地图当前区域未搜到相关企业</font>
 9         </div>
10 
11         <div id="mapCorpList" class="innerbox" style="position: absolute;top: 45%;left: 2px;width: 100%;height: 60%;overflow-y: auto;border: 1px solid darkgray;" >
12             <ul v-for="(corp, corpIndex) in corpList">
13                 <li style="height: 100px;border-bottom:#1db5ee 1px dashed;padding-bottom:10px;margin-bottom:0px;overflow:hidden;">
14                     <a href=""><img width="90" height="90" alt="logo" v-bind:src="corp.corpLogo" style="margin-top: 5px;border:#ccc 1px solid;padding:2px;float:left;"/></a>
15                     <a target="_blank" v-bind:href="‘http://localhost:8080/see_details.do?corp_id=‘+corp.corpId" >
16                         <font id = "map_corpName" style="padding:10px;" size="3"><b>{{ corp.corpName}}</b></font>
17                     </a><br/>
18                     <font style="padding:10px;" size="3">法人:</font>
19                     <font style="padding:0px;color: gray" size="3">{{ corp.operManName}}</font>
20                     <font style="padding:10px;" size="3">注册资本:</font>
21                     <font style="padding:0px;color: gray" size="3">{{ corp.regCapi}}万元</font><br/>
22                     <font style="padding:10px;" size="3">行业:</font>
23                     <font style="padding:0px;color: gray" size="3">{{ corp.belongTrade}}</font><br/>
24                     <span v-if="corp.admitMain != ‘——‘" style="margin-left: 10px;background-color: #1db5ee;"><font size="1.5" color="#ffffff">{{ corp.admitMain}}</font></span>
25                 </li>
26             </ul>
27             <font class="mapMessage" size="3" color="#808080" style="position: absolute;left: 33%;top: 45%;display: none">地图当前区域未搜到相关企业</font>
28         </div>
29 
30         <div id="mapCorpTable" class="innerbox" style="position: absolute;top: 45%;left: 2px;width: 100%;height: 60%;overflow-y: auto;border: 1px solid darkgray;display: none">
31             <table id="showCorpTable" class="display" style="margin-top: 5px">
32                 <thead>
33                 <tr align="left">
34                     <th>公司名称</th>
35                     <th>法人</th>
36                     <th>注册资本(万)</th>
37                     <th>所属行业</th>
38                     <th>详细地址</th>
39                 </tr>
40                 </thead>
41             </table>
42         </div>
43     </div>
44 
45     <!--地图区域-->
46     <div id="mapCorp_div" style="position: absolute;top: 61px;left: 36%;width: 64%;height: 90%;border: 1px solid lightgray;overflow: hidden;font-family: ‘微软雅黑‘;">
47         <div id="allmap" style="width: 100%;height: 100%;float:left;">
48         </div>
49         
50         <div style="position: absolute;top: 38%;left: 0px;width: 50px;height: 100px;border-radius:0 50px 50px 0;background-color: darkred;opacity:0.6;float:left;">
51             <img id = "map_right" src="/icon/map_right.png" width="60" height="50" style="margin-top: 25px"/>
52             <img id = "map_left" src="/icon/map_left.png" width="60" height="50" style="margin-top: 25px;display: none"/>
53         </div>
54     </div>
55 
56     <!--搜索区域-->
57     <div id="search" style="position: fixed;top: 10%;left: 76%;width: 20%;height: 7%;background-color: white;box-shadow: 0px 4px 8px rgba(44, 35, 35, 0.6)">
58         <input type="text" ref="cityName" placeholder="请输入城市名称" @keyup.enter="locationByCityName"
59                style="height: 35px;width: 220px;border: none;outline:none;font-size: 18px;margin-top: 7px"/>
60         <div style="position: absolute;top: 15%;left: 84%;height: 68%;width: 12%;background-image: url(/icon/map_search.png)" v-on:click="locationByCityName();">
61         </div>
62     </div>
63 </div>

 

 

二、JavaScript代码,map-vue.js文件

  1 var vm = new Vue({
  2     el: "#wholeDiv",
  3     data: {
  4         map: "", // 百度地图全局变量
  5         //regionList: [],
  6         corpList: [],
  7     },
  8     mounted: function () {
  9         var _this = this;
 10         map = new BMap.Map("allmap");
 11         var initPoint = new BMap.Point(118.801372, 32.061892);
 12         map.centerAndZoom(initPoint, 15); // 初始化地图,设置中心坐标点和地图级别
 13         map.addControl(new BMap.NavigationControl({enableGeolocation: true})); // 添加比例尺控件
 14         map.addControl(new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT})); // 左上角
 15         map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放
 16 
 17         this.getMapList();
 18 
 19         // 监听缩放事件
 20         map.addEventListener(‘zoomend‘, function (event) {
 21             console.log("缩放");
 22             _this.mapResize(event.target);
 23         });
 24         // 监听拖拽事件
 25         map.addEventListener(‘dragend‘, function (event) {
 26             console.log("拖拽");
 27             _this.mapResize(event.target);
 28         })
 29     },
 30     methods: {
 31         /**
 32          * 根据城市名称定位
 33          */
 34         locationByCityName: function () {
 35             var cityName = this.$refs.cityName.value;
 36             map.centerAndZoom(cityName,11);
 37             var _this = this;
 38             // 地图加载完成事件
 39             // 不加载完成,获取的是上一次的坐标
 40             map.addEventListener("tilesloaded", function (event){
 41                 _this.mapResize(event.target);
 42             });
 43         },
 44         /**
 45          * 获取数据
 46          */
 47         getMapList: function () {
 48             this.getAllCorp();
 49             this.getCorpDataTable();
 50         },
 51 
 52 
 53         /**
 54          * 获取所有公司坐标点
 55          */
 56         getAllCorp: function () {
 57             var _this = this;
 58             this.$http.get("http://localhost:8080/mapCorp.do").then(function (result) {
 59                 var mapCorpList = result.body;
 60                 _this.corpList = mapCorpList;
 61                 for (var i = 0; i < mapCorpList.length; i++) {
 62                     var point = new BMap.Point(mapCorpList[i].longitude, mapCorpList[i].latitude); // 标记坐标点
 63                     var label = new BMap.Label(mapCorpList[i].corpName, {offset: new BMap.Size(20, -10)});// 标记说明
 64                     _this.addMarker(point, label);
 65                 }
 66                 _this.getTradeEcharts(mapCorpList);
 67                 _this.getCapiEcharts(mapCorpList);
 68             });
 69         },
 70 
 71 
 72         /**
 73          * 获取地图范围内的公司
 74          */
 75         getCorpInsizeMap: function (leftLongitude, leftLatitude, rightLongitude, rightLatitude) {
 76             var _this = this;
 77             this.$http.get("http://localhost:8080/mapInside.do?leftLongitude=" + leftLongitude +
 78                 "&leftLatitude=" + leftLatitude +
 79                 "&rightLongitude=" + rightLongitude +
 80                 "&rightLatitude=" + rightLatitude).then(function (result) {
 81                 _this.corpList = result.body;
 82                 _this.getTradeEcharts(result.body);
 83                 _this.getCapiEcharts(result.body);
 84             });
 85         },
 86 
 87 
 88         /**
 89          * 企业行业图谱展示
 90          */
 91         getTradeEcharts: function (data) {
 92             var newList = data;
 93             var tempJSON = [];
 94             //遍历数组,并分类统计,放入tempJSON中
 95             for(var i = 0; i < newList.length; i++) {
 96                 if(!tempJSON[newList[i].belongTrade]) {
 97                     var arr = [];
 98                     arr.push(newList[i]);
 99                     tempJSON[newList[i].belongTrade] = arr;
100                 }else {
101                     tempJSON[newList[i].belongTrade].push(newList[i]);
102                 }
103             }
104             console.log(tempJSON);
105             console.log("tempJSON长度"+Object.keys(tempJSON).length);
106 
107             var tradeArr = [];
108             var i = 0;
109             for(var trade in tempJSON){
110                 if(i > 4){
111                     break;
112                 }
113                 tradeArr[i] = {
114                     value: tempJSON[trade].length,
115                     name: trade
116                 }
117                 i++;
118             }
119 
120             var myChart = echarts.init(document.getElementById(‘mapCorp1‘));
121             option = {
122                 title : {
123                     text: ‘企业所属行业分析(TOP5)‘,
124                     x:‘center‘
125                 },
126                 tooltip : {
127                     trigger: ‘item‘,
128                     formatter: "{a} <br/>{b} : {c} ({d}%)"
129                 },
130                 series : [
131                     {
132                         name: ‘所属行业‘,
133                         type: ‘pie‘,
134                         radius : ‘55%‘,
135                         center: [‘50%‘, ‘55%‘],
136                         data: tradeArr,
137                         itemStyle: {
138                             emphasis: {
139                                 shadowBlur: 10,
140                                 shadowOffsetX: 0,
141                                 shadowColor: ‘rgba(0, 0, 0, 0.5)‘
142                             }
143                         }
144                     }
145                 ]
146             };
147             myChart.setOption(option);
148         },
149 
150 
151         /**
152          * 企业资本图谱展示
153          */
154         getCapiEcharts: function (data) {
155             if(data.length > 0){
156                 $(‘#mapCorp1‘).css("display","block");
157                 $(‘#mapCorp2‘).css("display","block");
158                 $(‘.mapMessage‘).css("display","none");
159 
160                 var class1 = 0;
161                 var class2 = 0;
162                 var class3 = 0;
163                 var class4 = 0;
164                 var class5 = 0;
165                 //遍历数组,并分类统计,放入tempJSON中
166                 for(var i = 0; i < data.length; i++) {
167                     if( 0 < data[i].regCapi && data[i].regCapi <= 100){
168                         class1 += 1;
169                     }else if( 100 < data[i].regCapi && data[i].regCapi <= 500){
170                         class2 += 1;
171                     }else if( 500 < data[i].regCapi && data[i].regCapi <= 1000){
172                         class3 += 1;
173                     }else if( 1000 < data[i].regCapi && data[i].regCapi <= 5000){
174                         class4 += 1;
175                     }else if( 5000 < data[i].regCapi){
176                         class5 += 1;
177                     }
178                 }
179 
180                 var tradeArr = [];
181                 if(class1 != 0){
182                     tradeArr[0] = {
183                         value: class1,
184                         name: "0-100万"
185                     }
186                 };
187                 if(class2 != 0){
188                     tradeArr[1] = {
189                         value: class2,
190                         name: "101-500万"
191                     }
192                 };
193                 if(class3 != 0){
194                     tradeArr[2] = {
195                         value: class3,
196                         name: "501-1000万"
197                     }
198                 };
199                 if(class4 != 0){
200                     tradeArr[3] = {
201                         value: class4,
202                         name: "1001-5000万"
203                     }
204                 };
205                 if(class5 != 0){
206                     tradeArr[4] = {
207                         value: class5,
208                         name: "5001万以上"
209                     }
210                 };
211 
212 
213                 var myChart = echarts.init(document.getElementById(‘mapCorp2‘));
214                 option = {
215                     title : {
216                         text: ‘企业注册资本统计‘,
217                         x:‘center‘
218                     },
219                     tooltip : {
220                         trigger: ‘item‘,
221                         formatter: "{a} <br/>{b} : {c} ({d}%)"
222                     },
223                     series : [
224                         {
225                             name: ‘注册资本‘,
226                             type: ‘pie‘,
227                             radius : ‘55%‘,
228                             center: [‘50%‘, ‘55%‘],
229                             data: tradeArr,
230                             itemStyle: {
231                                 emphasis: {
232                                     shadowBlur: 10,
233                                     shadowOffsetX: 0,
234                                     shadowColor: ‘rgba(0, 0, 0, 0.5)‘
235                                 }
236                             }
237                         }
238                     ]
239                 };
240                 myChart.setOption(option);
241             }else{
242                 $(‘#mapCorp1‘).css("display","none");
243                 $(‘#mapCorp2‘).css("display","none");
244                 $(‘.mapMessage‘).css("display","block");
245             }
246         },
247 
248 
249         /**
250          * 表格展示
251          */
252         getCorpDataTable: function () {
253             $(‘#showCorpTable‘).DataTable({
254                 "ajax" : "http://localhost:8080/tableCorp.do",
255                 "pageLength" : 5,
256                 "pagingType" : "full_numbers",
257                 "language" : {
258                     "emptyTable" : "无可用数据",
259                     "infoEmpty" : "没有记录可以显示",
260                     "loadingRecords" : "请等待,数据正在加载中......",
261                     "search" : "搜索",
262                     "lengthMenu" : "Show _MENU_ entries",
263                     "lengthMenu" : ‘显示 <select>‘
264                     + ‘<option value="5">5</option>‘
265                     + ‘<option value="10">10</option>‘
266                     + ‘<option value="20">20</option>‘
267                     + ‘<option value="30">30</option>‘
268                     + ‘<option value="40">40</option>‘
269                     + ‘<option value="-1">所有</option>‘
270                     + ‘</select> 记录‘,
271                     "info" : "第_PAGE_页(共_PAGES_页)",
272                     "paginate" : {
273                         "first" : ‘首页‘,
274                         "previous" : ‘上一页‘,
275                         "next" : ‘下一页‘,
276                         "last" : ‘尾页‘
277                     },
278                     "aria" : {
279                         "paginate" : {
280                             "first" : ‘First‘,
281                             "previous" : ‘Previous‘,
282                             "next" : ‘Next‘,
283                             "last" : ‘Last‘
284                         }
285                     }
286                 },
287                 "columns" : [ {
288                     "data" : "corpName"
289                 }, {
290                     "data" : "operManName"
291                 }, {
292                     "data" : "regCapi"
293                 }, {
294                     "data" : "belongTrade"
295                 }, {
296                     "data" : "corpAddr"
297                 }  ]
298             });
299         },
300 
301 
302         /**
303          * 标记坐标点
304          * @param corpPoint
305          * @param corpNameLabel
306          */
307         addMarker: function (corpPoint, corpNameLabel) {
308             var marker = new BMap.Marker(corpPoint);
309             marker.setLabel(corpNameLabel);
310             map.addOverlay(marker);
311         },
312 
313 
314         /**
315          * 地图缩放
316          */
317         mapResize: function (_map) {
318             // 获取当前地图边界
319             var bounds = _map.getBounds(),
320                 southWest = bounds.getSouthWest(),  // 西北角
321                 northEast = bounds.getNorthEast();  // 东北角
322 
323             var zoomLevel = _map.getZoom();
324 
325             params = {
326                 level: zoomLevel,
327                 leftLongitude: southWest.lng,   // 左上角
328                 leftLatitude: northEast.lat,
329                 rightLongitude: northEast.lng,  // 右下角
330                 rightLatitude: southWest.lat
331             };
332 
333             // 搜索地图范围内的公司
334             // 每当地图大小改变,就重新搜索
335             this.getCorpInsizeMap(params.leftLongitude, params.leftLatitude,
336                 params.rightLongitude, params.rightLatitude);
337 
338             // 默认缩放级别为15
339 
340             console.log("左上角:" + params.leftLongitude+ "," + params.leftLatitude);
341             console.log("右下角:" + params.rightLongitude + "," + params.rightLatitude);
342         }
343     }
344 });

 

 1 $(‘#map_right‘).click(function () {
 2     $(this).css("display","none");
 3     $("#map_left").css("display","block");
 4     $("#mapCorpList").css("display","none");
 5     $("#mapCorpTable").css("display","block");
 6 
 7     $("#mapinfo_div").width($("#mapinfo_div").width() + 400);
 8     $("#mapCorp_div").width($("#mapCorp_div").width() - 400);
 9     $("#mapCorp_div").css("margin-left",400);
10 });
11 $(‘#map_left‘).click(function () {
12     $(this).css("display","none");
13     $("#map_right").css("display","block");
14     $("#mapCorpTable").css("display","none");
15     $("#mapCorpList").css("display","block");
16 
17     $("#mapinfo_div").width($("#mapinfo_div").width() - 400);
18     $("#mapCorp_div").width($("#mapCorp_div").width() + 400);
19     $("#mapCorp_div").css("margin-left",0);
20 });

 

 

三、Controller层代码

 1 package controller;
 2 
 3 import entity.BaiduMapCorp;
 4 import net.sf.json.JSONArray;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.stereotype.Controller;
 7 import org.springframework.web.bind.annotation.*;
 8 import service.BaiduMapService;
 9 
10 import java.util.List;
11 
12 @Controller
13 public class BaiduMapController {
14 
15     @Autowired
16     BaiduMapService baiduMapService;
17 
18 
19     //获取地图上所有企业
20     @GetMapping("/mapCorp.do")
21     @ResponseBody
22     public List<BaiduMapCorp> mapPointList() {
23         List<BaiduMapCorp> mapList = baiduMapService.getAllMapCorp();
24         return mapList;
25     }
26 
27 
28     //获得当前位置所有公司
29     @RequestMapping("/mapInside.do")
30     @ResponseBody
31     public List<BaiduMapCorp> getCorpInsideMap(@RequestParam(value = "leftLongitude") double leftLongitude,
32                                                @RequestParam(value = "leftLatitude") double leftLatitude,
33                                                @RequestParam(value = "rightLongitude") double rightLongitude,
34                                                @RequestParam(value = "rightLatitude") double rightLatitude) {
35         return baiduMapService.getCorpInsideMap(leftLongitude, leftLatitude, rightLongitude, rightLatitude);
36     }
37 
38     //datatable获取地图上所有企业
39     @RequestMapping(value = "/tableCorp.do", produces = "text/plain;charset=UTF-8")
40     @ResponseBody
41     public String getTableCorp() {
42         List<BaiduMapCorp> mapList = baiduMapService.getTableCorp();
43         String result = "{" +""data""+":"+ JSONArray.fromObject(mapList).toString()+"}";
44         System.out.println(result);
45         return result;
46     }
47 
48 }

 

四、实体类

  1 package entity;
  2 
  3 /**
  4  * 百度地图坐标点
  5  *
  6  */
  7 public class BaiduMapCorp {
  8 
  9     private Integer id;         //ID
 10 
 11     private String corpName;    //公司名称
 12 
 13     private double longitude;   //经度
 14 
 15     private double latitude;    //维度
 16 
 17     private String corpAddr;    //公司地址
 18 
 19     private Integer corpId;     //公司ID
 20 
 21     private String operManName; //公司法人
 22 
 23     private Integer regCapi;    //注册资本
 24 
 25     private String corpLogo;    //企业logo
 26 
 27     private String belongTrade; //所属行业
 28 
 29     private String admitMain;   //企业大类
 30 
 31     public BaiduMapCorp() {
 32     }
 33 
 34     public Integer getId() {
 35         return id;
 36     }
 37 
 38     public void setId(Integer id) {
 39         this.id = id;
 40     }
 41 
 42     public String getCorpName() {
 43         return corpName;
 44     }
 45 
 46     public void setCorpName(String corpName) {
 47         this.corpName = corpName;
 48     }
 49 
 50     public double getLongitude() {
 51         return longitude;
 52     }
 53 
 54     public void setLongitude(double longitude) {
 55         this.longitude = longitude;
 56     }
 57 
 58     public double getLatitude() {
 59         return latitude;
 60     }
 61 
 62     public void setLatitude(double latitude) {
 63         this.latitude = latitude;
 64     }
 65 
 66     public String getCorpAddr() {
 67         return corpAddr;
 68     }
 69 
 70     public void setCorpAddr(String corpAddr) {
 71         this.corpAddr = corpAddr;
 72     }
 73 
 74     public Integer getCorpId() {
 75         return corpId;
 76     }
 77 
 78     public void setCorpId(Integer corpId) {
 79         this.corpId = corpId;
 80     }
 81 
 82     public String getOperManName() {
 83         return operManName;
 84     }
 85 
 86     public void setOperManName(String operManName) {
 87         this.operManName = operManName;
 88     }
 89 
 90     public Integer getRegCapi() {
 91         return regCapi;
 92     }
 93 
 94     public void setRegCapi(Integer regCapi) {
 95         this.regCapi = regCapi;
 96     }
 97 
 98     public String getCorpLogo() {
 99         return corpLogo;
100     }
101 
102     public void setCorpLogo(String corpLogo) {
103         this.corpLogo = corpLogo;
104     }
105 
106     public String getBelongTrade() {
107         return belongTrade;
108     }
109 
110     public void setBelongTrade(String belongTrade) {
111         this.belongTrade = belongTrade;
112     }
113 
114     public String getAdmitMain() {
115         return admitMain;
116     }
117 
118     public void setAdmitMain(String admitMain) {
119         this.admitMain = admitMain;
120     }
121 
122 }

 

 

 

至此是关于百度地图标注及结合ECharts图谱数据可视化,仅供参考。

如有疏漏错误之处,还请不吝赐教!

 

以上是关于d3.js 实现企业图谱(基于vue)的主要内容,如果未能解决你的问题,请参考以下文章

在Vue项目里面使用d3.js

制造业知识图谱展示和管理的平台-知识图谱

Vue + d3.js实现在地图上选点

d3.js入门之DOM操作

实战基于 Vue,使用 D3.js 画一个疫情趋势折线图

REACT-D3 network-visual-graph(关系图谱)