0

I want to fill the gap in the round-arrow line, and the round-arrow line with opacity less than 1. I achieved this in the following code snippet, but I noticed it causes an overlap problem. I'd like to remove the semi-circle overlap area. To do this, I attempted to blend the gap line with the round-arrow line.
However, I encountered an issue where the opacity of the round-arrow line affected the gap line. I simply want to eliminate the semi-circle and ensure that the opacity of the gap line is not influenced by the round-arrow line.
Is there a way to accomplish this goal? (Maybe the worst way is to mask the semi-circle...) Here is my codepen demo: https://codepen.io/cactusxx/pen/gOqaQxQ

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <polyline id="p1" points="50,50 250,50" fill="none" stroke-width="10" stroke-linecap="round" />
    <mask id="m1" maskUnits="userSpaceOnUse">
      <use href="#p1" stroke="white" />
      <use href="#p1" stroke="black" stroke-dasharray="40 30" />
    </mask>
  </defs>

  <!--   blue gap line-->
  <use href="#p1" stroke="blue" mask="url(#m1)" />
  <!--   line with arrow -->
  <g opacity="0.5">
    <use href="#p1" stroke="rgb(255,0,0)" stroke-dasharray="40 30" />
    <!--     arrow -->
    <polygon id="arrowPoly" points="250,35 280,50 250,65" fill="rgb(255,0,0)" stroke="rgb(255,0,0)" stroke-width="5" stroke-linejoin="round" />
  </g>

</svg>

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <!--  Blend the blue line into the SourceGraphic. -->
    <polyline id="pp" points="50,50 250,50" fill="none" stroke-width="10" stroke="blue" stroke-linecap="round" />
    <filter id="blend" filterUnits="userSpaceOnUse">
      <feImage x="0" y="0" xlink:href="#pp" result="backline" />
      <feBlend in="SourceGraphic" in2="backline" mode="normal" />
    </filter>
  </defs>

  <g opacity="0.5" filter="url(#blend)">
    <use href="#p1" stroke="rgb(255,0,0)" stroke-dasharray="40 30" />
    <!--     arrow -->
    <polygon id="arrowPoly" points="250,35 280,50 250,65" fill="rgb(255,0,0)" stroke="rgb(255,0,0)" stroke-width="5" stroke-linejoin="round"/>
  </g>

</svg>

4
  • 1
    you can put the <polygon id="arrowPoly" inside the mask and <use> the arrowPoly at the end of your code. Also I would like to tell you that you may use a <marker> for the arrow.
    – enxaneta
    Commented Oct 27, 2023 at 9:14
  • Note that to do what @enxaneta said you'll need to set your fill differently, so that you can set it to black in the mask. The easiest might be to move the fill declaration on a parent <g>, so that the one on the <use> wins.
    – Kaiido
    Commented Oct 27, 2023 at 9:23
  • 1
    @enxaneta Thank you for your reply! I know how to use to attach an arrow to the end of the line. I think my problem is that there will be an overlap when the arrow has an opacity less than 1. Please forgive me, I don’t know how to eliminate this area using your method.
    – personax
    Commented Oct 27, 2023 at 10:26
  • @Kaiido Thank you very much for replying. I’m having some difficulty understanding how to implement your advice for my purpose. If you have the time, could you please provide a code example? I would greatly appreciate it.
    – personax
    Commented Oct 27, 2023 at 10:34

2 Answers 2

1

As I've commented you can put the <polygon id="arrowPoly" inside the mask and <use> the arrowPoly at the end of your code.

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <polyline id="p1" points="50,50 250,50" fill="none" stroke-width="10" stroke-linecap="round" />
    <mask id="m1" maskUnits="userSpaceOnUse">
      <use href="#p1" stroke="white" />
      <use href="#p1" stroke="black" stroke-dasharray="40 30" />
      <polygon id="arrowPoly" points="250,35 280,50 250,65"   /> 
    </mask>
  </defs>

  <!--   blue gap line-->
  <use href="#p1" stroke="blue" mask="url(#m1)" />
  <!--  line with arrow -->
 <g opacity=".5" >
    <use href="#p1" stroke="rgb(255,0,0)" stroke-dasharray="40 30" />
    <!--  arrow -->
   <use href="#arrowPoly" fill="rgb(255,0,0)"/>
  </g>

</svg>

6
  • Thank you very much for providing this example! I didn't understand before why placing the <Polygon id=arrowpoly inside a <mask> and then using <use> to use the polygon achieves the effect of the arrow covering the blue line (even though the arrow has transparency). After looking at your code, I still don't understand the principle behind doing it this way. If you could briefly explain, I would greatly appreciate it!
    – personax
    Commented Oct 27, 2023 at 12:35
  • 1
    when you are using the arrowpoly inside the mask it's filled black by default. You are filling it red only when used with <use>
    – enxaneta
    Commented Oct 27, 2023 at 12:45
  • Thanks for the explanation! I found that if I set a round corner for the arrow by adding <use href="#arrowPoly" fill="rgb(255,0,0)" stroke-width="5" stroke-linejoin="round" stroke="rgb(255,0,0)">, then an overlap area will appear. You can see the effect on this link: [codepen.io/cactusxx/pen/MWLKpWb]. If you could give me some advice on how to revise it, I would appreciate it!
    – personax
    Commented Oct 28, 2023 at 6:13
  • The example you have in codepen (broken link above) uses a filter and no mask. This would be a different question.
    – enxaneta
    Commented Oct 28, 2023 at 6:58
  • Sorry, this is the link: codepen.io/cactusxx/pen/MWLKpWb. I didn't describe my question clearly. My arrow is a round arrow, so I need to set the stroke.
    – personax
    Commented Oct 28, 2023 at 7:03
1

Finally, I resolved the issue of overlap by eliminating the overlapping area from the gap-fill line (Update: I've made the entire arrow in the gap-fill line invisible, so I don't need to calculate the points; I can simply use the same points as the arrow.). While this might not be the optimal solution, it currently fulfills my objective. If you have any alternative or better solutions, I would greatly appreciate your input!

Here is my solution: https://codepen.io/cactusxx/pen/MWLKmyB

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <polyline id="p1" points="50,50 250,50" fill="none" stroke-width="10" stroke-linecap="round" />
    <mask id="m1" maskUnits="userSpaceOnUse">
      <use href="#p1" stroke="white" />
      <use href="#p1" stroke="black" stroke-dasharray="40 30" />
      <polygon points="250,35 280,50 250,65" stroke-width="5" stroke-linejoin="round" stroke="black" />
    </mask>
  </defs>

  <!--   blue gap -->
  <use href="#p1" stroke="rgb(0,0,0,0.8)" mask="url(#m1)" />
  <!--   line with arrow -->
  <g opacity="0.5">
    <use href="#p1" stroke="rgb(255,0,0)" stroke-dasharray="40 30" />
    <!--  round arrow -->
    <polygon id="arrowPoly" points="250,35 280,50 250,65" stroke-width="5" stroke-linejoin="round" stroke="rgb(255,0,0)" fill="rgb(255,0,0)" />
  </g>

</svg>

Not the answer you're looking for? Browse other questions tagged or ask your own question.