使用 jQuery 修改 Raphael SVG 图像
我有一个小型应用程序,需要为弧生成文本路径标签。我通过拉斐尔绘制弧线,效果很好。然而 Raphael 不支持 textPaths。我们可以通过 jQuery 将它们添加到 svg 元素,但由于某种原因它们不会渲染。当我静态复制动态生成的代码时,它呈现得很好。
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="600">
<desc>Created with Raphaël</desc><defs></defs>
<a title="This is a test entry">
<path fill="none" stroke="#1e79a0" d="M395.2627944162883,355A110,110,0,0,1,199.5099996593139,344.74103073833805" style="stroke-width: 20px; " stroke-width="20" id="This_is_a_test_entry"></path>
</a>
<text>
<textpath xlink:href="#This_is_a_test_entry">This is a test entry</textpath>
</text>
</svg>
使用上面的代码,您永远不会看到弧的标签。然而,当以下内容被硬编码时,它会按预期呈现:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="600">
<a title="Bacon">
<path id="Arc" fill="none" stroke="#1e79a0" d="M395.2627944162883,355A110,110,0,0,1,201.13265490709162,348.2208261467985" style="stroke-width: 20;" stroke-width="20">
</path>
</a>
<text>
<textPath xlink:href="#Arc">This is an Arc</textPath>
</text>
</svg>
任何关于为什么我没有看到我的整个 svg 的见解将不胜感激。
编辑:
我已经对我的 javascript 进行了更改,我认为它几乎就在那里,但 textPath 仍然不会呈现。这是当前的代码,主要感谢 Femi:
function drawRange(start, end, R, range, id, title) {
var color = "hsb(".concat(Math.round(R) / 200, ",", end / 360, ", .75)");
var key_position = key[id];
var svg_bits = document.getElementsByTagName('svg')[0].childNodes;
var svgns = document.createElementNS('http://www.w3.org/2000/svg', "path");
var path;
range.attr({title: title});
range.animate({arc: [start, end, R]}, 900, ">");
//Add an id to the path element that was just drawn. This doesn't seem to help though.
for(var i = 0; i < svg_bits.length; i++) {
if (svg_bits[i].tagName == "a" && svg_bits[i].getAttribute('title') == title){
path = svg_bits[i].childNodes[0];
}
}
path.setAttribute('id', title);
//Add the name to the key, set the color and unhide the element.
$(key_position).html(range.attr("title"));
$(key_position).css('color', Raphael.getRGB(color).hex);
$(key_position).show();
};
function makeSVG(tag, attrs) {
var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (var k in attrs)
el.setAttribute(k, attrs[k]);
return el;
};
function addLabel(label) {
var text = makeSVG("text", {});
var title = makeSVG("textPath", {"xlink:href":'#' + label.replace(/\s/g, '_')});
title.appendChild(document.createTextNode(label));
text.appendChild(title);
r.canvas.appendChild(text);
};
我得到了 textPath 的边界框 0x0,但没有 textPath。
I have a small application where I need to generate textPath labels for arcs. I'm drawing the arcs via Raphael and that is working great. However Raphael has no support for textPaths. We can add them to the svg element via jQuery but they don't render for some reason. When I duplicate the dynamically generated code statically it renders fine.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="600">
<desc>Created with Raphaël</desc><defs></defs>
<a title="This is a test entry">
<path fill="none" stroke="#1e79a0" d="M395.2627944162883,355A110,110,0,0,1,199.5099996593139,344.74103073833805" style="stroke-width: 20px; " stroke-width="20" id="This_is_a_test_entry"></path>
</a>
<text>
<textpath xlink:href="#This_is_a_test_entry">This is a test entry</textpath>
</text>
</svg>
With the above code you never see the label for the arc. However when the following is hard coded it renders as expected:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="600">
<a title="Bacon">
<path id="Arc" fill="none" stroke="#1e79a0" d="M395.2627944162883,355A110,110,0,0,1,201.13265490709162,348.2208261467985" style="stroke-width: 20;" stroke-width="20">
</path>
</a>
<text>
<textPath xlink:href="#Arc">This is an Arc</textPath>
</text>
</svg>
Any insight as to why I'm not seeing my entire svg would be much appreciated.
EDIT:
I've made changes to my javascript and I think it's almost there but the textPath still won't render. Here is the current code, mostly thanks to Femi:
function drawRange(start, end, R, range, id, title) {
var color = "hsb(".concat(Math.round(R) / 200, ",", end / 360, ", .75)");
var key_position = key[id];
var svg_bits = document.getElementsByTagName('svg')[0].childNodes;
var svgns = document.createElementNS('http://www.w3.org/2000/svg', "path");
var path;
range.attr({title: title});
range.animate({arc: [start, end, R]}, 900, ">");
//Add an id to the path element that was just drawn. This doesn't seem to help though.
for(var i = 0; i < svg_bits.length; i++) {
if (svg_bits[i].tagName == "a" && svg_bits[i].getAttribute('title') == title){
path = svg_bits[i].childNodes[0];
}
}
path.setAttribute('id', title);
//Add the name to the key, set the color and unhide the element.
$(key_position).html(range.attr("title"));
$(key_position).css('color', Raphael.getRGB(color).hex);
$(key_position).show();
};
function makeSVG(tag, attrs) {
var el = document.createElementNS('http://www.w3.org/2000/svg', tag);
for (var k in attrs)
el.setAttribute(k, attrs[k]);
return el;
};
function addLabel(label) {
var text = makeSVG("text", {});
var title = makeSVG("textPath", {"xlink:href":'#' + label.replace(/\s/g, '_')});
title.appendChild(document.createTextNode(label));
text.appendChild(title);
r.canvas.appendChild(text);
};
I get a bounding box of 0x0 for the textPath but no textPath.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可能需要删除第一个示例中出现的
xlink
,或者添加适当的 XML 命名空间定义。编辑:当您添加
textPath
元素时,您可能需要使用正确的元素名称(textPath
,而不是textpath
)。编辑:相当有趣,因为它是浏览器和 jQuery 改变路径的组合。要获得正确的东西,请使用此函数(从jquery 的追加不适用于 svg 元素?):
然后执行以下操作:
这将为您提供正确的 SVG:但是,它仍然无法正确绘制,这很奇怪。
You may need to either remove the
xlink
that appears in the first sample, or add the appropriate XML namespace definition.EDIT: when you are adding the
textPath
element you may need to use the correct element name (textPath
, nottextpath
).EDIT: moderately interesting, as it is combination of the browser and jQuery changing the path. To get the right thing, use this function (liberated from the answer to jquery's append not working with svg element?):
And then do this:
That will get you the right SVG: however, it still won't draw right, which is odd.
如果您不担心您的工作无法在 ie8 或更早版本中运行,为什么不使用 kieth wood 的支持 textpath 的 jquery SVG 插件
该插件的路径语法不同,但很容易从 Raphael 转换
SVG 插件提供了美丽的径向渐变,但这就是我现在参与其中的原因。
如果你想要路径上的文本而不是每个字母都沿着曲线走,那么你可以继续使用 Rap 并使用这个...http://irunmywebsite.com/raphael/additionalhelp.php?v=1&q=anglebannersoncurves
请原谅拼写 iPod新手
If your not worried about your work not working in ie8 or earlier why not use kieth wood's jquery SVG plugin that supports textpath
The path syntax for the plugin is different but easy to convert from Raphael
The SVG plugin delivers beautiful radial gradients but this is why I am involved with it now.
If you want text on a path without gollowing the curve with every letter then you could stay with Rap and use this...http://irunmywebsite.com/raphael/additionalhelp.php?v=1&q=anglebannersoncurves
Excuse spelling iPod newbie
Femi 的答案非常好,唯一缺少的是重绘和设置 xlink 命名空间。
我无法弄清楚根本原因,但它一定是 Raphael 核心中的某些东西阻止了 SVG 画布更新,因为修复绘图所需要做的就是通过快速删除然后读取 svg 元素来强制重绘来自 DOM:
应该注意的是,任何对 SVG 属性的直接攻击都会破坏与使用 VML 的浏览器(叹息,IE)的兼容性。我还没有研究过在 VML 中处理文本路径的方法。下面的代码是为了完整性。
Femi's answer is pretty good, the only things missing are getting it to redraw and setting the xlink namespace.
I can't figure out the underlying reason, but it must be something in the core of Raphael that prevents the SVG canvas from updating, since all you need to do to fix drawing is force a redraw by quickly removing and then readding the svg element from the DOM:
It should be noted that any direct hacking of SVG attributes will break compatibility with browsers (sigh, IE) that use VML instead. I've yet to look into a way of doing text paths in VML. Code below is for completeness.
因此,在此处找到 Raphael 的补丁并对补丁进行一些小调整后,它是在职的。我仍然不确定我错过了什么,但 textPaths 现在呈现,每个人都很高兴。感谢大家的帮助。
So, after finding a patch to Raphael here and making a small tweak to the patch it is working. I'm still not sure what I was missing but the textPaths now render and everyone is happy. Thanks to everyone for the help.