Chrome中的svg动画bug的解决方法:背面可见性和变换原点有时没有效果

J. *_*ser 5 css svg google-chrome css-animations

我想制作一个包含一些"卡片翻转"式动画的svg图片文件,使用带有svg文件中嵌入的样式表的css.在Chrome中,至少会出现两个问题,具体取决于所使用的确切代码:即使翻转时卡的正面仍保持可见,使背面遮挡,或卡背面错误定位.这是我想要实现的简化版本:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   viewBox="0 0 100 100"
   id="svg2"
   version="1.1">
  <style>
    .outmost {
        perspective: 100px;
        transform-style: preserve-3d;
    }

    .outer {
        transform-style: preserve-3d;

        animation: flip 3s infinite alternate;
        transform-origin: 50% 50%;
    }

    /* Front side */
    .outer > :nth-last-child(1)  {
        transform: rotateY(0deg);
    }

    /* Backside */
    .outer > :nth-child(1)  {
        transform: rotateY(-180deg);
    }

    /* Both sides */
    .outer > *  {
        backface-visibility: hidden;
        <!-- transform-style: preserve-3d; -->
        transform-origin: 50% 50%;
    }

    @keyframes flip {
        50%     { transform: rotateY(180deg); }
    }
  </style>
  <g class="outmost"> <!-- Container of the card -->
      <g class="outer"> <!-- The card itself -->
        <rect x="30" y="30" width="40" height="40" fill="red" /> <!-- Back side of the card -->
        <rect x="30" y="30" width="40" height="40" fill="green" /> <!-- Front side of the card -->
      </g>
  </g>
</svg>
Run Code Online (Sandbox Code Playgroud)

这是一张裸露的照片,如上面的代码所示:http: //imgh.us/transformorigin_example_1.svg

这是包含rects的图片,如下所示<g> <rect … /> </g>:http: //imgh.us/transformorigin_example_2.svg

这在Firefox 44中非常正确地显示,但在Chrome 48(在MS Windows下)严重破坏,我想知道是否有办法解决这种问题.(我已经写过了让它在Internet Explorer中运行的想法 - 后者根本没有为图片制作动画,这比破坏的动画好得多.)

首先,Chrome似乎并不尊重背面可视性,这会破坏整个卡片技巧:它始终显示同一张卡片; 背面不可见.我试图通过分别动画卡的正面和背面的动画来解决这个问题,当卡转向另一侧时改变每个卡的可见性属性,但这在Firefox或Chrome中都不能很好地工作 - 显然时间控制不够紧,所以两个翻转不同步.

其次,如果我把rect:s放在组内(这对应于实际使用),它仍然可以在Firefox中运行,但是Chrome通过奇怪地将卡的背面偏移到左侧来响应(这似乎是因为原始旋转,意图将背面置于颠倒的起始位置,围绕错误的中心旋转 - 换句话说,翻译原点属性似乎尚未在该阶段生效,或者已经错误地完成了,并且然后围绕它的新中心旋转整个东西(然而,它确实似乎是translation-origin: 50% 50%(受损的)对象,因为它应该,只有其中一个部分现在处于错误的位置,因此整个效果最终错误) .非常令人反感.

我尝试过的一些事情无济于事:1)放入transform-origin: 50% 50%;标有/*前面*/和/*背面*/的声明块内(以便它们在代码方面接近它们应该影响的转换) ); 2)在/*前侧*/和/*后侧*/块之前放置声明块/*双方*/; 3)将样式信息放在rect元素(<rect … style=”…” />)中; 4)(有点拼命)添加-webkit-前缀; 5)使用-webkit-backface-visibility: visible;-webkit-backface-visibility: hidden;,即将可见性打开,然后关闭,如同在这个问题的答案中一样; 6)按照本问题的建议,将"溢出:可见"添加到"外部"组; 7)增加一个额外的,transform:rotateY(0deg);或者transform: translate3d(0,0,0);在同一个问题中提出的.

也许有趣的是,在Chrome的检查员中无所事事地玩弄属性有时可以消除第二个问题(不正确的翻译起源),使得卡片的两面最终都在同一个地方,如果这些卡是半透明的并且包含一个形状(但是背面 - 可见性仍然是错误的),尽管在发生这种情况时我无法辨别任何模式.这种行为表明我们可能实际上在处理两个不同的错误.到目前为止,似乎只能在检查员中实现这一点,而不是通过对源进行更改.

我试图在网上找到信息,但谷歌搜索"chrome backface-visibility bug"或"chrome transform-origin bug"这些东西并没有真正发挥我已经尝试过的想法.(然而,它确实引发了这个错误的引用:"Chrome充满了这些类型的SVG转换错误.")有一堆旧的,有点类似的stackoverflow问题,但以下都没有帮助: backface-visibility :隐藏在Chrome有错误, 在Chrome今天的表现-webkit-背面能见度突破?, Webkit背面可见性不起作用.

有任何想法吗?

小智 0

我找不到在 Chrome 中使用纯 SVG 的解决方案。然而,我确实使用 HTML 元素实现了相同的效果,这对于某些人来说可能是可以接受的解决方案。

技巧是为每个面使用单独的 SVG 元素,因为它backface-visibility: hidden适用于 HTML 元素。

代码笔: https: //codepen.io/IJMacD/pen/qBLjdxw

<html>
  <style>
    .outmost {
        perspective: 1000px;
        transform-style: preserve-3d;
    }

    .outer {
        transform-style: preserve-3d;

        animation: flip 3s infinite alternate;
        transform-origin: 50px 0;
      
        position: relative;
    }

    /* Front side */
    .outer > :nth-last-child(1)  {
        transform: rotateY(0deg);
        backface-visibility: hidden;
    }

    /* Backside */
    .outer > :nth-child(1)  {
        transform: rotateY(-180deg);
    }

    /* Both sides */
    .outer > *  {
      position: absolute;
    }

    @keyframes flip {
        50%     { transform: rotateY(180deg); }
    }
  </style>
  
  <div class="outmost"> <!-- Container of the card -->
    <div class="outer"> <!-- The card itself -->
      <!-- Back side of the card -->
      <svg
         viewBox="0 0 100 100"
           width="100"
           height="100">

        <rect x="30" y="30" width="40" height="40" fill="red" /> 
        <text x="38" y="62" fill="white" style="font-family: sans-serif;font-size:32">R</text>
      </svg>
      <!-- Front side of the card -->
      <svg
         viewBox="0 0 100 100"
           width="100"
           height="100">

        <rect x="30" y="30" width="40" height="40" fill="green" /> 
        <text x="38" y="62" fill="white" style="font-family: sans-serif;font-size:32">F</text>
      </svg>
    </div>
  </div>
</html>
Run Code Online (Sandbox Code Playgroud)