【问题标题】:SVG transform rotate by 90, 180 or 270 degrees not working on circle in Safari iOS 10SVG 变换旋转 90、180 或 270 度不适用于 Safari iOS 10 中的圆圈
【发布时间】:2017-03-14 19:39:39
【问题描述】:

我想通过设置stroke-dasharray 和改变stroke-dashoffset 来使用SVG 圆形元素创建一个圆环图。 SVG 元素需要旋转 270(或 -90)度,以便图表“条形图”从顶部开始。代码如下:

http://jsfiddle.net/q3wb6gkq/

使用transform="rotate(270, 80, 80)"中的第一个数字指定旋转角度。

问题是:在 iOS 10 上的 Safari 中查看时,未应用此旋转。实际上,设置 90、180 或 270 度旋转都没有效果。也不会应用相同的角度但为负(例如 -90)。

这是 iOS 10.0.1 上 Safari 中上述小提琴的截图:

在 iOS 9.3.5 上的 Safari 中也是如此:

作为一种解决方法,我发现使用类似 270.1 度的值可以解决问题,但是我想知道为什么 270 不工作以及是否有更好的处理方法。

【问题讨论】:

  • 无法重现此问题,但我怀疑它正在发生,因为圆圈没有特定的起点或终点。您可以通过将transform 属性移动到封闭的<g> 元素来修复它。或者,如果这不起作用,请使用 elliptical arc path segments 创建一个圆形路径。
  • 谢谢 - 我已经尝试在封闭的 元素上设置相同的转换,不幸的是这没有帮助。我没有尝试使用 ,因为我想继续使用 以及它的 stroke-dasharray 和 stroke-dashoffset 属性。当您说您无法重现该问题时 - 您的意思是您在 iOS 10 设备上打开了小提琴并且正确应用了转换?
  • @squeamishossifrage 一个圆圈在 SVG 中确实有一个特定的起点/终点。它位于3 o'clock
  • @RobertLongson 谢谢,我不知道。 ilokhov:我只是没有相同的环境,仅此而已。
  • 我的圆圈从底部拉入,因此需要旋转 90 度。因为我用一个比我现在使用 91deg 的圆的宽度大得多的节点(点)覆盖起点......但这让我不开心。我需要在ios9.3上尝试。这可能只是一个 Safari ios 10 错误。目前还不确定。

标签: ios svg mobile-safari ios10


【解决方案1】:

我在 iOS 10.1 和 Safari 10.0.1 上经历过这种痛苦。该错误肯定是由任何rotate 值触发的,该值计算为可被 90 度整除的值。

但它变得更奇怪了:错误的存在受当前缩放级别的影响。

查看我整理的这个演示/系列最小测试用例(jsFiddle 版本here)。最好运行 sn -p 然后展开到整页:

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>

正如演示中所述,它似乎已在 iOS 10.2 中得到修复,至少在我刚刚下载的公测版中是这样。据推测,Safari 修复程序也将在适当的时候到达。

iOS 10.1

iOS 10.2(公测 2)

【讨论】:

  • 感谢您整理测试用例。我目前无法访问 iOS 设备来检查行为 - 我会在接下来的几天内查看并回复您。不过,它似乎已在 iOS 10.2 测试版中修复这一事实令人鼓舞,希望在向公众发布时它会保持这种状态。
  • 刚刚在 iOS 10 设备上检查了测试用例,可以确认您的发现。您的最后一个示例包括设置“will-change:transform”(我以前不知道此属性)并且父元素的旋转似乎解决了这个问题。我在这里更新了我原来的小提琴来演示:jsfiddle.net/urfbc0gv 因为这为我原来的问题提供了一个解决方案,所以我将此答案标记为已接受。还要感谢您检查 iOS 10.2 测试版上的行为 - 希望此行为将很快得到修复。
  • 谢谢@ilokhov! will-change CSS 属性通常用于手动启动 GPU(如果启用),它可能无法自动检测到 animationtransition,例如在页面加载后由 JS 应用的。它可以帮助防止当元素突然触发硬件加速时可能发生的卡顿。因此,虽然它可能有效,但请注意,它也不必要地从浏览器请求 GPU 加速。不漂亮,但仍然是一种解决方法。
  • 如果有人想贡献或查看,也将我的演示作为一个小型 GitHub 存储库放在一起:github.com/unitof/90-degree-safari
【解决方案2】:

确实,将旋转变换设置为 90.1 度可以解决问题...

我测试了很多东西,在这里报告: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>

【讨论】:

  • 另外,我没有为旋转提供 x 和 y 坐标transform="rotate(-90.1 55 55)" 为我修复了它(其中 55 是 SVG 视图框的宽度/2)
【解决方案3】:

这也发生在我身上,我决定使用几乎不能被 90 度整除的旋转来临时解决这个问题。

【讨论】:

    猜你喜欢
    • 2013-04-22
    • 2010-10-16
    • 2013-02-09
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2021-02-24
    相关资源
    最近更新 更多