How can I make the markers overlap perfectly so it doesn't appear twice for the same end?

Viewed 179

I am trying to implement a highlight feature that makes the arrow bigger and changes its color. but the problem is when the width change, one of the two end markers (arrowhead) becomes bigger, but also doesn't overlap on the smaller one. how can I make it overlap so they appear as one bigger arrowhead instead of two

without highlight

without highlight

with highlight

with highlight

my code

    render() {
    const [start, target] = this.props.points;
    const activeColor = !this.state.isActive ? "#6b6b6b" : "#ffa500";
    const arrowWidth = !this.state.isActive ? "1" : "2";

    return (
        <g>
            {
                this.props.IsNotDot &&
                <line
                    x1={start.x}
                    y1={start.y}
                    x2={target.x}
                    y2={target.y}
                    stroke={activeColor}
                    strokeWidth={arrowWidth}
                    strokeOpacity="0.7"
                    markerEnd="url(#arrowhead)"/>
            }
        </g>
    );
}
1 Answers

Why not just create two separate marker definitions and show the correct one? You can swap the ID of the marker with a variable like you're doing for stroke color or by using CSS.

Note: I had to multiply the markerWidth, markerHeight, refX, and refY by the scale to get this to work. I think the reason for this is how SVG handles scaling strokes.

<svg>
    <defs>
        <marker id="arrowA" 
        markerWidth="10" 
        markerHeight="10" 
        refX="0" refY="3" 
        orient="auto"
        markerUnits="strokeWidth">
            <path fill="black" d="M0,0 L0,6 L9,3 z" />   
        </marker>
        <marker id="arrowB" 
        markerWidth="30" 
        markerHeight="30" 
        refX="0" refY="9" 
        orient="auto"
        markerUnits="strokeWidth">
          <path 
          fill="orange" transform='scale(3)' 
          d="M0,0 L0,6 L9,3 z" />
        </marker>
    </defs>
</svg>

<svg id="lineA" width="276px" height="100px">
    <line x1="64" y1="28" x2="200" y2="70" 
    stroke="black" 
    marker-end="url(#arrowA)">
    </line>
</svg>
<svg id="lineB" width="276px" height="100px">
    <line x1="64" y1="28" x2="200" y2="70" 
    stroke="black" 
    marker-end="url(#arrowB)">
    </line>
</svg>

CSS to swap

#lineA {
  cursor:pointer;
}

#lineA line {
  marker-end: url("#arrowA");
}


#lineA:hover line {
  stroke:orange;
  marker-end: url("#arrowB");
}
<svg>
    <defs>
        <marker id="arrowA" 
        markerWidth="10" 
        markerHeight="10" 
        refX="0" refY="3" 
        orient="auto"
        markerUnits="strokeWidth">
            <path fill="black" d="M0,0 L0,6 L9,3 z" />   
        </marker>
        <marker id="arrowB" 
        markerWidth="20" 
        markerHeight="20" 
        refX="0" refY="6" 
        orient="auto"
        markerUnits="strokeWidth">
          <path 
          fill="orange" transform='scale(2)' 
          d="M0,0 L0,6 L9,3 z" />
        </marker>
    </defs>
</svg>

<svg id="lineA" width="276px" height="100px">
    <line x1="64" y1="28" x2="200" y2="70" 
    stroke="black" >
    </line>
</svg>

Hover over the arrow

Related