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

时间:2018-08-10 11:44:55

标签: 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就会添加两个属性requiredExtensionssystemLanguagewhich leads to the element no being rendered。删除克隆上的console.log(tSVGElement2);后,一切正常。

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

1 个答案:

答案 0 :(得分:1)

您的问题的答案:

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

  

我猜这是由属性同步引起的,而console.log触发它的原因是它枚举了所有属性,从而为systemLanguage / requiredExtensions创建了撕下/包装器-进而使它们需要同步


预编辑:似乎我对不继承名称空间是错误的,但有趣的是,尽管‘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等。在这种情况下,变异观察者提供了更通用的解决方案。您可以与不同的父母多次观看,同一个观察者将被回收:

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)之后管理日志,它应该可以正常输出。~~