我正在尝试用knockoutJS动态地呈现一些SVG。换句话说,ajax响应将带着有效的SVG返回,我希望svgweb动态显示它。
Note -这个问题是用你自己的问题回答的,所以我希望能给下一个人留出一个小时左右的搜索时间。
发布于 2013-10-12 20:05:25
正如在这个答案中所描述的,您需要使用svgweb公开的appendChild方法。请注意,它接受一个实际的节点,而不仅仅是文本。
为了简单起见,您可以去掉来自ajax响应的任何<xml>或<doctype>节点。然后,在用jQuery包装剥离的文本之后,结果的第0‘节点应该是一个有效的svg节点,可以传递给appendChild。
下面的敲除扩展结束了这个功能。
ko.bindingHandlers.renderSvg = {
init: renderSvg,
update: renderSvg
};
function renderSvg(element, valueAccessor, allBindingsAccessor, viewModel) {
var rawVal = valueAccessor();
var svgText = ko.utils.unwrapObservable(rawVal);
if (!svgText) {
element.innerHTML = '';
} else {
//clear out previous content
element.innerHTML = '';
//strip out any `<xml>` or <!doctype> tags that come over
if (svgText.indexOf('<svg') > 0){
svgText = svgText.substr(svgText.indexOf('<svg'));
}
window.svgweb.appendChild($(svgText)[0], element);
}
};当然,它的名称是:
<div data-bind="renderSvg: mySvgField"></div>编辑
结果是用jQuery包装SVG字符串,并试图附加结果会导致问题。我发现的修复方法是用jQuery包装父jQuery,然后使用jQuery循环所有子节点。一个简单的1级搜索对我来说就足够了。显然,更复杂的用例需要递归搜索。更新后的代码如下。
function renderSvg(element, valueAccessor, allBindingsAccessor, viewModel) {
var rawVal = valueAccessor();
var svgText = ko.utils.unwrapObservable(rawVal);
if (!svgText) {
element.innerHTML = '';
} else {
element.innerHTML = '';
if (svgText.indexOf('<svg') > 0){
svgText = svgText.substr(svgText.indexOf('<svg'));
}
if (!$.browser.msie || $.browser.version > 8){
//normal browsers
window.svgweb.appendChild($(svgText)[0], element);
} else {
//IE 8
var $svg = $(svgText);
var svg = document.createElementNS(svgns, 'svg');
svg.setAttribute('width', $svg.attr('width'));
svg.setAttribute('height', $svg.attr('height'));
$.each($svg.children(), function(i, el){
var path = document.createElementNS(svgns, el.tagName);
for (var i = 0, allAttributes = el.attributes, len = allAttributes.length; i < len; i++){
path.setAttribute(allAttributes.item(i).nodeName, allAttributes.item(i).nodeValue);
}
svg.appendChild(path);
});
window.svgweb.appendChild(svg, element);
}
}
}https://stackoverflow.com/questions/19338662
复制相似问题