javascript - Chrome 在记录克隆的 SVGElement 时添加属性 [requiredExtensions, systemLanguage]

标签 javascript google-chrome svg

问题

正在 SVGElements 上进行转换并发现了一些我不理解的东西。

基本上我正在尝试克隆现有的 SVGElement使用cloneNode(true)并使用 transform.baseVal.getItem(0).setMatrix() 更改其矩阵。只要我不记录新的SVGElement,这一切都可以正常工作。使用console.log() .

这是一个例子

必须检查实际的控制台,而不是代码片段的内联输出。

;window.onload = function(){
  var tSVG = document.querySelector('svg');
  var tSVGElement = tSVG.querySelector('#AL > g');
  var tSVGElement2 = tSVGElement.cloneNode(1);
  var tMatrix2 = tSVGElement2.transform.baseVal.numberOfItems ? tSVGElement2.transform.baseVal.getItem(0).matrix : tSVGElement2.transform.baseVal.appendItem(tSVG.createSVGTransform()).matrix
  
  console.log(1, tSVGElement2);

  tMatrix2.e += 50;
  tMatrix2.f += 50;
  
  tSVGElement2.transform.baseVal.getItem(0).setMatrix(tMatrix2)
  tSVGElement.parentNode.appendChild(tSVGElement2);
  
  console.log(2, tSVGElement2);
};
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2253" width="811" height="661">
  <g id="AL" class="Touchable">
    <g transform="matrix(0.0736096,0,0,0.0736094,313.881,379.029)">
      <g stroke-width=".39819491" transform="matrix(2.51133 0 0 2.51134 -239.06 -636.03)">
        <rect width="397" height="397" x="95.790001" y="253.86" fill="#ccc" stroke="#000" stroke-width="1.19458485" stroke-miterlimit="3" ry="0" rx="0"></rect>
        <path fill="#fff" d="M153.88 347.3H354.4v207.58H153.88z"></path>
        <path fill="#010002" d="M202.2 395.8c-3.22-3.24-4.84-7.17-4.84-11.8 0-4.63 1.62-8.55 4.85-11.8 3.3-3.23 7.2-4.85 11.8-4.85 4.6 0 8.6 1.62 11.8 4.86 3.3 3.3 4.9 7.2 4.9 11.8 0 4.6-1.6 8.6-4.8 11.8-3.2 3.3-7.1 4.9-11.8 4.9-4.7 0-8.5-1.6-11.8-4.8zm-21.32 79.6c1.04.8 2.26 1.22 3.64 1.22 1.4 0 2.6-.4 3.65-1.22 1.04-.8 1.56-2.13 1.56-3.98v-45.1c0-.7.34-1.16 1.04-1.4.7-.22 1.27-.33 1.73-.33.46 0 1.04.1 1.74.3.7.2 1.04.7 1.04 1.4V530c0 2.1.75 3.83 2.25 5.2 1.5 1.4 3.3 2.1 5.38 2.1s3.9-.7 5.4-2.1c1.5-1.37 2.3-3.1 2.3-5.2v-63.46c0-1.16.5-1.9 1.4-2.26.9-.36 1.6-.53 2.1-.53s1.1.18 1.9.52c.8.34 1.2 1.1 1.2 2.25V530c0 2.08.8 3.8 2.3 5.2 1.5 1.4 3.3 2.08 5.4 2.08 2.3 0 4.2-.7 5.6-2.07 1.4-1.4 2.1-3.1 2.1-5.2l.4-103.7c0-.7.4-1.1 1.1-1.4.7-.2 1.3-.3 1.78-.3.5 0 1.05.1 1.75.4.7.3 1 .7 1 1.4v45.1c0 1.9.5 3.2 1.55 4 1 .8 2.2 1.2 3.45 1.2s2.4-.4 3.46-1.2c1.03-.8 1.55-2.1 1.55-4v-47.9c0-4.6-1.54-8.8-4.66-12.5-3.15-3.7-7.37-5.5-12.7-5.5h-36.5c-5.3 0-9.2 1.9-11.6 5.6-2.44 3.7-3.65 7.8-3.65 12.5v47.8c0 1.9.5 3.2 1.53 4zm179.86-134.93c2.08 1.96 3.12 4.45 3.12 7.46v206.73c0 3-1.04 5.5-3.12 7.46-2.1 1.97-4.63 2.95-7.64 2.95H155.04c-3 0-5.55-.98-7.63-2.95-2-1.96-3.1-4.45-3.1-7.46V347.93c0-3 1.1-5.5 3.1-7.46 2.1-1.97 4.7-2.95 7.7-2.95h198c3 0 5.6.98 7.7 2.95zm-14.23 14.4H161.7v192.86h184.8V354.86zm-52.7 45.78c4.6 0 8.6-1.62 11.8-4.85 3.2-3.23 4.9-7.17 4.9-11.8 0-4.63-1.6-8.55-4.8-11.8-3.2-3.23-7.1-4.85-11.8-4.85-4.6 0-8.5 1.62-11.8 4.86-3.2 3.3-4.8 7.2-4.8 11.8 0 4.6 1.6 8.6 4.9 11.8 3.3 3.2 7.2 4.9 11.8 4.9zm-33.1 74.75c1.1.8 2.3 1.22 3.7 1.22 1.4 0 2.6-.4 3.7-1.22 1.1-.8 1.6-2.13 1.6-3.98v-45.1c0-.7.4-1.16 1.1-1.4.7-.22 1.3-.33 1.8-.33s1.1.1 1.8.3c.7.2 1.06.7 1.06 1.4V530c0 2.1.75 3.83 2.25 5.2 1.5 1.4 3.3 2.1 5.4 2.1 2.08 0 3.87-.7 5.38-2.1 1.5-1.37 2.27-3.1 2.27-5.2v-63.46c0-1.16.43-1.9 1.4-2.26.9-.35 1.6-.53 2.1-.53s1.1.18 2 .52c.95.34 1.4 1.1 1.4 2.25V530c0 2.08.7 3.8 2.1 5.2 1.4 1.4 3.24 2.08 5.56 2.08 2.1 0 3.9-.7 5.4-2.07 1.5-1.4 2.26-3.1 2.26-5.2V426.3c0-.7.3-1.16 1-1.4.7-.22 1.25-.33 1.7-.33.46 0 1.03.1 1.73.32s1.02.7 1.02 1.4v45.1c0 1.8.5 3.1 1.56 3.9 1.05.8 2.27 1.2 3.65 1.2 1.4 0 2.6-.4 3.65-1.2 1.04-.8 1.56-2.2 1.56-4v-47.8c0-4.7-1.6-8.8-4.84-12.5-3.25-3.7-7.53-5.6-12.84-5.6H275c-5.3 0-9.26 1.8-11.8 5.5-2.55 3.7-3.8 7.8-3.8 12.5v47.8c0 1.8.5 3.1 1.54 4zm180.6 49.16h-15.6V472.7s.1-2.13-2.7-2.13h-23.7c-3.9 0-3.2 2.55-3.2 2.55v52.52h-16.8c-4.9 0-.4 4.27-.4 4.27l29.8 36.1s2.5 2.9 5.1.3c3.6-3.5 28.9-37.2 28.9-37.2s4.5-4.4-1.4-4.4zm-61.2-140.98h15.6v51.85s0 2.14 2.7 2.14H422c3.88 0 3.2-2.56 3.2-2.56v-52.5H442c4.9 0 .4-4.2.4-4.2l-29.87-36.1s-2.45-2.8-5.02-.3c-3.5 3.6-28.9 37.3-28.9 37.3s-4.5 4.5 1.5 4.5z"></path>
      </g>
    </g>
  </g>
</svg>

预期输出:

<g transform="matrix(0.0736096 0 0 0.0736094 363.881 429.029)">..</g>

实际输出:

<g transform="matrix(0.0736096 0 0 0.0736094 363.881 429.029)" requiredExtensions="" systemLanguage="">..</g>

所以一旦我记录了克隆的 SVGElement Chrome 添加了两个属性 requiredExtensionssystemLanguage , which leads to the element no being rendered 。一旦我删除 console.log(tSVGElement2);在克隆上一切正常。

为什么 Chrome 在日志记录中添加这两个属性? IE11 也只将其添加到子元素上。

最佳答案

对于您的原因问题:

我为此提出了一个问题,经 chrome ( https://bugs.chromium.org/p/chromium/issues/detail?id=873470 ) 确认,似乎这是一个错误。原因是:

I'd guess that this is caused by attribute synchronization, and the reason console.log triggers it is that it enumerates all properties and thus creates the tear-off/wrapper for systemLanguage/requiredExtensions - which in turn makes them require synching.

<小时/>

预编辑:似乎我对 namespace 不被继承的看法是错误的,一件有趣的事情是虽然 'requiredExtensions' 属性应该设置为“true”或不存在可供渲染的元素。这是 SVG 规范 @ 5.7.1 here 的一部分通常,该属性(与 systemLanguage 一起)在 switch 元素上设置。有趣的是,在主线程中控制台 cloned g 时,会添加此属性,其值 "" 会转换为 false,并最终导致元素不被渲染。

但是,如果您等待事件循环完成然后记录,则属性不存在,请参阅此 FIDDLE .

作为结论,如果您克隆 g 节点并控制台记录它而不将其附加到树中,则这些属性将出现并且元素将不会被渲染。虽然我不知道这是预期的行为还是错误。

解决方案

在行为得到解决之前,猴子修补appendChild,我必须使用微任务队列,因为显然属性是在调用appendChild期间添加的:

SVGGraphicsElement.prototype.appendChild = (function(append){
    return function(node){
        setTimeout(function(){
        node.removeAttribute("requiredExtensions");
        node.removeAttribute("systemLanguage");
    },0);
        return append.apply(this,arguments);
    }
}(SVGGraphicsElement.prototype.appendChild));

http://jsfiddle.net/ibowankenobi/8s97ophj/

解决方案 2:

显然,您必须对其他修改 DOM 树的函数进行猴子修补,例如 inserNode 等。在这种情况下,突变观察器提供了更通用的解决方案。您可以与不同的 parent 一起观看多次,同一观察者被回收:

function watch(node,parentNode){
    var config = watch._config,
                callback = function(list,observer){
            list.forEach(function(d,i){
                            if(d.type !== "childList"){return}
                            if(
                                Array.prototype.slice.call(d.addedNodes)
                                .some(function(d,i){
                                    return d === node
                                })
                            ) {
                                console.log("added??");
                                setTimeout(function(){
                                node.removeAttribute("requiredExtensions");
                                node.removeAttribute("systemLanguage");
                            },0);
                                observer.disconnect();
                            }
                        })
        },
                observer = node._observer || (node._observer = new MutationObserver(callback));
        observer.observe(parentNode,config);
        return node;
}
watch._config = {childList:true,subtree:true};

使用:

var tSVG = document.querySelector('svg');
  var tSVGElement = tSVG.querySelector('#AL > g');
  var tSVGElement2 = tSVGElement.cloneNode(1);
  watch(tSVGElement2,tSVGElement.parentNode/*Or tSVG since subtree:true*/);
....

一旦进入 DOM,观察者就会断开连接,属性也会被删除,如果需要,您可以修改函数并提供要更改的属性列表。查看此工作 FIDDLE

<小时/>

~~发生这种情况是因为您没有克隆整个 svg,而是克隆 g,此时 xmlns 尚未定义这个 g 因为它从它的 ownerSVG 继承了它。当您将其附加到其父 svg 时,浏览器就会知道它是 SVG 的一部分。如果您在 tSVGElement.parentNode.appendChild(tSVGElement2) 之后控制台日志,它应该输出正常。~~

关于javascript - Chrome 在记录克隆的 SVGElement 时添加属性 [requiredExtensions, systemLanguage],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51785795/

相关文章:

javascript - 动态添加的 SVG g 标签未显示

javascript - 在JS中获取URL参数并嵌入到JS函数中

Javascript - 拖动后如何获得矩形,圆形坐标?

Javascript .getHours() 无法正常工作

pdf 页面属性中的 Javascript 在 Google Chrome 中不起作用

flash - 固定位置在 Chrome 中损坏,后面有 Flash

javascript - 如何将 font-awesome svg 图标导出为 base64 url​​?

javascript - 使用 jQuery 创建悬停和单击功能的精益方法到 SVG 目录映射

javascript - 将 Intl.NumberFormat 与 'de' 区域设置和 'percent' 样式一起使用

javascript - 如何在 react 路由器中加载下一页之前等到服务调用完成