国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答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庫??梢允褂肏TML,CSS,SVG以及Canvas來展示數據。力導向圖能夠用來表示節點間多對多的關系。 實現效果:連線有箭頭,點擊節點能改變該節點顏色和所連接的線的粗細,縮放、拖拽。 版本:4
推薦度:
導讀詳解如何在react中搭建d3力導向圖:D3js力導向圖搭建 d3js是一個可以基于數據來操作文檔的JavaScript庫。可以使用HTML,CSS,SVG以及Canvas來展示數據。力導向圖能夠用來表示節點間多對多的關系。 實現效果:連線有箭頭,點擊節點能改變該節點顏色和所連接的線的粗細,縮放、拖拽。 版本:4

D3js力導向圖搭建

d3js是一個可以基于數據來操作文檔的JavaScript庫??梢允褂肏TML,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
主站蜘蛛池模板: 成人免费久久精品国产片久久影院 | 欧美日韩另类国产 | 欧美日韩亚洲一区二区三区 | 欧美日韩在线高清 | 91久久精品国产91久久性色也 | 高h肉肉视频在线播放观看 福利视频一区二区三区 | 国产精品久久久久免费 | 亚洲欧美日韩国产综合高清 | 一区二区三区在线观看免费 | 日韩有码电影 | 一区二区三区高清不卡 | 欧美日韩亚洲色图 | 欧美日韩亚洲高清不卡一区二区三区 | 岛国大片在线观看 | 99热成人精品国产免国语的 | 操比网站| 91精品日本久久久久久牛牛 | 中文字幕第4页 | 欧美在线中文 | 成人欧美一区二区三区视频 | 亚洲欧美精品伊人久久 | 国产欧美日韩在线 | 久久99国产精一区二区三区 | 国产在线视频一区二区三区 | 91情侣在线偷精品国产 | 亚洲国产成人精品女人久久久 | 正在播放国产一区 | 婷婷在线免费视频 | 国产高清在线精品一区二区三区 | www.国产精品 | 九九精品视频一区在线 | 欧美色图一区二区 | 午夜日韩精品 | 亚洲欧洲日产国码一级毛片 | 91精品啪国产在线观看免费牛牛 | 午夜视频免费在线观看 | 亚洲欧美另类日韩 | 免费永久在线观看黄网 | 国内精品伊人久久久久妇 | 亚洲欧美日韩中文v在线 | 中文字幕日韩一区二区三区不卡 |