<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        D3.js實(shí)現(xiàn)拓?fù)鋱D的示例代碼

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:12:10
        文檔

        D3.js實(shí)現(xiàn)拓?fù)鋱D的示例代碼

        D3.js實(shí)現(xiàn)拓?fù)鋱D的示例代碼:最近寫(xiě)項(xiàng)目需要畫(huà)出應(yīng)用程序調(diào)用鏈的網(wǎng)路拓?fù)鋱D,完全自己寫(xiě)需要花費(fèi)些時(shí)間,那么首先想到的是echarts,但echarts的自定義寫(xiě)法寫(xiě)起來(lái)非常麻煩,而且它的文檔都是基于配置說(shuō)明的,對(duì)于自定義開(kāi)發(fā)不太方便,嘗試后果斷放棄,改用D3.js,自己完全可控。 我們先看
        推薦度:
        導(dǎo)讀D3.js實(shí)現(xiàn)拓?fù)鋱D的示例代碼:最近寫(xiě)項(xiàng)目需要畫(huà)出應(yīng)用程序調(diào)用鏈的網(wǎng)路拓?fù)鋱D,完全自己寫(xiě)需要花費(fèi)些時(shí)間,那么首先想到的是echarts,但echarts的自定義寫(xiě)法寫(xiě)起來(lái)非常麻煩,而且它的文檔都是基于配置說(shuō)明的,對(duì)于自定義開(kāi)發(fā)不太方便,嘗試后果斷放棄,改用D3.js,自己完全可控。 我們先看

        最近寫(xiě)項(xiàng)目需要畫(huà)出應(yīng)用程序調(diào)用鏈的網(wǎng)路拓?fù)鋱D,完全自己寫(xiě)需要花費(fèi)些時(shí)間,那么首先想到的是echarts,但echarts的自定義寫(xiě)法寫(xiě)起來(lái)非常麻煩,而且它的文檔都是基于配置說(shuō)明的,對(duì)于自定義開(kāi)發(fā)不太方便,嘗試后果斷放棄,改用D3.js,自己完全可控。

        我們先看看效果

        我把代碼分享下,供和我一樣剛接觸D3的同學(xué)參考,不對(duì)的地方歡迎指正!

        完整代碼:

        html:

        <!DOCTYPE html>
        <html lang="en">
        <head>
         <meta charset="UTF-8">
         <title>Title</title>
         <script type="text/javascript" src="http://d3js.org/d3.v5.min.js">
         </script>
         <style>
         body{
         overflow: hidden;
         }
         #togo{
         width: 800px;
         height:500px;
         border:1px solid #ccc;
         user-select: none;
         }
         #togo text{
         font-size:10px;/*和js里保持一致*/
         fill:#1A2C3F;
         text-anchor: middle;
         }
         #togo .node-other{
        
         text-anchor: start;
         }
         #togo .health1{
         stroke:#92E1A2;
         }
         #togo .health2{
         stroke:orange;
         }
         #togo .health3{
         stroke:red;
         }
         #togo #cloud,#togo #database{
         fill:#ccc;
         }
         #togo .link{
         stroke:#E4E8ED;
         }
         #togo .node-title{
         font-size: 14px;
         }
         #togo .node-code circle{
         fill:#3F86F5;
         }
         #togo .node-code text{
         fill:#fff;
         }
         #togo .node-bg{
         fill:#fff;
         }
         #togo .arrow{
         fill:#E4E8ED;
         }
         </style>
         <script src="data.js"></script>
        </head>
        <body>
         <svg id="togo" width="800" height="500">
        
         </svg>
         <script src="togo.js"></script>
         <script>
        
         </script>
        
         <script>
         let t=new Togo('#togo',__options);
         t.render();
         </script>
        </body>
        </html>
        

        JS:

        const fontSize = 10;
        const symbolSize = 40;
        const padding = 10;
        
        /*
        * 調(diào)用 new Togo(svg,option).render();
        * */
        class Togo {
         /**/
         constructor(svg, option) {
         this.data = option.data;
         this.edges = option.edges;
         this.svg = d3.select(svg);
        
         }
        
         //主渲染方法
         render() {
         this.scale = 1;
         this.width = this.svg.attr('width');
         this.height = this.svg.attr('height');
         this.container = this.svg.append('g')
         .attr('transform', 'scale(' + this.scale + ')');
        
        
         this.initPosition();
         this.initDefineSymbol();
         this.initLink();
         this.initNode();
         this.initZoom();
        
         }
        
         //初始化節(jié)點(diǎn)位置
         initPosition() {
         let origin = [this.width / 2, this.height / 2];
         let points = this.getVertices(origin, Math.min(this.width, this.height) * 0.3, this.data.length);
         this.data.forEach((item, i) => {
         item.x = points[i].x;
         item.y = points[i].y;
         })
         }
        
         //根據(jù)多邊形獲取定位點(diǎn)
         getVertices(origin, r, n) {
         if (typeof n !== 'number') return;
         var ox = origin[0];
         var oy = origin[1];
         var angle = 360 / n;
         var i = 0;
         var points = [];
         var tempAngle = 0;
         while (i < n) {
         tempAngle = (i * angle * Math.PI) / 180;
         points.push({
         x: ox + r * Math.sin(tempAngle),
         y: oy + r * Math.cos(tempAngle),
         });
         i++;
         }
         return points;
         }
        
         //兩點(diǎn)的中心點(diǎn)
         getCenter(x1, y1, x2, y2) {
         return [(x1 + x2) / 2, (y1 + y2) / 2]
         }
        
         //兩點(diǎn)的距離
         getDistance(x1, y1, x2, y2) {
         return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
         }
        
         //兩點(diǎn)角度
         getAngle(x1, y1, x2, y2) {
         var x = Math.abs(x1 - x2);
         var y = Math.abs(y1 - y2);
         var z = Math.sqrt(x * x + y * y);
         return Math.round((Math.asin(y / z) / Math.PI * 180));
         }
        
        
         //初始化縮放器
         initZoom() {
         let self = this;
         let zoom = d3.zoom()
         .scaleExtent([0.7, 3])
         .on('zoom', function () {
         self.onZoom(this)
         });
         this.svg.call(zoom)
         }
        
         //初始化圖標(biāo)
         initDefineSymbol() {
         let defs=this.container.append('svg:defs');
        
         //箭頭
         const marker = defs
         .selectAll('marker')
         .data(this.edges)
         .enter()
         .append('svg:marker')
         .attr('id', (link, i) => 'marker-' + i)
         .attr('markerUnits', 'userSpaceOnUse')
         .attr('viewBox', '0 -5 10 10')
         .attr('refX', symbolSize / 2 + padding)
         .attr('refY', 0)
         .attr('markerWidth', 14)
         .attr('markerHeight', 14)
         .attr('orient', 'auto')
         .attr('stroke-width', 2)
         .append('svg:path')
         .attr('d', 'M2,0 L0,-3 L9,0 L0,3 M2,0 L0,-3')
         .attr('class','arrow')
        
        
         //數(shù)據(jù)庫(kù)
         let database =defs.append('g')
         .attr('id','database')
         .attr('transform','scale(0.042)');
        
         database.append('path')
         .attr('d','M512 800c-247.42 0-448-71.63-448-160v160c0 88.37 200.58 160 448 160s448-71.63 448-160V640c0 88.37-200.58 160-448 160z')
        
         database.append('path')
         .attr('d','M512 608c-247.42 0-448-71.63-448-160v160c0 88.37 200.58 160 448 160s448-71.63 448-160V448c0 88.37-200.58 160-448 160z') ;
        
         database.append('path')
         .attr('d','M512 416c-247.42 0-448-71.63-448-160v160c0 88.37 200.58 160 448 160s448-71.63 448-160V256c0 88.37-200.58 160-448 160z') ;
        
         database.append('path')
         .attr('d','M64 224a448 160 0 1 0 896 0 448 160 0 1 0-896 0Z');
        
         //云
         let cloud=defs.append('g')
         .attr('id','cloud')
         .attr('transform','scale(0.042)')
         .append('path')
         .attr('d','M709.3 285.8C668.3 202.7 583 145.4 484 145.4c-132.6 0-241 102.8-250.4 233-97.5 27.8-168.5 113-168.5 213.8 0 118.9 98.8 216.6 223.4 223.4h418.9c138.7 0 251.3-118.8 251.3-265.3 0-141.2-110.3-256.2-249.4-264.5z')
        
        
        
         }
        
         //初始化鏈接線
         initLink() {
         this.drawLinkLine();
         this.drawLinkText();
         }
        
         //初始化節(jié)點(diǎn)
         initNode() {
         var self = this;
         //節(jié)點(diǎn)容器
         this.nodes = this.container.selectAll(".node")
         .data(this.data)
         .enter()
         .append("g")
         .attr("transform", function (d) {
         return "translate(" + d.x + "," + d.y + ")";
         })
         .call(d3.drag()
         .on("drag", function (d) {
         self.onDrag(this, d)
         })
         )
         .on('click', function () {
         alert()
         })
        
         //節(jié)點(diǎn)背景默認(rèn)覆蓋層
         this.nodes.append('circle')
         .attr('r', symbolSize / 2 + padding)
         .attr('class', 'node-bg');
        
         //節(jié)點(diǎn)圖標(biāo)
         this.drawNodeSymbol();
         //節(jié)點(diǎn)標(biāo)題
         this.drawNodeTitle();
         //節(jié)點(diǎn)其他說(shuō)明
         this.drawNodeOther();
         this.drawNodeCode();
        
         }
        
         //畫(huà)節(jié)點(diǎn)語(yǔ)言標(biāo)識(shí)
         drawNodeCode() {
         this.nodeCodes = this.nodes.filter(item => item.type == 'app')
         .append('g')
         .attr('class','node-code')
         .attr('transform', 'translate(' + -symbolSize / 2 + ',' + symbolSize / 3 + ')')
        
         this.nodeCodes
         .append('circle')
         .attr('r', d => fontSize / 2 * d.code.length / 2 + 3)
        
         this.nodeCodes
         .append('text')
         .attr('dy', fontSize / 2)
         .text(item => item.code);
        
         }
        
         //畫(huà)節(jié)點(diǎn)圖標(biāo)
         drawNodeSymbol() {
         //繪制節(jié)點(diǎn)
         this.nodes.filter(item=>item.type=='app')
         .append("circle")
         .attr("r", symbolSize / 2)
         .attr("fill", '#fff')
         .attr('class', function (d) {
         return 'health'+d.health;
         })
         .attr('stroke-width', '5px')
        
        
         this.nodes.filter(item=>item.type=='database')
         .append('use')
         .attr('xlink:href','#database')
         .attr('x',function () {
         return -this.getBBox().width/2
         })
         .attr('y',function () {
         return -this.getBBox().height/2
         })
        
         this.nodes.filter(item=>item.type=='cloud')
         .append('use')
         .attr('xlink:href','#cloud')
         .attr('x',function () {
         return -this.getBBox().width/2
         })
         .attr('y',function () {
         return -this.getBBox().height/2
         })
         }
        
         //畫(huà)節(jié)點(diǎn)右側(cè)信息
         drawNodeOther() {
         //如果是應(yīng)用的時(shí)候
         this.nodeOthers = this.nodes.filter(item => item.type == 'app')
         .append("text")
         .attr("x", symbolSize / 2 + padding)
         .attr("y", -5)
         .attr('class','node-other')
        
         this.nodeOthers.append('tspan')
         .text(d => d.time + 'ms');
        
         this.nodeOthers.append('tspan')
         .text(d => d.rpm + 'rpm')
         .attr('x', symbolSize / 2 + padding)
         .attr('dy', '1em');
        
         this.nodeOthers.append('tspan')
         .text(d => d.epm + 'epm')
         .attr('x', symbolSize / 2 + padding)
         .attr('dy', '1em')
         }
        
         //畫(huà)節(jié)點(diǎn)標(biāo)題
         drawNodeTitle() {
         //節(jié)點(diǎn)標(biāo)題
         this.nodes.append("text")
         .attr('class','node-title')
         .text(function (d) {
         return d.name;
         })
         .attr("dy", symbolSize)
        
         this.nodes.filter(item => item.type == 'app').append("text")
         .text(function (d) {
         return d.active + '/' + d.total;
         })
         .attr('dy', fontSize / 2)
         .attr('class','node-call')
        
         }
        
         //畫(huà)節(jié)點(diǎn)鏈接線
         drawLinkLine() {
         let data = this.data;
         if (this.lineGroup) {
         this.lineGroup.selectAll('.link')
         .attr(
         'd', link => genLinkPath(link),
         )
         } else {
         this.lineGroup = this.container.append('g')
        
        
         this.lineGroup.selectAll('.link')
         .data(this.edges)
         .enter()
         .append('path')
         .attr('class', 'link')
         .attr(
         'marker-end', (link, i) => 'url(#' + 'marker-' + i + ')'
         ).attr(
         'd', link => genLinkPath(link),
         ).attr(
         'id', (link, i) => 'link-' + i
         )
         .on('click', () => { alert() })
         }
        
         function genLinkPath(d) {
         let sx = data[d.source].x;
         let tx = data[d.target].x;
         let sy = data[d.source].y;
         let ty = data[d.target].y;
         return 'M' + sx + ',' + sy + ' L' + tx + ',' + ty;
         }
         }
        
        
         drawLinkText() {
         let data = this.data;
         let self = this;
         if (this.lineTextGroup) {
         this.lineTexts
         .attr('transform', getTransform)
        
         } else {
         this.lineTextGroup = this.container.append('g')
        
         this.lineTexts = this.lineTextGroup
         .selectAll('.linetext')
         .data(this.edges)
         .enter()
         .append('text')
         .attr('dy', -2)
         .attr('transform', getTransform)
         .on('click', () => { alert() })
        
         this.lineTexts
         .append('tspan')
         .text((d, i) => this.data[d.source].lineTime + 'ms,' + this.data[d.source].lineRpm + 'rpm');
        
         this.lineTexts
         .append('tspan')
         .text((d, i) => this.data[d.source].lineProtocol)
         .attr('dy', '1em')
         .attr('dx', function () {
         return -this.getBBox().width / 2
         })
         }
        
         function getTransform(link) {
         let s = data[link.source];
         let t = data[link.target];
         let p = self.getCenter(s.x, s.y, t.x, t.y);
         let angle = self.getAngle(s.x, s.y, t.x, t.y);
         if (s.x > t.x && s.y < t.y || s.x < t.x && s.y > t.y) {
         angle = -angle
         }
         return 'translate(' + p[0] + ',' + p[1] + ') rotate(' + angle + ')'
         }
         }
        
        
         update(d) {
         this.drawLinkLine();
         this.drawLinkText();
         }
        
         //拖拽方法
         onDrag(ele, d) {
         d.x = d3.event.x;
         d.y = d3.event.y;
         d3.select(ele)
         .attr('transform', "translate(" + d3.event.x + "," + d3.event.y + ")")
         this.update(d);
         }
        
         //縮放方法
         onZoom(ele) {
         var transform = d3.zoomTransform(ele);
         this.scale = transform.k;
         this.container.attr('transform', "translate(" + transform.x + "," + transform.y + ")scale(" + transform.k + ")")
         }
        
        }
        

        數(shù)據(jù):

        let __options={
         data:[{
         type:'app',
         name: 'monitor-web-server',
         time: 30,
         rpm: 40,
         epm: 50,
         active: 3,
         total: 5,
         code: 'java',
         health: 1,
         lineProtocol: 'http',
         lineTime: 12,
         lineRpm: 34,
         }, {
         type:'database',
         name: 'Mysql',
         time: 30,
         rpm: 40,
         epm: 50,
         active: 3,
         total: 5,
         code: 'java',
         health: 2,
         lineProtocol: 'http',
         lineTime: 12,
         lineRpm: 34,
        
         },
         {
         type:'app',
         name: 'Redis',
         time: 30,
         rpm: 40,
         epm: 50,
         active: 3,
         total: 5,
         code: 'java',
         health: 3,
         lineProtocol: 'http',
         lineTime: 12,
         lineRpm: 34,
        
         }, {
         type:'cloud',
         name: 'ES',
         time: 30,
         rpm: 40,
         epm: 50,
         active: 3,
         total: 5,
         code: 'java',
         health: 1,
         lineProtocol: 'http',
         lineTime: 12,
         lineRpm: 34,
         value: 100
         }
         ],
         edges: [
         {
         source: 0,
         target: 3,
         }, {
         source: 1,
         target: 2,
         }
         , {
         source: 1,
         target: 3,
         },
         {
         source: 0,
         target: 1,
         },
         {
         source: 0,
         target: 2,
         }
         // {
         // source: 3,
         // target: 2,
         // },
         ]
        }

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        D3.js實(shí)現(xiàn)拓?fù)鋱D的示例代碼

        D3.js實(shí)現(xiàn)拓?fù)鋱D的示例代碼:最近寫(xiě)項(xiàng)目需要畫(huà)出應(yīng)用程序調(diào)用鏈的網(wǎng)路拓?fù)鋱D,完全自己寫(xiě)需要花費(fèi)些時(shí)間,那么首先想到的是echarts,但echarts的自定義寫(xiě)法寫(xiě)起來(lái)非常麻煩,而且它的文檔都是基于配置說(shuō)明的,對(duì)于自定義開(kāi)發(fā)不太方便,嘗試后果斷放棄,改用D3.js,自己完全可控。 我們先看
        推薦度:
        標(biāo)簽: 實(shí)現(xiàn) 代碼 d3
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产三级在线观看免费| 国产精品免费高清在线观看| 91精品免费高清在线| 亚洲日产无码中文字幕| 99在线视频免费观看| 久久亚洲高清综合| a级毛片视频免费观看| 亚洲精品无码专区在线在线播放 | 亚洲精品无码久久久久久久 | 91精品导航在线网址免费| 亚洲精品无码鲁网中文电影| 国产无遮挡又黄又爽免费网站| 亚洲色爱图小说专区| a在线观看免费视频| 久久精品国产精品亚洲艾| 99热这里只有精品免费播放| 亚洲国产成人手机在线电影bd | 久久亚洲伊人中字综合精品| 亚洲综合久久精品无码色欲| 成年女人免费视频播放体验区 | 久久亚洲国产成人精品无码区| 两个人看的www高清免费视频| 亚洲国产成人片在线观看无码 | 精品国产免费一区二区三区| 日韩亚洲欧洲在线com91tv| 亚洲最大免费视频网| 亚洲中文字幕无码久久| 免费国内精品久久久久影院| 中文字幕免费在线看电影大全| 亚洲一本综合久久| 欧美三级在线电影免费| 日韩精品视频在线观看免费| 亚洲国产精品无码久久SM| 国产91色综合久久免费分享| 日本亚洲高清乱码中文在线观看| 亚洲人成图片小说网站| 香蕉97超级碰碰碰免费公| 日韩精品无码免费视频| 亚洲成在人线电影天堂色| 免费一级肉体全黄毛片| 69视频在线观看免费|