0

There are two movable rectangles, between them is an arrow that connects them. It would be necessary if there was a third rectangle in the arrow’s path, it would bypass it without crossing it

I implemented the connection of two moving rectangles with an arrow using konva-react, you need to make the arrow bypass the rectangle when crossing it

import { Stage, Layer, Rect, Group, Arrow } from 'react-konva';

function ColoredRect(props) {
    let position = props.position;
    let index = props.index;
    let handleDrag = (propsValue) => {
        props.setPosition(
            position.map((item, Zindex) => {
                if(index === Zindex) {
                return ([propsValue.currentTarget.attrs.y, 
                propsValue.currentTarget.attrs.x]);
                }else{
                   return item;
                }
            })
        );
    }

    return (<Rect
        x={position[index][1]}
        y={position[index][0]}
        width={100}
        height={100}
        fill = 'green'
        shadowBlur={5}
        draggable
        onDragMove={handleDrag}
        name='fillShape'
    />
    );

}
function ArrowComponent(props) {
    let positionStart = props.positionStart, positionEnd = props.positionEnd;
    return (
        <Arrow
            points={[positionStart[1] + 50, positionStart[0] + 50, positionEnd[1] + 50, positionEnd[0] + 50]}
            pointerLength={10}
            pointerWidth={10}
            fill='black'
            stroke='black'
            strokeWidth={4}
        />
    )
}
function Shape(props) {
    const groupEl = useRef(null);
    const layerEl = useRef(null);
    const arrowGroupEl = useRef(null);
    const stageEl = useRef(null);
    const [positionShape, setPositionShape] = useState([[100, 100], [300, 300], [100, 500]]);
    let handDragMoveLayer = (e) => {
        let target = e.target;
        let targetRect = target.getClientRect();
        groupEl.current.children.forEach(function (group) {
            if (group === target) {
                return;
            }
            if (haveIntersection(group.getClientRect(), arrowGroupEl.current.children[0].getClientRect()) /*targetRect)*/) {
                group.fill('red');
            } else {
                group.fill('green');
            }
        });
    }
    let haveIntersection = (r1, r2) => {
        return !(
            r2.x > r1.x + r1.width ||
            r2.x + r2.width < r1.x ||
            r2.y > r1.y + r1.height ||
            r2.y + r2.height < r1.y
        );
    }
    return (
        <Stage width={window.innerWidth} height={window.innerHeight} ref = {stageEl}>
            <Layer
                ref={layerEl}
                onDragMove={handDragMoveLayer}
            >
                <Group ref={groupEl} >
                    {positionShape.map((item, index) => {
                        return <ColoredRect key={index} position={positionShape} index={index} setPosition={setPositionShape} />
                    })}
                </Group>
                <Group ref = {arrowGroupEl}>
                    <ArrowComponent positionStart={positionShape[0]} positionEnd={positionShape[1]} />
                </Group>
            </Layer>
        </Stage>
    );
}

render(<Shape />, document.getElementById('root'));
R0Ger
  • 1
  • 1
  • What do you mean by "bypass"? Go around the rectangle? Curved or not? Go on top? – lavrton Sep 02 '19 at 16:20
  • find the moment when the arrow touches the rectangle, and moves away from it, in the opposite direction – R0Ger Sep 03 '19 at 21:44
  • Are you talking about 'routing' ? So that the line of the arrow between the two rectangles must not cross a rectangle that falls between them ? – Vanquished Wombat Sep 10 '19 at 16:22

0 Answers0