内容简介:React 已经成为了公司所有项目的前端必选框架了,参考了一下第一步很重要,我们图当然是要绘制在DOM上了
React 已经成为了公司所有项目的前端必选框架了, JavaScript
社区非常活跃,而 React
也几乎成为了前端最火热的框架,所以各种知名的库几乎都已经有了 React
的版本。但是一些库还没有,比如 dagre-d3
。 dagre-d3
是一个来绘制关系图的 Javascript
库。
参考了一下 react-highcharts
,其实在 React
中实现 dagre-d3
其实也还好。
- 获取DOM node
第一步很重要,我们图当然是要绘制在DOM上了
ref
简介
React提供的 ref
属性,表示为对组件真正实例的引用,其实就是ReactDOM.render()返回的组件实例。 有一点要注意一下, ReactDOM.render()
渲染组件时返回的是组件实例;而渲染dom元素时,返回是具体的dom节点。
getDOMRef(ref) { console.log(ref); } getComponentRef(ref) { console.log(ref); } <svg ref={this.getDOMRef} /> <DagreD3 ref={this.getComponentRef} /> 复制代码
这里我们用nodeTree和nodeTreeInner来保存具体的dom节点。
setNodeTree = (nodeTree) => { this.nodeTree = nodeTree; } setNodeTreeInner = (nodeTreeInner) => { this.nodeTreeInner = nodeTreeInner; } render() { return ( <svg ref={this.setNodeTree}> <g ref={this.setNodeTreeInner} /> </svg> ) } 复制代码
- 渲染到DOM上(开始画图)
由于要获取真正的 DOM
节点,所以需要将上面代码的执行放到 componentDidMount
我们定义一个 renderDag
方法,放到 componentDidMount
和 componentDidUpdate
里面
renderDag() { const { nodes, edges } = this.props; const g = new dagreD3.graphlib.Graph() .setGraph({}) // Set an object for the graph label .setDefaultNodeLabel(() => ({})) .setDefaultEdgeLabel(() => ({})); // Default to assigning a new object as a label for each new edge. Object.keys(nodes).forEach((id) => { // 画点 g.setNode(id, nodes[id]); }); edges.forEach((edge) => { // 画线 edge[2] ? g.setEdge(edge[0], edge[1], edge[2]) : g.setEdge(edge[0], edge[1]); }); // 渲染dag图 const svg = d3.select(this.nodeTree); const inner = d3.select(this.nodeTreeInner); // 鼠标滚动缩放 const zoom = d3.zoom().on('zoom', () => inner.attr('transform', d3.event.transform)); svg.call(zoom); const render = new dagreD3.render(); // eslint-disable-line render(inner, g); } 复制代码
- 效果图
- 完整代码
import React from 'react'; import PropTypes from 'prop-types'; import * as dagreD3 from 'dagre-d3'; import * as d3 from 'd3'; class DagreD3 extends React.Component { static defaultProps = { width: '100%', height: '100%', nodes: {}, edges: [], graph: {}, interactive: false, onNodeClick: () => {} } static propTypes = { width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]), height: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]), nodes: PropTypes.object, edges: PropTypes.array, graph: PropTypes.object, interactive: PropTypes.bool, onNodeClick: PropTypes.func, onNodeHover: PropTypes.func } componentDidMount() { this.renderDag(); } shouldComponentUpdate(nextProps) { return !(this.props.nodes === nextProps.nodes) || !(this.props.edges === nextProps.edges); } componentDidUpdate() { this.renderDag(); } setNodeTree = (nodeTree) => { this.nodeTree = nodeTree; } setNodeTreeInner = (nodeTreeInner) => { this.nodeTreeInner = nodeTreeInner; } renderDag() { const { nodes, edges, interactive, fit, onNodeClick, graph } = this.props; const g = new dagreD3.graphlib.Graph() .setGraph({ ...graph }) // Set an object for the graph label .setDefaultNodeLabel(() => ({})) .setDefaultEdgeLabel(() => ({})); // Default to assigning a new object as a label for each new edge. Object.keys(nodes).forEach((id) => { g.setNode(id, nodes[id]); }); edges.forEach((edge) => { edge[2] ? g.setEdge(edge[0], edge[1], edge[2]) : g.setEdge(edge[0], edge[1]); }); const svg = d3.select(this.nodeTree); const inner = d3.select(this.nodeTreeInner); if (interactive) { // 自适应缩放 const zoom = d3.zoom().on('zoom', () => inner.attr('transform', d3.event.transform)); svg.call(zoom); } const render = new dagreD3.render(); // eslint-disable-line render(inner, g); // Run the renderer. This is what draws the final graph. render(inner, g); // 自适应宽高 if (fit) { const { height: gHeight, width: gWidth } = g.graph(); const { height, width } = this.nodeTree.getBBox(); const transX = width - gWidth; const transY = height - gHeight; svg.attr('viewBox', `0 0 ${width} ${height}`); inner.attr('transform', d3.zoomIdentity.translate(transX, transY)); } if (onNodeClick) { // 点击事件 svg.selectAll('g.node').on('click', id => onNodeClick(id)); } } render() { const { width, height } = this.props; return ( <svg width={width} height={height} ref={this.setNodeTree}> <g ref={this.setNodeTreeInner} /> </svg> ); } } export { d3 }; export default DagreD3; 复制代码
- 使用
<DagreD3 fit interactive graph={{ rankdir: 'LR' }} nodes={nodes} edges={edges} onNodeClick={this.onNodeClick} /> 复制代码
以上所述就是小编给大家介绍的《React 项目中使用 dagre-d3》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用 MonoRepo 管理前端项目
- 使用 Mkdocs 制作项目文档
- 使用Taro开发项目总结
- 使用 Maven 构建 Java 项目
- 使用gradle构建java项目
- flask使用蓝图规划大型项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。