我正在创建一个包含SVG元素的dom结构:
<div data-bind="with: searchable_select.f0000001" style="verticalAlign: top">
<input data-bind="value: select_filter_value, valueUpdate: 'afterkeydown', event: { change: change_filter_, blur: blur_filter_ }" style="display: none">
<div>
<select data-bind="options: select_list, value: working_value, event: { change: change_selector_ }, optionsText: 'label', optionsValue: 'value'" style="display: inline-block; maxWidth: 150px">
<option value="person_full_name_asc">Member Full Name (A-Z)</option>
<option value="person_full_name_desc">Member Full Name (Z-A)</option>
</select>
<svg style="display: inline-block; verticalAlign: middle" width="18" height="18" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle cx="6" cy="6" r="5" fill="#AAAAAA" stroke="#000000" stroke-width="2"></circle>
<path fill="#AAAAAA" stroke="#000000" stroke-width="2" d="M10,10 L17,17"></path>
</g>
</svg>
</div>
</div>
svg元素实际上没有显示。当我在Chrome开发人员工具中找到svg元素时,宽度和高度都显示为零。
我尝试删除了style属性。我已经尝试在style属性中设置宽度和高度。
我已将svg复制到单独的HTML文件中:
<html>
<head><title>maggen</title></head>
<body>
<svg style="display: inline-block; verticalAlign: middle" width="18" height="18" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<circle cx="6" cy="6" r="5" fill="#AAAAAA" stroke="#000000" stroke-width="2"></circle>
<path fill="#AAAAAA" stroke="#000000" stroke-width="2" d="M10,10 L17,17"></path>
</g>
</svg>
</body>
</html>
显示正常的地方。
如果我将svg元素包装在div中,则显示svg元素。事实上,如果我在Chrome开发者工具中编辑HTML,它就会显示出来。
所以,是的,为什么?我已经在谷歌搜索了这个,但要么它不存在,或者(更有可能)我的Google Fu无法完成任务。我的意思是,当然,我可以将它包装在一个div中 - 也许这是正确的事情 - 但我不愿意,因为那时我需要将其他东西包装在div中并且dom将开始变得混乱。 / p>
编辑:在预感中,我尝试将视口属性编辑到Chrome工具中的SVG元素中。瞧!元素是可见的!当我在创建文档时包含viewport属性时,它是不可见的。所以我尝试在Chrome工具中添加一个随机属性到SVG元素。瞧!元素是可见的!所以,我想,问题是Chrome特有的,并尝试在Firefox中运行...
...元素没有出现的地方。
编辑:太棒了,所以将它包装在div中并不能保证它显示出来。但是,在Chrome开发者工具中进行“编辑为HTML”确实会显示出来。
编辑:嗯,我已经让它正常工作了,是的,结果证明它是创建DOM元素的Javascript的一个功能。代码中有很多东西,但我可以把它归结为:
此代码有效(createElement根据传入的参数创建标记并设置属性):
var div = this.createElement(
'div',
element_name + '_div',
null, style_options, null, null
);
div.innerHTML = [
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width=' + width + ' height=' + height + '>',
svg_xml.join(''),
'</svg>'
].join('');
if (parent) parent.appendChild(div);
return div;
此代码不会:
var svg = this.createElement('svg', element_name, null, style_options, classlist, {
viewport: '0 0 ' + width + ' ' + height,
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
width: width,
height: height
});
svg.innerHTML = svg_xml.join('');
if (parent) parent.appendChild(svg);
return svg;
所以,当然,我现在有一些工作,但我不明白为什么。或者更重要的是,我不明白为什么一种方式有效而另一种方式无效。我有几个猜测,但它们只是猜测,真的。
答案 0 :(得分:17)
&#34;我现在有一些工作,但我不明白为什么。&#34;
问题是您使用的方法不会在SVG名称空间中创建SVG元素。 xmlns
属性仅影响XML解析器的行为,而不影响DOM方法的行为。
我不确定您使用多个参数的this.createElement()
方法使用哪个库。但是,我怀疑它可能是从调用基本的document.createElement(tagName)
方法开始的。这就是MDN says about the standard DOM createElement
method:
在HTML文档中创建指定的HTML元素,如果元素未知,则创建
HTMLUnknownElement
。 ...在其他文档中创建一个null namespaceURI的元素。
换句话说,因为您(大概是间接地)在HTML文档上调用createElement
,所以它总是会创建一个HTML元素。标签名为&#34; svg&#34;的HTML元素被视为未知的跨式元素。
相反,使用div.innerHTML
传递标记字符串会正确创建SVG元素,因为它会调用HTML5解析器来确定要创建的元素类型。使用与从文件解析标记时相同的规则来确定命名空间。在Chrome开发者工具中编辑HTML具有相同的效果。
旁注: 避免在SVG元素上调用.innerHTML
。有些浏览器支持它,但它不是规范的一部分。您没有收到错误,因为您的svg
变量实际上是HTMLUnknownElement
的实例。将SVG代码传递给父innerHTML
的{{1}}方法通常有效,尽管SMIL动画存在一些错误。正如@Robert Longson在评论中所说,您可以使用DOMParser object将HTML或XML代码解析为文档。
动态创建SVG元素的另一种方法是使用<div>
。您还必须使用此方法来创建SVG的所有子元素。创建它们后,您可以使用库方法设置属性,样式和类。 (但是你还没有指定你正在使用的库,所以我不确定。)