SVG transform rotate by 90, 180 or 270 degrees not working on circle in Safari iOS 10

后端 未结 3 1955

I want to create a donut chart using an SVG circle element by setting stroke-dasharray and varying stroke-dashoffset. The SVG element needs to be rotat

相关标签:
3条回答
  • 2021-02-12 22:10

    Indeed, set the rotate transformation to something like 90.1deg solves the issue...

    I have test many things, reported here: https://codepen.io/KevinNTH/pen/ZBgKdG

    <!-- workaround ios -->
    <svg class="wka-ios">
      <g transform="rotate(-90.1 30 30)">
        <circle cx="25" cy="25" r="15"/>
      </g>
    </svg>
    
    0 讨论(0)
  • 2021-02-12 22:11

    I've experienced this painfully on iOS 10.1 and Safari 10.0.1. The bug is definitely triggered by any rotate value which computes to a value divisible by 90 degrees.

    But it gets weirder: the bug's presence is affected by the current zoom level.

    See this demo/series of minimal test cases I put together (jsFiddle version here). Best to run the snippet then expand to full page:

    svg {
      height: 80px;
      width: 80px;
    }
    
    circle {
      fill: none;
      stroke-dasharray: 150;
      stroke-width: 4px;
      stroke: #6fdb6f;
      transform-origin: center center;
    }
    
    .degrot {
      transform: rotate(-90deg);
    }
    
    .degrot-offset {
      transform: rotate(-90.1deg);
    }
    
    .degrot-offset-more {
      transform: rotate(-92deg);
    }
    
    .turnrot {
      transform: rotate(-0.25turn);
    }
    
    .turnrot-offset {
      transform: rotate(-0.251turn);
    }
    
    
    svg[viewBox] circle {
      stroke-dasharray: 300;
      stroke-width: 8px;
    }
    
    svg[viewBox].scaledown circle {
      stroke-dasharray: 300;
      stroke-width: 8px;
    }
    
    svg[viewBox].noscale circle {
      stroke-dasharray: 150;
      stroke-width: 4px;
    }
    
    svg[viewBox].scaleup circle {
      stroke-dasharray: 75;
      stroke-width: 2px;
    }
    
    .wc {
      will-change: transform;
    }
    
    
    /* Demo prettification */
    
    p:last-child {
      margin-bottom: 0;
    }
    
    td {
      padding: 10px;
    }
    
    tr td:first-of-type {
      width: 80px;
      min-height: 80px;
    }
    
    tr + tr td {
      border-top: 1px solid #dcdcdc;
    }
    <table>
      <tr><td colspan="2">In Safari 10.0.1 and iOS 10.1, strange behavior can be observed on SVG shapes with <code>rotate</code> values not divisible by 90 degrees, when <code>transform-origin: center center;</code></td></tr>
      <tr>
        <td>
    
          <svg xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot" r="35" cy="40" cx="40" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-90deg);</code>
          <p>The stroke improperly begins <a href="https://www.w3.org/TR/SVG11/shapes.html#CircleElement">at 3:00</a>, as if the <code>transform</code> rule hadn't been applied.</p>
        </td>
      </tr>
    
      <tr>
        <td>
    
          <svg xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot-offset" r="35" cy="40" cx="40" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-90.1deg);</code>
          <p>The stroke begins at (twelve seconds before) 12:00, as expected.</p>
        </td>
      </tr>
    
      <tr>
        <td>
    
          <svg xmlns="http://www.w3.org/2000/svg">
            <circle class="turnrot" r="35" cy="40" cx="40" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-0.25turn);</code>
          <p>The same bug applies to any <code>rotate</code> value which computes to a multiple of 90 degrees.</p>
        </td>
      </tr>
    
      <tr>
        <td>
    
          <svg xmlns="http://www.w3.org/2000/svg">
            <circle class="turnrot-offset" r="35" cy="40" cx="40" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-0.251turn);</code>
          <p>43 seconds before noon.</p>
        </td>
      </tr>
    
    
      <tr><td colspan="2">But when the SVG element specifies a <code>viewBox</code> which is being scaled down, things can get weird:</td></tr>
      
      <tr>
        <td>
    
          <svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot" r="70" cy="80" cx="80" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-90deg);</code>
          <p>So far, so the same.</p>
        </td>
      </tr>
    
      <tr>
        <td>
    
          <svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot-offset" r="70" cy="80" cx="80" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-90.1deg);</code>
          <p>But now, offsetting by a little bit doesn't work, <em>unless</em> you zoom in the page in past a certain zoom threshold (either via pinching, or <code>View > Zoom</code> and/or keyboard shortcut). Try it; it's unsetting!</p>
          <p>This is probably because of some rounding of that the zooming engine performs, because...</p>
        </td>
      </tr>
    
      <tr>
        <td>
    
          <svg viewBox="0 0 160 160" class="scaledown" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot-offset-more" r="70" cy="80" cx="80" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-92deg);</code>
          <p>offsetting by a larger amount restores expected behavior.</p>
        </td>
      </tr>
    
      <tr><td colspan="2">If the SVG element is not being scaled <em>down</em>, behavior identical to the first section resumes. Zooming has no effect:</td></tr>
      
      <tr>
        <td>
          
          <svg viewBox="0 0 80 80" class="noscale" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot" r="35" cy="40" cx="40" />
          </svg>
    
          <svg viewBox="0 0 40 40" class="scaleup" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot" r="17.5" cy="20" cx="20" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-90deg);</code>
          <p>
          Top: No scaling (viewBox dimensions match parent element's)<br><br>
          Bottom: Scaling up (viewBox dimensions half of parent element's)
          </p>
        </td>
      </tr>
    
      <tr>
        <td>
          
          <svg viewBox="0 0 80 80" class="noscale" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot-offset" r="35" cy="40" cx="40" />
          </svg>
    
          <svg viewBox="0 0 40 40" class="scaleup" xmlns="http://www.w3.org/2000/svg">
            <circle class="degrot-offset" r="17.5" cy="20" cx="20" />
          </svg>
    
        </td>
        <td>
          <code>transform: rotate(-90.1deg);</code>
          <p>
            Top: No scaling (viewBox dimensions match parent element's)<br><br>
            Bottom: Scaling up (viewBox dimensions half of parent element's)
          </p>
        </td>
      </tr>
    
      <tr><td colspan="2">But there is one exception:</td></tr>
    
      <tr>
        <td>
          
          <svg class="degrot wc" xmlns="http://www.w3.org/2000/svg">
            <circle r="35" cy="40" cx="40" />
          </svg>
    
        </td>
        <td>
          <p>On the parent <code>svg</code> element:</p>
          <code>transform: rotate(-90deg);<br>will-change: transform;</code>
          <p>Iff the the the rotation is applied to a <em>parent</em> of the SVG shape (including the SVG element itself) along with the rule <code>will-change: transform</code>, all rotation values work as expected.</p>
        </td>
      </tr>
    
      <tr><td colspan="2">All these behaviors have been observed in Safari 10.0.1 and iOS 10.1. They appear to be fixed as of iOS 10.2 Beta 2.</td></tr>
    </table>

    As stated in the demo, it appears to be fixed in iOS 10.2, at least in the public beta version I just downloaded. Presumably, a Safari fix will also be arriving in due time.

    iOS 10.1

    iOS 10.2 (Public Beta 2)

    0 讨论(0)
  • 2021-02-12 22:12

    This is happening to me as well, I settled on using a rotation just shy of being divisible by 90 degrees to get around this in the interim.

    0 讨论(0)
提交回复
热议问题