内容简介: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使用蓝图规划大型项目
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入理解程序设计
[美] Jonathan Bartlett / 郭晴霞 / 人民邮电出版社 / 2014-1 / 49.00
是否真正理解汇编语言,常常是普通程序员和优秀程序员的分水岭。《深入理解程序设计:使用Linux汇编语言》介绍了Linux平台下的汇编语言编程,教你从计算机的角度看问题,从而了解汇编语言及计算机的工作方式,为成就自己的优秀程序员之梦夯实基础。 很多人都认为汇编语言晦涩难懂,但New Medio技术总监Jonathan Bartlett的这本书将改变人们的看法。本书首先介绍计算机的体系结构,然后......一起来看看 《深入理解程序设计》 这本书的介绍吧!