diff --git a/README.md b/README.md index e88d0d2..b0227ee 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ export default App; | `strokeWidth` | `number` | A size in `px` | `strokeDasharray` | `string` | Adds dashes to the stroke. It has to be a string representing an array of sizes. See some [SVG strokes documentation](https://www.w3schools.com/graphics/svg_stroking.asp). | `noCurves` | `boolean` | Set this to true if you want angles instead of curves +| `shortestPath` | `boolean` | Set this to true if you want the shortest straight line between anchors | `offset` | `number` | Optional number for space between element and start/end of stroke | `svgContainerStyle` | `Style` | Style of the SVG container element. Useful if you want to add a z-index to your SVG container to draw the arrows under your elements, for example. | `children` | `React.Node` | @@ -131,6 +132,7 @@ The `ArcherStyle` type has the following shape: strokeWidth: number, strokeDasharray: number, noCurves: boolean, + shortestPath: boolean, endShape: Object } ``` diff --git a/src/ArcherContainer.js b/src/ArcherContainer.js index 302c194..b7782ad 100644 --- a/src/ArcherContainer.js +++ b/src/ArcherContainer.js @@ -21,6 +21,7 @@ type Props = { strokeWidth: number, strokeDasharray?: string, noCurves?: boolean, + shortestPath?: boolean, children: React$Node | FunctionChild, style?: Object, svgContainerStyle?: Object, @@ -284,6 +285,8 @@ export class ArcherContainer extends React.Component { const noCurves = style.noCurves || this.props.noCurves; + const shortestPath = style.shortestPath || this.props.shortestPath; + const offset = this.props.offset || 0; const startingAnchorOrientation = source.anchor; @@ -313,6 +316,7 @@ export class ArcherContainer extends React.Component { arrowLabel={label} arrowMarkerId={this._getMarkerId(source, target)} noCurves={!!noCurves} + shortestPath={!!shortestPath} offset={offset} endShape={endShape} /> diff --git a/src/SvgArrow.js b/src/SvgArrow.js index 2d1a965..6dbafcd 100644 --- a/src/SvgArrow.js +++ b/src/SvgArrow.js @@ -14,6 +14,7 @@ type Props = { arrowLabel?: ?React$Node, arrowMarkerId: string, noCurves: boolean, + shortestPath: boolean, offset?: number, endShape: Object, }; @@ -126,7 +127,9 @@ function computePathString({ xEnd, yEnd, noCurves, + shortestPath, offset, + endingAnchorOrientation, }: {| xStart: number, yStart: number, @@ -137,7 +140,9 @@ function computePathString({ xEnd: number, yEnd: number, noCurves: boolean, + shortestPath: boolean, offset?: number, + endingAnchorOrientation?: AnchorPositionType, |}): string { const curveMarker = noCurves ? '' : 'C'; @@ -154,9 +159,25 @@ function computePathString({ yEnd = yEnd - yOffset; } + function computeArrowDirection(endingAnchorOrientation) { + switch (endingAnchorOrientation) { + case 'left': + return `${xEnd - 1},${yEnd} `; + case 'right': + return `${xEnd + 1},${yEnd} `; + case 'top': + return `${xEnd},${yEnd - 1} `; + case 'bottom': + return `${xEnd},${yEnd + 1} `; + default: + return ''; + } + } + + const convertArrowDirectionParams = computeArrowDirection(endingAnchorOrientation) return ( `M${xStart},${yStart} ` + - `${curveMarker}${xAnchor1},${yAnchor1} ${xAnchor2},${yAnchor2} ` + + (shortestPath ? convertArrowDirectionParams : `${curveMarker}${xAnchor1},${yAnchor1} ${xAnchor2},${yAnchor2} `) + `${xEnd},${yEnd}` ); } @@ -171,6 +192,7 @@ const SvgArrow = ({ arrowLabel, arrowMarkerId, noCurves, + shortestPath, offset, endShape, }: Props) => { @@ -218,7 +240,9 @@ const SvgArrow = ({ xEnd, yEnd, noCurves, + shortestPath, offset, + endingAnchorOrientation, }); const { xLabel, yLabel, labelWidth, labelHeight } = computeLabelDimensions(