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

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

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題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關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        詳解如何在react中搭建d3力導向圖

        來源:懂視網 責編:小采 時間:2020-11-27 22:21:43
        文檔

        詳解如何在react中搭建d3力導向圖

        詳解如何在react中搭建d3力導向圖:D3js力導向圖搭建 d3js是一個可以基于數據來操作文檔的JavaScript庫。可以使用HTML,CSS,SVG以及Canvas來展示數據。力導向圖能夠用來表示節點間多對多的關系。 實現效果:連線有箭頭,點擊節點能改變該節點顏色和所連接的線的粗細,縮放、拖拽。 版本:4
        推薦度:
        導讀詳解如何在react中搭建d3力導向圖:D3js力導向圖搭建 d3js是一個可以基于數據來操作文檔的JavaScript庫。可以使用HTML,CSS,SVG以及Canvas來展示數據。力導向圖能夠用來表示節點間多對多的關系。 實現效果:連線有箭頭,點擊節點能改變該節點顏色和所連接的線的粗細,縮放、拖拽。 版本:4

        D3js力導向圖搭建

        d3js是一個可以基于數據來操作文檔的JavaScript庫。可以使用HTML,CSS,SVG以及Canvas來展示數據。力導向圖能夠用來表示節點間多對多的關系。

        實現效果:連線有箭頭,點擊節點能改變該節點顏色和所連接的線的粗細,縮放、拖拽。

        版本:4.X

        安裝和導入

        npm安裝:npm install d3

        前端導入:import * as d3 from 'd3';

        一、完整代碼

        import React, { Component } from 'react';
        import PropTypes from 'prop-types';
        import { connect } from 'react-redux';
        import { push } from 'react-router-redux';
        import * as d3 from 'd3';
        import { Row, Form } from 'antd';
        
        import { chartReq} from './actionCreator';
        import './Chart.less';
        
        const WIDTH = 1900;
        const HEIGHT = 580;
        const R = 30;
        
        let simulation;
        
        class Chart extends Component {
         constructor(props, context) {
         super(props, context);
         this.print = this.print.bind(this);
         this.forceChart = this.forceChart.bind(this);
         this.state = {
        
         };
         }
        
         componentWillMount() {
         this.props.dispatch(push('/Chart'));
         }
        
         componentDidMount() {
         this.print();
         }
        
         print() {
         let callback = (res) => { // callback獲取后臺返回的數據,并存入state
         let nodeData = res.data.nodes;
         let relationData = res.data.rels;
         this.setState({
         nodeData: res.data.nodes,
         relationData: res.data.rels,
         });
         let nodes = [];
         for (let i = 0; i < nodeData.length; i++) {
         nodes.push({
         id: (nodeData[i] && nodeData[i].id) || '',
         name: (nodeData[i] && nodeData[i].name) || '',
         type: (nodeData[i] && nodeData[i].type) || '',
         definition: (nodeData[i] && nodeData[i].definition) || '',
         });
         }
         let edges = [];
         for (let i = 0; i < relationData.length; i++) {
         edges.push({
         id: (relationData[i] && (relationData[i].id)) || '',
         source: (relationData[i] && relationData[i].start.id) || '',
         target: (relationData[i] && relationData[i].end.id) || '',
         tag: (relationData[i] && relationData[i].name) || '',
         });
         }
         this.forceChart(nodes, edges); // d3力導向圖內容
         };
         this.props.dispatch(chartReq({ param: param }, callback));
         }
        
         // func
         forceChart(nodes, edges) {
         this.refs['theChart'].innerHTML = '';
        
         // 函數內其余代碼請看拆解代碼
         }
        
         render() {
         
         return (
         <Row style={{ minWidth: 900 }}>
         <div className="outerDiv">
         <div className="theChart" id="theChart" ref="theChart">
         
         </div>
         </div>
         </Row>
         );
         }
         }
        
         Chart.propTypes = {
         dispatch: PropTypes.func.isRequired,
         };
         
         function mapStateToProps(state) {
         return {
         
         };
         }
         
         const WrappedChart = Form.create({})(Chart);
         export default connect(mapStateToProps)(WrappedChart);
        
        

        二、拆解代碼

        1.組件

        <div className="theChart" id="theChart" ref="theChart">
        </div>

        整個圖都將在div里繪制。

        2.構造節點和連線

        let nodes = []; // 節點
        for (let i = 0; i < nodeData.length; i++) {
         nodes.push({
         id: (nodeData[i] && nodeData[i].id) || '',
         name: (nodeData[i] && nodeData[i].name) || '', // 節點名稱
         });
        }
        let edges = []; // 連線
        for (let i = 0; i < relationData.length; i++) {
         edges.push({
         id: (relationData[i] && (relationData[i].id)) || '',
         source: (relationData[i] && relationData[i].start.id) || '', // 開始節點
         target: (relationData[i] && relationData[i].end.id) || '', // 結束節點
         tag: (relationData[i] && relationData[i].name) || '', // 連線名稱
         });
        }
        

        具體怎么構造依據你們的項目數據。

        3.定義力模型

        const simulation = d3.forceSimulation(nodes) // 指定被引用的nodes數組
         .force('link', d3.forceLink(edges).id(d => d.id).distance(150))
         .force('collision', d3.forceCollide(1).strength(0.1))
         .force('center', d3.forceCenter(WIDTH / 2, HEIGHT / 2))
         .force('charge', d3.forceManyBody().strength(-1000).distanceMax(800));

        通過simulation.force()設置力,可以設置這幾種力:

        1. Centering:中心力,設置圖中心點位置。
        2. Collision:節點碰撞作用力,.strength參數范圍為[0,1]。
        3. Links:連線的作用力;.distance設置連線兩端節點的距離。
        4. Many-Body:.strength的參數為正時,模擬重力,為負時,模擬電荷力;.distanceMax的參數設置最大距離。

        Positioning:給定向某個方向的力。

        通過simulation.on監聽力圖元素位置變化。

        4.繪制svg

        const svg = d3.select('#theChart').append('svg') // 在id為‘theChart'的標簽內創建svg
         .style('width', WIDTH)
         .style('height', HEIGHT * 0.9)
         .on('click', () => {
         console.log('click', d3.event.target.tagName);
         })
         .call(zoom); // 縮放
        const g = svg.append('g'); // 則svg中創建g

        創建svg,在svg里創建g,將節點連線等內容放在g內。

        1. select:選擇第一個對應的元素
        2. selectAll:選擇所有對應的元素
        3. append:創建元素

        5.繪制連線

        const edgesLine = svg.select('g')
         .selectAll('line')
         .data(edges) // 綁定數據
         .enter() // 添加數據到選擇集edgepath
         .append('path') // 生成折線
         .attr('d', (d) => { return d && 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y; }) // 遍歷所有數據,d表示當前遍歷到的數據,返回繪制的貝塞爾曲線
         .attr('id', (d, i) => { return i && 'edgepath' + i; }) // 設置id,用于連線文字
         .attr('marker-end', 'url(#arrow)') // 根據箭頭標記的id號標記箭頭
         .style('stroke', '#000') // 顏色
         .style('stroke-width', 1); // 粗細

        連線用貝塞爾曲線繪制:(M  起點X  起點y  L  終點x  終點y)

        6.繪制連線上的箭頭

        const defs = g.append('defs'); // defs定義可重復使用的元素
        const arrowheads = defs.append('marker') // 創建箭頭
         .attr('id', 'arrow')
         // .attr('markerUnits', 'strokeWidth') // 設置為strokeWidth箭頭會隨著線的粗細進行縮放
         .attr('markerUnits', 'userSpaceOnUse') // 設置為userSpaceOnUse箭頭不受連接元素的影響
         .attr('class', 'arrowhead')
         .attr('markerWidth', 20) // viewport
         .attr('markerHeight', 20) // viewport
         .attr('viewBox', '0 0 20 20') // viewBox
         .attr('refX', 9.3 + R) // 偏離圓心距離
         .attr('refY', 5) // 偏離圓心距離
         .attr('orient', 'auto'); // 繪制方向,可設定為:auto(自動確認方向)和 角度值
        arrowheads.append('path')
         .attr('d', 'M0,0 L0,10 L10,5 z') // d: 路徑描述,貝塞爾曲線
         .attr('fill', '#000'); // 填充顏色
        1. viewport:可視區域
        2. viewBox:實際大小,會自動縮放填充viewport

        7.繪制節點

        const nodesCircle = svg.select('g')
         .selectAll('circle')
         .data(nodes)
         .enter()
         .append('circle') // 創建圓
         .attr('r', 30) // 半徑
         .style('fill', '#9FF') // 填充顏色
         .style('stroke', '#0CF') // 邊框顏色
         .style('stroke-width', 2) // 邊框粗細
         .on('click', (node) => { // 點擊事件
         console.log('click');
         })
         .call(drag); // 拖拽單個節點帶動整個圖
        

        創建圓作為節點。

        .call()調用拖拽函數。

        8.節點名稱

        const nodesTexts = svg.select('g')
         .selectAll('text')
         .data(nodes)
         .enter()
         .append('text')
         .attr('dy', '.3em') // 偏移量
         .attr('text-anchor', 'middle') // 節點名稱放在圓圈中間位置
         .style('fill', 'black') // 顏色
         .style('pointer-events', 'none') // 禁止鼠標事件
         .text((d) => { // 文字內容
         return d && d.name; // 遍歷nodes每一項,獲取對應的name
         });
        

        因為文字在節點上層,如果沒有設置禁止鼠標事件,點擊文字將無法響應點擊節點的效果,也無法拖拽節點。

        9.連線名稱

        const edgesText = svg.select('g').selectAll('.edgelabel')
         .data(edges)
         .enter()
         .append('text') // 為每一條連線創建文字區域
         .attr('class', 'edgelabel')
         .attr('dx', 80)
         .attr('dy', 0);
        edgesText.append('textPath')// 設置文字內容
         .attr('xlink:href', (d, i) => { return i && '#edgepath' + i; }) // 文字布置在對應id的連線上
         .style('pointer-events', 'none')
         .text((d) => { return d && d.tag; });
        

        10.鼠標移到節點上有氣泡提示

        nodesCircle.append('title')
         .text((node) => { // .text設置氣泡提示內容
         return node.definition;
         });

        11.監聽圖元素的位置變化

        simulation.on('tick', () => {
         // 更新節點坐標
         nodesCircle.attr('transform', (d) => {
         return d && 'translate(' + d.x + ',' + d.y + ')';
         });
         // 更新節點文字坐標
         nodesTexts.attr('transform', (d) => {
         return 'translate(' + (d.x) + ',' + d.y + ')';
         });
         // 更新連線位置
         edgesLine.attr('d', (d) => {
         const path = 'M ' + d.source.x + ' ' + d.source.y + ' L ' + d.target.x + ' ' + d.target.y;
         return path;
         });
         // 更新連線文字位置
         edgesText.attr('transform', (d, i) => {
         return 'rotate(0)';
         });
        });
        

        12.拖拽

        function onDragStart(d) {
         // console.log('start');
         // console.log(d3.event.active);
         if (!d3.event.active) {
         simulation.alphaTarget(1) // 設置衰減系數,對節點位置移動過程的模擬,數值越高移動越快,數值范圍[0,1]
         .restart(); // 拖拽節點后,重新啟動模擬
         }
         d.fx = d.x; // d.x是當前位置,d.fx是靜止時位置
         d.fy = d.y;
        }
        function dragging(d) {
         d.fx = d3.event.x;
         d.fy = d3.event.y;
        }
        function onDragEnd(d) {
         if (!d3.event.active) simulation.alphaTarget(0);
         d.fx = null; // 解除dragged中固定的坐標
         d.fy = null;
        }
        const drag = d3.drag()
         .on('start', onDragStart)
         .on('drag', dragging) // 拖拽過程
         .on('end', onDragEnd);
        

        13.縮放

        function onZoomStart(d) {
         // console.log('start zoom');
        }
        function zooming(d) {
         // 縮放和拖拽整個g
         // console.log('zoom ing', d3.event.transform, d3.zoomTransform(this));
         g.attr('transform', d3.event.transform); // 獲取g的縮放系數和平移的坐標值。
        }
        function onZoomEnd() {
         // console.log('zoom end');
        }
        const zoom = d3.zoom()
         // .translateExtent([[0, 0], [WIDTH, HEIGHT]]) // 設置或獲取平移區間, 默認為[[-∞, -∞], [+∞, +∞]]
         .scaleExtent([1 / 10, 10]) // 設置最大縮放比例
         .on('start', onZoomStart)
         .on('zoom', zooming)
         .on('end', onZoomEnd);
        

        三、其它效果

        1.單擊節點時讓連接線加粗

        nodesCircle.on('click, (node) => {
         edges_line.style("stroke-width",function(line){
         if(line.source.name==node.name || line.target.name==node.name){
         return 4;
         }else{
         return 0.5;
         }
         });
        })
        

        2.被點擊的節點變色

        nodesCircle.on('click, (node) => {
         nodesCircle.style('fill', (nodeOfSelected) => { // nodeOfSelected:所有節點, node: 選中的節點
         if (nodeOfSelected.id === node.id) { // 被點擊的節點變色
         console.log('node')
         return '#36F';
         } else {
         return '#9FF';
         }
         });
        })
        

        四、在react中使用注意事項

        componentDidMount() {
         this.print();
        }
        print() {
         let callback = (res) => { // callback獲取后臺返回的數據,并存入state
         let nodeData = res.data.nodes;
         let relationData = res.data.rels;
         this.setState({
         nodeData: res.data.nodes,
         relationData: res.data.rels,
         });
         let nodes = [];
         for (let i = 0; i < nodeData.length; i++) {
         nodes.push({
         id: (nodeData[i] && nodeData[i].id) || '',
         name: (nodeData[i] && nodeData[i].name) || '',
         type: (nodeData[i] && nodeData[i].type) || '',
         definition: (nodeData[i] && nodeData[i].definition) || '',
         });
         }
         let edges = [];
         for (let i = 0; i < relationData.length; i++) {
         edges.push({
         id: (relationData[i] && (relationData[i].id)) || '',
         source: (relationData[i] && relationData[i].start.id) || '',
         target: (relationData[i] && relationData[i].end.id) || '',
         tag: (relationData[i] && relationData[i].name) || '',
         });
         }
         this.forceChart(nodes, edges); // d3力導向圖內容
         };
         this.props.dispatch(getDataFromNeo4J({
         neo4jrun: 'match p=(()-[r]-()) return p limit 300',
         }, callback));
        }
        
        

        在哪里構造圖 因為圖是動態的,如果渲染多次(render執行多次,渲染多次),不會覆蓋前面渲染的圖,反而會造成渲染多次,出現多個圖的現象。把構造圖的函數print()放到componentDidMount()內執行,則只會渲染一次。
        對節點和連線數據進行增刪改操作后,需要再次調用print()函數,重新構造圖。

        從哪里獲取數據 數據不從redux獲取,發送請求后callback直接獲取。

        五、干貨:d3項目查找網址

        D3js所有項目檢索.http://blockbuilder.org/search/

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        詳解如何在react中搭建d3力導向圖

        詳解如何在react中搭建d3力導向圖:D3js力導向圖搭建 d3js是一個可以基于數據來操作文檔的JavaScript庫。可以使用HTML,CSS,SVG以及Canvas來展示數據。力導向圖能夠用來表示節點間多對多的關系。 實現效果:連線有箭頭,點擊節點能改變該節點顏色和所連接的線的粗細,縮放、拖拽。 版本:4
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲毛片免费观看| 久久伊人亚洲AV无码网站| 亚洲一区精品中文字幕| 亚洲国产成人精品女人久久久 | 国产亚洲精品AA片在线观看不加载 | 国产免费黄色无码视频| 一级特黄aa毛片免费观看| 毛色毛片免费观看| 亚洲一级免费毛片| 一级成人a做片免费| 亚洲日韩在线观看免费视频| 一区二区三区免费电影| 亚洲色成人WWW永久网站| 亚洲国产成人久久精品大牛影视| 免费黄网站在线看| 亚洲好看的理论片电影| 免费国产黄网站在线看| 亚洲欧洲久久av| 亚洲风情亚Aⅴ在线发布| 亚洲hairy多毛pics大全| 亚洲精品免费视频| 亚洲中文字幕乱码AV波多JI| 久久久久久久久无码精品亚洲日韩| 美女网站在线观看视频免费的 | 国产一精品一aⅴ一免费| 亚洲精品视频在线观看视频| 久草视频在线免费| 亚洲AV无码一区二区三区网址| 亚洲成av人在片观看| 免费毛片在线看不用播放器| 亚洲国产夜色在线观看| 四虎永久免费观看| 免费一区二区三区| 亚洲国产精品无码第一区二区三区| 亚洲精品国产高清不卡在线 | 妞干网手机免费视频| 亚洲第一页在线播放| 精品久久洲久久久久护士免费 | 亚洲校园春色另类激情| 日韩精品成人亚洲专区| 极品色天使在线婷婷天堂亚洲|