react-d3-tree
Version:
React component to create interactive D3 tree hierarchies
104 lines (103 loc) • 4.17 kB
JavaScript
import React from 'react';
import { linkHorizontal, linkVertical } from 'd3-shape';
import { select } from 'd3-selection';
export default class Link extends React.PureComponent {
constructor() {
super(...arguments);
this.linkRef = null;
this.state = {
initialStyle: {
opacity: 0,
},
};
this.handleOnClick = evt => {
this.props.onClick(this.props.linkData.source, this.props.linkData.target, evt);
};
this.handleOnMouseOver = evt => {
this.props.onMouseOver(this.props.linkData.source, this.props.linkData.target, evt);
};
this.handleOnMouseOut = evt => {
this.props.onMouseOut(this.props.linkData.source, this.props.linkData.target, evt);
};
}
componentDidMount() {
this.applyOpacity(1, this.props.transitionDuration);
}
componentWillLeave(done) {
this.applyOpacity(0, this.props.transitionDuration, done);
}
applyOpacity(opacity, transitionDuration, done = () => { }) {
if (this.props.enableLegacyTransitions) {
select(this.linkRef)
// @ts-ignore
.transition()
.duration(transitionDuration)
.style('opacity', opacity)
.on('end', done);
}
else {
select(this.linkRef).style('opacity', opacity);
done();
}
}
drawStepPath(linkData, orientation) {
const { source, target } = linkData;
const deltaY = target.y - source.y;
return orientation === 'horizontal'
? `M${source.y},${source.x} H${source.y + deltaY / 2} V${target.x} H${target.y}`
: `M${source.x},${source.y} V${source.y + deltaY / 2} H${target.x} V${target.y}`;
}
drawDiagonalPath(linkData, orientation) {
const { source, target } = linkData;
return orientation === 'horizontal'
? linkHorizontal()({
source: [source.y, source.x],
target: [target.y, target.x],
})
: linkVertical()({
source: [source.x, source.y],
target: [target.x, target.y],
});
}
drawStraightPath(linkData, orientation) {
const { source, target } = linkData;
return orientation === 'horizontal'
? `M${source.y},${source.x}L${target.y},${target.x}`
: `M${source.x},${source.y}L${target.x},${target.y}`;
}
drawElbowPath(linkData, orientation) {
return orientation === 'horizontal'
? `M${linkData.source.y},${linkData.source.x}V${linkData.target.x}H${linkData.target.y}`
: `M${linkData.source.x},${linkData.source.y}V${linkData.target.y}H${linkData.target.x}`;
}
drawPath() {
const { linkData, orientation, pathFunc } = this.props;
if (typeof pathFunc === 'function') {
return pathFunc(linkData, orientation);
}
if (pathFunc === 'elbow') {
return this.drawElbowPath(linkData, orientation);
}
if (pathFunc === 'straight') {
return this.drawStraightPath(linkData, orientation);
}
if (pathFunc === 'step') {
return this.drawStepPath(linkData, orientation);
}
return this.drawDiagonalPath(linkData, orientation);
}
getClassNames() {
const { linkData, orientation, pathClassFunc } = this.props;
const classNames = ['rd3t-link'];
if (typeof pathClassFunc === 'function') {
classNames.push(pathClassFunc(linkData, orientation));
}
return classNames.join(' ').trim();
}
render() {
const { linkData } = this.props;
return (React.createElement("path", { ref: l => {
this.linkRef = l;
}, style: Object.assign({}, this.state.initialStyle), className: this.getClassNames(), d: this.drawPath(), onClick: this.handleOnClick, onMouseOver: this.handleOnMouseOver, onMouseOut: this.handleOnMouseOut, "data-source-id": linkData.source.id, "data-target-id": linkData.target.id }));
}
}