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)的主要内容,如果未能解决你的问题,请参考以下文章