SVG PacMan 中的鬼眼在 Firefox 中正确渲染,但在其他浏览器中不正确

Posted

技术标签:

【中文标题】SVG PacMan 中的鬼眼在 Firefox 中正确渲染,但在其他浏览器中不正确【英文标题】:Ghost eyes in SVG PacMan are rendered correctly in Firefox, but not in other browsers 【发布时间】:2021-06-21 04:41:47 【问题描述】:

我的 SVG PacMan 的 GitHub 存储库可在此处获得:https://github.com/FlatAssembler/SVG-Pacman

你可以在这里看到它:http://flatassembler.github.io/pacman.html

画鬼的功能在这里:

      function drawGhost(x, y, color, id, transparent) 
        //Duhovi su geometrijski likovi omedeni crtama (dno) i kubicnom Bezierovom krivuljom (vrh).
        if (/Firefox/.test(navigator.userAgent)) 
          var svg = document.createElementNS(XML_namespace_of_SVG, "svg");
          svg.setAttribute("x", x - 8);
          svg.setAttribute("y", y - 16);
          var path = document.createElementNS(XML_namespace_of_SVG, "path");
          path.setAttribute("fill", color);
          var d = "M " + 0 + " " + (16 + 8);
          d +=
            "C " +
            3 +
            " " +
            0 +
            " " +
            (8 + 5) +
            " " +
            0 +
            " " +
            (8 + 8) +
            " " +
            (16 + 8);
          d += " l -4 -3 l -4 3 l -4 -3 Z";
          path.setAttribute("d", d);
          svg.setAttribute("id", id);
          if (transparent) svg.setAttribute("fill-opacity", 0.5); //Siluete (bijeli duhovi).
          svg.appendChild(path);
          var left_eye = document.createElementNS(
            XML_namespace_of_SVG,
            "circle"
          );
          left_eye.setAttribute("cx", 5);
          left_eye.setAttribute("cy", 15);
          left_eye.setAttribute("r", 2);
          left_eye.setAttribute("fill", "black");
          svg.appendChild(left_eye);
          var right_eye = document.createElementNS(
            XML_namespace_of_SVG,
            "circle"
          );
          right_eye.setAttribute("cx", 11);
          right_eye.setAttribute("cy", 15);
          right_eye.setAttribute("r", 2);
          right_eye.setAttribute("fill", "black");
          svg.appendChild(right_eye);
          zaslon.appendChild(svg);
         else 
          var path = document.createElementNS(XML_namespace_of_SVG, "path");
          path.setAttribute("fill", color);
          var d = "M " + (x - 8) + " " + (y + 8);
          d +=
            "C " +
            (x - 5) +
            " " +
            (y - 16) +
            " " +
            (x + 5) +
            " " +
            (y - 16) +
            " " +
            (x + 8) +
            " " +
            (y + 8);
          d += " l -4 -3 l -4 3 l -4 -3 Z";
          path.setAttribute("d", d);
          path.setAttribute("id", id);
          if (transparent) path.setAttribute("fill-opacity", 0.5); //Siluete (bijeli duhovi).
          zaslon.appendChild(path);
        
      

如果我启用在所有浏览器中呈现幽灵的眼睛,那么在 Firefox 以外的浏览器中,幽灵不再是动画的。我用来制作鬼魂动画的代码如下:

          for (var i = 0; i < 3; i++) 
            if (
              jeLiPacmanPojeoDuha[i] &&
              brojacGlavnePetlje - kadaJePacmanPojeoVelikuTocku < 30
            )
              //Ako je PacMan nedavno pojeo duha, animiraj bijelu siluetu...
              zaslon
                .getElementById("bijeli" + (i + 1))
                .setAttribute(
                  "transform",
                  "translate(" +
                    (20 / 5) *
                      brojacAnimacijskePetlje *
                      xKomponentaSmjeraPacmana[smjerKretanjaSiluete[i]] +
                    " " +
                    (20 / 5) *
                      brojacAnimacijskePetlje *
                      yKomponentaSmjeraPacmana[smjerKretanjaSiluete[i]] +
                    ")"
                );
            //... inace animiraj duha.
            else
              zaslon
                .getElementById("duh" + (i + 1))
                .setAttribute(
                  "transform",
                  "translate(" +
                    (20 / 5) *
                      brojacAnimacijskePetlje *
                      xKomponentaSmjeraPacmana[smjerDuha[i]] +
                    " " +
                    (20 / 5) *
                      brojacAnimacijskePetlje *
                      yKomponentaSmjeraPacmana[smjerDuha[i]] +
                    ")"
                );
         

好像 SVG 转换在 Firefox 以外的浏览器中对 &lt;svg&gt; 元素本身没有影响。我该怎么办?

【问题讨论】:

第一个,非常酷的项目!也都在 SVG 中!查看 DOM,您将 SVG 放入另一个 SVG 中,我不知道这是否有效。你能证实吗?在 Firefox 中,我看到嵌套的 SVG,在 Chrome 中,我看到它是扁平的。你可以改用组吗? @ChrisHaas “使用组”是什么意思?我很确定在 SVG 元素中使用 SVG 元素是有效的:***.com/posts/16890342/revisions 我只做过简单的 SVG 工作,从未见过我认为有效的嵌套语法。我还错过了您正在使用 navigator.userAgent 进行文字 UA 测试并执行不同的逻辑。我看到了两个不同的 DOM,但我认为生成逻辑是相同的。对于那个很抱歉。对于一个组,我的意思是 &lt;g&gt; 元素,这是 SVG 对事物进行分组的方式。嵌套的&lt;svg&gt; 元素可能具有非标准的转换规则,但这只是我的猜测。我会制作一个非常简单的 5 元素 SVG 并尝试让转换工作吗? 我下载了您的项目并为所有浏览器重新启用了眼睛。然后当我通过 Chrome 运行代码时,您的转换似乎都在工作,它们只是跳动。不幸的是,在逻辑和语言(克罗地亚语?)之间很难调试。你认真地做了一件非常棒的事情,这超出了我进一步调试的能力。我唯一的最后一个猜测是,您似乎正在添加和删除 DOM 项目,对吗?如果是这样,Chrome 可能正在执行您不想要的优化,我也不知道具体会是什么。 我的猜测是 Chrome 正在以一种特殊的方式处理嵌套的&lt;svg&gt;,但我真的不知道为什么。我仅以此为基础,这是我在您的代码中可以看到的唯一区别。您应该能够对此进行非常非常简单的测试,只需一个简单的 &lt;svg&gt; 和嵌套的 &lt;svg&gt; 并尝试以与当前循环相同的帧速率对其进行动画处理。不要将任何现有代码用于此测试,使此代码独立。 【参考方案1】:

自己解决了,下面是我修改drawGhost函数的方法:

        function drawGhost(x, y, color, id, transparent) 
            //Duhovi su geometrijski likovi omedeni crtama (dno) i kubicnom Bezierovom krivuljom (vrh).
            var svg = document.createElementNS(XML_namespace_of_SVG, "g");
            svg.setAttribute("x", x - 8);
            svg.setAttribute("y", y - 16);
            var path = document.createElementNS(XML_namespace_of_SVG, "path");
            path.setAttribute("fill", color);
            var d = "M " + (x - 8) + " " + (y + 8);
            d +=
                    "C " +
                    (x - 5) +
                    " " +
                    (y - 16) +
                    " " +
                    (x + 5) +
                    " " +
                    (y - 16) +
                    " " +
                    (x + 8) +
                    " " +
                    (y + 8);
            d += " l -4 -3 l -4 3 l -4 -3 Z";
            path.setAttribute("d", d);
            svg.setAttribute("id", id);
            if (transparent)
                svg.setAttribute("fill-opacity", 0.5); //Siluete (bijeli duhovi).
            svg.appendChild(path);
            var left_eye = document.createElementNS(
                    XML_namespace_of_SVG,
                    "circle"
                    );
            left_eye.setAttribute("cx", x - 8 + 5);
            left_eye.setAttribute("cy", y - 16 + 15);
            left_eye.setAttribute("r", 2);
            left_eye.setAttribute("fill", "black");
            svg.appendChild(left_eye);
            var right_eye = document.createElementNS(
                    XML_namespace_of_SVG,
                    "circle"
                    );
            right_eye.setAttribute("cx", x - 8 + 11);
            right_eye.setAttribute("cy", y - 16 + 15);
            right_eye.setAttribute("r", 2);
            right_eye.setAttribute("fill", "black");
            svg.appendChild(right_eye);
            zaslon.appendChild(svg);
        

【讨论】:

以上是关于SVG PacMan 中的鬼眼在 Firefox 中正确渲染,但在其他浏览器中不正确的主要内容,如果未能解决你的问题,请参考以下文章

Firefox 中的 SVG 过滤器转换

Firefox中的svg变换原点问题

Firefox 中的 svg innerHTML 无法显示

Firefox 浏览器中的 SVG 路径元素缩放转换错误

内容安全策略正在阻止 Firefox 中的 svg 图标精灵

在 Firefox 中的画布上下文对象上使用 svg 调用 drawImage() 时出现问题