Home > database >  my SVG (donnut chart) doesn't display correctly on IOS
my SVG (donnut chart) doesn't display correctly on IOS

Time:06-10

Context : I want to display a donut chart using one SVG composed of two circles :

Final result

  • Both circles are dynamically filled with a css variable (as a percent).

Everythings works fine on PC and Android (chrome).

When viewing with an iPhone, the green circle is fully filled hiding the grey circle.

Below is the result as seen with IOS phone (tried Safari and Chrome) :

enter image description here

Here is a snippet, took 45% for green and 75% for grey

Code :

:root {
  --val: 0;
}

svg {
  transform: rotate(135deg);
}

.percent {
  stroke-dasharray: 100;
  stroke-dashoffset: calc(100 - var(--val));
}

.white {
  transform: rotate(135deg)
}

.forty-five{
  --val: 45;
}

.complete {
   --val: 75;
 }
<div >
  <svg width="250" height="250" viewBox="0 0 140 140">
  <circle  cx="70" cy="70" r="52" fill="none" stroke="#e6e6e6" strokeWidth="18" pathLength="100" />
  <circle  cx="70" cy="70" r="52" fill="none" stroke="#333" strokeWidth="18" pathLength="100" />
  <circle  cx="70" cy="70" r="52" fill="none" stroke="#6AA617" strokeWidth="18" pathLength="100" />
  </svg>
</div>

Any suggestion or any other way to obtain this result ?

EDIT : I just found out that there is the same problem when using Firefox on pC

CodePudding user response:

As @A Haworth already pointed out:
css calc support for svg properties is still rather spotty (might work in Chrome but not in Firefox – might also depend on the actual svg element and certain properties.
Probably fixed and negligible in the near future ... unless ie returns).

But you don't really need it anyway.

Since your horseshoe gauge should render only 270° of a 360° circle, you could instead tweak the pathLength property:

The ideal pathLength would be 133.333
360/270*100
(i.e. the 270° part of the circle will result in a computed circumference of 100 svg units)

Now you can use css-variable to display percentage based values:

:root {
  --val: 100;
  --dashGap: 133.333;
  --offset: 0;
}

svg {
  transform: rotate(135deg);
}

.percent {
  stroke-dashoffset: var(--offset);
  stroke-dasharray: var(--val) var(--dashGap)
}
<div >
  <svg width="250" height="250" viewBox="0 0 140 140">
    <defs>
          <circle id="circle" cx="70" cy="70" r="52" fill="none" pathLength="133.333" stroke-width="18" />
    </defs>
   <!-- bg circle -->
    <use  href="#circle" stroke="#e6e6e6" />
   <!-- percentage circles -->
    <use  href="#circle" stroke="green" style="--val:50"/>
    <use  href="#circle" stroke="pink" style="--val:25; --offset:-50" />
  </svg>
</div>

If you need to render values progressively like 50% 25% (so a total of 75%) you can use a stroke-dahoffset variable.
Each new segment needs to have a negative offset according the previous segments's percentage.

  • Related