Chrome中svg动画错误的解决方法:背面可见性和变换原点有时没有影响

pxq42qpu  于 2023-09-28  发布在  Go
关注(0)|答案(1)|浏览(97)

我想制作一个包含一些“卡片翻转”风格动画的svg图片文件,使用css并在svg文件中嵌入样式表。在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>

这是一个带有裸矩形的图片,如上面的代码所示:http://imgh.us/transformorigin_example_1.svg
这是一幅以列特为单位的图,像这样:<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的React是奇怪地将卡片的背面向左偏移(这似乎是因为原始的旋转,旨在将背面放在颠倒的起始位置,围绕错误的中心旋转-换句话说,translation-origin属性似乎在那个阶段尚未生效,或者做得不正确),然后围绕新的中心旋转整个东西(然而,它确实看起来像是在(mangled)对象的translation-origin: 50% 50%处,因为它应该,只有一个部分现在处于错误的位置,所以整个效果最终是错误的)。非常令人厌恶。
有几件事我试过了,没有用:1)将transform-origin: 50% 50%;放在标记为/* Front side /和/ Backside /的声明块中(以便它们在代码方面接近它们应该影响的转换); 2)将声明块/ Both sides /放在/ Front side /和/ Backside */块之前; 3)将样式信息放入rect元素(<rect … style=”…” />)中; 4)(有点绝望)添加-webkit-前缀; 5)使用-webkit-backface-visibility: visible;-webkit-backface-visibility: hidden;,即打开能见度,然后关闭,如this question的答案; 6)将“overflow:visible”添加到“outer”组,如this question中所建议的; 7)加入额外的transform:rotateY(0deg);transform: translate3d(0,0,0);,如同一问题所建议。
也许还有一点很有趣,在Chrome的inspector中随意摆弄属性有时可以中和第二个问题(不正确的translation-origin),使卡片的两面最终在同一个地方,如果卡片是半透明的并且包含一个形状(但背面可见性仍然是错误的),这就变得很明显了,尽管我还没有能够在发生这种情况时辨别出任何模式。这种行为表明我们实际上可能在处理两个不同的bug。到目前为止,似乎只有在检查器中才有可能实现这一点,而不是通过对源代码进行更改。
我曾试图在网上寻找信息,但在谷歌上搜索“Chrome backface-visibility bug”或“chrome transform-origin bug”之类的东西,并没有真正找到任何有用的东西,我已经尝试过的想法。(然而,它确实出现了这句不祥的话:“Chrome充满了这些类型的SVG转换错误。”)有一堆旧的,有点类似的stackoverflow问题,但以下都没有帮助:backface-visibility:hidden bug in chromeDid -webkit-backface-visibility break today in Chrome?Webkit backface visibility not working .
有什么想法吗?

yv5phkfx

yv5phkfx1#

我找不到一个解决方案,在纯SVG的Chrome中工作。然而,我确实使用HTML元素实现了同样的效果,这对某些人来说可能是一个可以接受的解决方案。
诀窍是为每个面使用单独的SVG元素,因为backface-visibility: hidden适用于HTML元素。
CodePen: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>

相关问题