Javascript Chrome在记录克隆的SVGElement时添加属性[requiredExtensions,systemLanguage] 问题
正在处理Javascript Chrome在记录克隆的SVGElement时添加属性[requiredExtensions,systemLanguage] 问题,javascript,google-chrome,svg,Javascript,Google Chrome,Svg,正在处理SVGElements上的转换,发现了一些我不理解的东西 基本上,我尝试使用cloneNode(true)克隆一个现有的SVGElement,并使用transform.baseVal.getItem(0.setMatrix()更改其矩阵。只要我不使用console.log()记录新的SVGElement,这一切都可以正常工作 这里有一个例子 必须检查实际的控制台,而不是代码段的内联输出 ;window.onload=函数(){ var tSVG=document.querySelect
SVGElements
上的转换,发现了一些我不理解的东西
基本上,我尝试使用cloneNode(true)
克隆一个现有的SVGElement
,并使用transform.baseVal.getItem(0.setMatrix()
更改其矩阵。只要我不使用console.log()
记录新的SVGElement
,这一切都可以正常工作
这里有一个例子
必须检查实际的控制台,而不是代码段的内联输出
;window.onload=函数(){
var tSVG=document.querySelector('svg');
var tSVGElement=tSVG.querySelector('#AL>g');
var tSVGElement2=tSVGElement.cloneNode(1);
var tMatrix=tSVGElement2.transform.baseVal.numberOfItems?tSVGElement2.transform.baseVal.getItem(0)。矩阵:tSVGElement2.transform.baseVal.appendItem(tSVG.createSVGTransform())。矩阵
控制台日志(1,tSVGElement2);
tMatrix2.e+=50;
t矩阵x2.f+=50;
tSVGElement2.transform.baseVal.getItem(0).setMatrix(tMatrix)
tSVGElement.parentNode.appendChild(tSVGElement2);
控制台日志(2,tSVGElement2);
};代码>
对于您的“为什么”问题:
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*/);
....
我为此打开了一个问题,经chrome()确认,这似乎是一个bug。原因是:
我猜这是由属性同步引起的,而console.log触发它的原因是它枚举了所有属性,从而为systemLanguage/requiredExtensions创建了撕裂/包装器,这反过来又使它们需要同步
预编辑:似乎我对名称空间未被继承的看法是错误的,一件有趣的事情是,尽管'requireExtensions'
属性应该设置为“true”或不存在,以便元素呈现。这是SVG spec@5.7.1的一部分,通常在开关
元素上设置属性(以及systemLanguage
)。有趣的是,在主线程中对克隆的g进行控制台操作时,会使用值
“”添加此属性,该值会转换为false,并导致元素无法呈现
但是,如果等待事件循环完成并记录日志,则属性不存在,请参见此
作为结论,如果克隆g节点并在不将其附加到树的情况下对其进行控制台日志记录,则会显示这些属性,并且不会呈现元素。虽然我不知道这是故意的行为还是一个bug
解决方案
在行为得到解决之前,我必须使用一个微任务队列,因为显然属性是在调用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));
解决方案2:
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树的其他函数,如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后,观察者被断开连接,属性被删除,您可以修改该函数,并提供一个属性列表,以便根据需要进行更改。请参见此操作
~~之所以会发生这种情况,是因为您没有克隆整个
svg
,而是克隆g
,此时没有为此g
定义xmlns
,因为它是从其所有者vg
继承的。当您将它附加到其父级svgsvg
时,浏览器就知道它是svg的一部分。如果您在tSVGElement.parentNode.appendChild(tSVGElement2)
之后进行控制台日志记录,那么它的输出应该很好。~~遗憾的是,即使在附加属性之后,属性仍然会保留。我更新了剪下的片段,以便您可以自己查看。如果删除id属性会发生什么?您是指父对象?是的,这就是您要克隆的。我克隆它的子对象,而不是对象本身。组
I clone只有一个转换。听起来像是一个Chrome bug。你有没有向Chrome的bugtracker报告过,或者看看是否有其他人报告过?@Robert Longson:我检查过,但还没有报告我自己。但它也出现在IE11和Edge中,只是在克隆元素的所有子元素上添加了属性。你总是给我同样的回答:-)如果你向浏览器的错误追踪者报告一个错误,它可能会被修复。我们能为您做些什么?也就是说,除了“你发现了一个bug”之外,你还想在答案中寻找什么?经chrome确认,这是一个bug。请参阅更新的answer@ibrahim谢谢。不幸的是,IE支持的答案仍然悬而未决,我猜他们没有chromium团队快:-)我会接受你的帖子,因为你回答了我的主要问题。