Is there way to combine two SVGs with opacity and only show one SVG when they overlap?

97 views Asked by At

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>

2

There are 2 answers

6
enxaneta On

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>

0
personax On

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>