Home > Blockchain >  How to avoid unwanted circle on SVG path element
How to avoid unwanted circle on SVG path element

Time:06-12

I'm putting together a Sankey diagram via SVG but suddenly under some unknown conditions one of the paths show a circle where there shouldn't be any.

I tried to remove as much as possible from the my SVG but removing anything further makes this no longer reproducible.

Here you can see my reduced SVG image. The black path element is the one having the issue. I manually marked where the path stroke element should end but somehow it shows a circle which seems to have the same radius as the stroke width.

example image showing the issue

<div style="width: 100%; height: 100%;">
  <svg width=100% height=500px>
    <g >
      <g >
        <path d="M107.61971830985915,30C107.61971830985915,74,107.61971830985915,74,107.61971830985915,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>
        <path d="M251.11267605633802,30C251.11267605633802,192,328.943661971831,192,328.943661971831,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="71.74647887323944"></path>
        <path d="M478.38028169014075,30C478.38028169014075,192,384.7464788732394,192,384.7464788732394,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
        <path d="M542.1549295774647,30C542.1549295774647,192,572.1549295774648,192,572.1549295774648,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="87.69014084507042"></path>
        <path d="M344.8169014084507,30C344.8169014084507,192,452.50704225352115,192,452.50704225352115,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="95.66197183098592"></path>
        <path d="M143.49295774647888,148C143.49295774647888,251,153.49295774647888,251,153.49295774647888,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="79.71830985915493"></path>
        <path d="M409.12773522289996,148C409.12773522289996,251,213.28169014084506,251,213.28169014084506,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
      </g>
    </g>
  </svg>
</div>

Any clue where this comes from and what I can do to avoid it?

Clarification:

The paths are computed by d3. It's not a manually created graphic and I'm looking for a general solution to the problem, not a solution for this particular example.

CodePudding user response:

I changed the first path to <path d="M107.62,30L107.62,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>. I worked this out by loading it in to Illustrator.

I'm not 100% sure what the issue was, but maybe someone smarter than me will figure it out. The maths of SVGs hurts my brain.

<div style="width: 100%; height: 100%;">
  <svg width=100% height=500px>
    <g >
      <g >
        <path d="M107.62,30L107.62,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>
        <path d="M251.11267605633802,30C251.11267605633802,192,328.943661971831,192,328.943661971831,354"  fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="71.74647887323944"></path>
        <path d="M478.38028169014075,30C478.38028169014075,192,384.7464788732394,192,384.7464788732394,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
        <path d="M542.1549295774647,30C542.1549295774647,192,572.1549295774648,192,572.1549295774648,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="87.69014084507042"></path>
        <path d="M344.8169014084507,30C344.8169014084507,192,452.50704225352115,192,452.50704225352115,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="95.66197183098592"></path>
        <path d="M143.49295774647888,148C143.49295774647888,251,153.49295774647888,251,153.49295774647888,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="79.71830985915493"></path>
        <path d="M409.12773522289996,148C409.12773522289996,251,213.28169014084506,251,213.28169014084506,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
      </g>
    </g>
  </svg>
</div>

CodePudding user response:

Apperently a browser related bug you should report.

As a "post-processing" workaround you could use this helper I've once created to convert flat curves to L commands. (based on path data polyfill by Jarek Foksa)

Fixed the issue in edge.

let paths = document.querySelectorAll('path');
convertStraightCurves(paths)

function convertStraightCurves(paths){
  paths.forEach(function(path){
      let pathData = path.getPathData({normalize:true}); 
      pathData.forEach(function(com, c){
          let [type, values] = [ com['type'], com['values'] ];

          //check straight vertical curves
          if(type=='C'){
            let [x1,x2,x3] = [values[0], values[2], values[4]]
            let [y1,y2,y3] = [values[1], values[3], values[5]]
            
              // check if curve is straight
              let angle1 =  getAngle(x2,y2, x3, y3);
              let angle2 =  getAngle(x1,y1, x3, y3);

              if(angle1===angle2 ){
                  pathData[c]['type']='L';
                  pathData[c]['values']= [x3, y3];
            }
          }
      })
      path.setPathData(pathData);
    })
}


 function getAngle(x1, y1, x2, y2){
     let angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
     return Math.floor(angle);   
 }
<script src="https://cdn.jsdelivr.net/npm/[email protected]/path-data-polyfill.min.js"></script>
<div style="width: 100%; height: 100%;">
  <svg width=100% height=500px>
    <g >
      <g >
        <path d="M107.62,30L107.62,118" fill="none" stroke="#000000" stroke-opacity="1" stroke-width="200"></path>
        <path d="M251.11267605633802,30C251.11267605633802,192,328.943661971831,192,328.943661971831,354"  fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="71.74647887323944"></path>
        <path d="M478.38028169014075,30C478.38028169014075,192,384.7464788732394,192,384.7464788732394,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
        <path d="M542.1549295774647,30C542.1549295774647,192,572.1549295774648,192,572.1549295774648,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="87.69014084507042"></path>
        <path d="M344.8169014084507,30C344.8169014084507,192,452.50704225352115,192,452.50704225352115,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="95.66197183098592"></path>
        <path d="M143.49295774647888,148C143.49295774647888,251,153.49295774647888,251,153.49295774647888,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="79.71830985915493"></path>
        <path d="M409.12773522289996,148C409.12773522289996,251,213.28169014084506,251,213.28169014084506,354" fill="none" stroke="#00bbff35" stroke-opacity="0.5" stroke-width="39.859154929577464"></path>
      </g>
    </g>
  </svg>
</div>

Also working curveto commands

d="M107.6 30 C 107.6 74 107.6 118 107.6 118"
[x2,y2] = [x3,y3]

d="M107.6 30 C 107.6 118 107.6 118 107.6 118"
[x1,y1] = [x2,y2] = [x3,y3]

  • Related