在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就会添加两个属性requiredExtensions
和systemLanguage
,which leads to the element no being rendered。删除克隆上的console.log(tSVGElement2);
后,一切正常。
为什么Chrome会在日志记录中添加这两个属性? IE11还将其添加到子元素上。
答案 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)
之后管理日志,它应该可以正常输出。~~