Search code examples
svgpath

Show several sections (specified by percentages) of an SVG path


I have several SVG path elements, which I want to be displayed only partially as several sections. For this, I have percentages for the parts of the paths that should be visible. E.g., the two pairs (0.3,0.5), (0.75,1.0) indicates that a path should be visible from 30% to 50% and from 75% to 100% of its length. How do I implement this in an SVG?

I have tried linearGradients, which do not work precisely for curved paths. I also thought that this problem is trivial by using stroke-dasharray, but this does not work correctly with percentages (at least what I have tried). Unfortunately, I also cannot invoke JavaScript in my environment, as the SVG attributes can only be directly accessed.

Does anyone have an idea or can enlighten me?


Solution

  • You had the right idea with stroke-dasharray. Why percentages do not really work, see this explanation. The solution consists of two steps:

    1. For the path (or the grafic primitive), define an attribute (not a CSS property, and unitless) pathLength="100". 100 is an arbitrary number here, but fits nicely with the use of percentages. The effect is that for all calculations that depend on a path length, the attribute value is used instead of the real length so that a dash length of 1 simply means 1/100 of the total path length.

    2. Divide the total path length you defined in groups of dash lengths and gap lengths. Set the resulting list as the value of stroke-dasharray, and take care that the sum of all numbers in that list equals the defined pathLength. Note that the first number must be a dash. If you want to start with a gap, move the length of the gap to the end, and set stroke-dashoffset to the negative length of the initial gap. (You could use px units here, but they are not needed.)

    path {
      fill: none;
      stroke: black;
      stroke-width: 9;
    }
    #dash-first {
      stroke-dasharray: 30 20 25 25;
    }
    #gap-first {
      stroke-dasharray: 20 25 25 30;
      stroke-dashoffset: -30;
    }
    <svg viewBox="0 0 100 20">
      <path id="dash-first" d="M10,5 90,5" pathLength="100" />
      <path id="gap-first" d="M10,15 90,15" pathLength="100" />
    </svg>


    I recently used that idea to compute breaks in a long "wall", see this CodePen. In the Javascript section you will find a a method Wall.sectorsToDashes() that converts a list of Boolean values into a dasharray, where true means the stroke is shown as a dash, and false as a gap. The pathLength value is the length of the list, and each entry corresponds to a unit length of 1.