1. 程式人生 > >Vue和d3.js(v4)力導向圖force結合使用,v3版本升級v4【一】

Vue和d3.js(v4)力導向圖force結合使用,v3版本升級v4【一】

前段時間因為參與專案涉密,所以一直沒有更新部落格,有些博友給我私信或者留言要部分博文的原始碼,因為我的電腦更換,demo的原始碼沒有備份 所以無法提供。大家可針對具體問題問我,有空我定會回覆的。另外轉發文章請說明出處,謝謝關注! 之前有多篇博文介紹了d3力導向圖的繪製過程的一些問題,現在由於效能和UI的要求,要升級d3版本。因為v3版本現在使用的不多了,網上可找的資料不多且拓展性不好,因此花了點時間做了版本升級。 ### 效果展示 ![](https://img2020.cnblogs.com/blog/1414921/202009/1414921-20200914140127702-2018772202.png) ### 初始化佈局 ```js this.force = d3.forceSimulation(nodes) .force('link', d3.forceLink(links).id(d => d.id).strength(0.6).distance(Math.floor(height / 4))) .force('charge', d3.forceManyBody().strength(-500).distanceMin(50).distanceMax(400)) .force('center', d3.forceCenter()) .force('collision', d3.forceCollide().radius(50)) .velocityDecay(0.5) ``` 基礎的配置,中文api裡說的很清楚,[d3-force](https://d3js.org.cn/document/d3-force/#installing) ### 容器建立 ```js let circles = null; // circle元素集合 let lines = null; // line元素集合 let gContainer = null; // 所有元素容器 let gCircle = null; // circle元素容器 let gLine = null; // line元素容器 let svg = null; ...... svg = d3.select('#svgForce') .append('svg') .attr('class', 'svg__container') .attr('viewBox', [-width / 2, -height / 2, width, height]) // g容器,存放其他元素 gContainer = svg .append('g') .attr('class', 'force__container') .attr('transform', 'translate(' + 10 + ',' + 10 + ')'); // 容器 gLine = gContainer.append('g').attr('class', 'force__line'); gCircle = gContainer.append('g').attr('class', 'force__circle'); ``` 容器建立,區分線和節點,便於維護和處理 ### Zoom縮放(僅附上關鍵程式碼,不可貼上複製直接實現哦~) ```js // zoom縮放 let zoom = d3.zoom() .scaleExtent([0.5, 5]) .on('zoom', this.zoomed); // 滑鼠放大縮小 zoomed () { const transform = d3.event.transform; d3.selectAll('.force__container').attr('transform', transform); } .... svg.call(zoom) ``` ### Drag拖拽 ```js // 拖拽 let drag = d3.drag() .on('start', d => { if (!d3.event.active) this.force.alphaTarget(0.8).restart(); // 當alpha為0 設定值讓其動起來 d.fx = d.x; d.fy = d.y; }) .on('drag', d => { d.fx = d3.event.x; d.fy = d3.event.y; d.drag = true; this.force.force('center', null) // 允許隨意拖動 }) .on('end', d => { if (!d3.event.active) this.force.alphaTarget(0); // 靜下來 }) circles = gCircle.selectAll('g') .data(that.nodes, d => `circle${d.id}`) .join('g') .call(drag) ``` 1. d.fx 和 d.fy 表示設定拖拽固定的節點位置,如果想結束拽動後固定,需要在end中 刪除2個值~ 2. 拖拽函式:`start`,`drag`和`end` 3. 設定`this.force.force('center', null)` 是讓節點隨著拖動的位置隨意飄動,不然你拽不走它的,它會被center的向心力吸引的 ### 模擬tick ```js this.force.on('tick', () => { circles.attr('transform', d => `translate(${d.x},${d.y})`); lines.selectAll('path') .attr('d', d => that.linkTick(d)) ``` `linkTick` 是直線平行線的繪製方法,上篇博文有寫,[d3力導圖繪製節點間多條關係平行線的方法](https://www.cnblogs.com/webhmy/p/12464082.html) ### 小結 本文主要寫了下佈局,拖拽,縮放一些基礎方法的改變和使用。下篇將說一些最近調研的一些新玩意,包括文字加底色,線條加底色的