使用jQuery修改Raphael SVG图像

时间:2011-07-12 20:52:39

标签: jquery svg raphael

我有一个小应用程序,我需要为弧生成textPath标签。我正在通过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。

4 个答案:

答案 0 :(得分:3)

您可能需要删除第一个示例中显示的xlink,或添加相应的XML命名空间定义。

编辑:当您添加textPath元素时,您可能需要使用正确的元素名称(textPath,而不是textpath)。

编辑:中等有趣,因为它是浏览器和jQuery改变路径的组合。要获得正确的事物,请使用此功能(从jquery's append not working with svg element?的答案中解放出来):

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;
 }

然后这样做:

var paper = Raphael("notepad", 320, 200);

// do all your other stuff here
...

var text = makeSVG("text", {});
       var c = makeSVG("textPath", {"xlink:href":"#Arc"});
       c.appendChild(document.createTextNode("This is an Arc"));
       text.appendChild(c);
paper.canvas.appendChild(text);

这会让你得到正确的SVG:但是,它仍然不能正确绘制,这很奇怪。

答案 1 :(得分:2)

如果你不担心你的工作不在ie8或更早的工作,为什么不使用支持textpath的kieth wood的jquery SVG插件 该插件的路径语法不同,但很容易从Raphael转换 SVG插件提供了漂亮的径向渐变,但这就是我现在参与其中的原因。

如果你想要一条路径上的文字,而不是每个字母的曲线,那么你可以留下Rap并使用它...... http://irunmywebsite.com/raphael/additionalhelp.php?v = 1&amp; q = anglebannersoncurves

借口拼写iPod新手

答案 2 :(得分:1)

Femi的答案非常好,唯一缺少的是让它重绘并设置xlink命名空间。

我无法弄清楚潜在的原因,但它必须是Raphael核心中阻止SVG画布更新的东西,因为你需要做的就是通过快速删除然后重新读取来强制重绘来自DOM的svg元素:

$('#myRaphaelDiv').html($('#myRaphaelDiv').html());

应该注意的是,任何直接入侵SVG属性都会破坏与使用VML的浏览器(叹气,IE)的兼容性。我还没有研究在VML中进行文本路径的方法。以下代码是为了完整性。

// add the new namespace attribute to the SVG canvas. 'raphael' is the Raphael instance.
// note that this only needs to be done once.
$(raphael.canvas).attr('xmlns:xlink', "http://www.w3.org/1999/xlink");

// draw the curved text
var lblId = 'some_unique_dom_id';
var path = raphael.path().attr({
    stroke : 'none' // defaults to black
    // ...other path attributes used in generating it...
});
var label = raphael.text().attr({ 'text-anchor' : 'start' });

// create and inject raw SVG textPath element
var link;
try {
    link = document.createElementNS('http://www.w3.org/2000/svg', 'textPath');
} catch (e) {
    // no createElementNS() method is pretty much synonymous with using IE, so
    // this is where you would do your VML version of a text path
    alert("Your browser does not support SVG, please use Firefox, Chrome etc");
}
link.setAttribute('xlink:href', '#' + lblId);
link.appendChild(document.createTextNode("path-oriented text"));

// finally, force a redraw of the SVG document. 
// Obviously, you would defer this until all elements had been added.
$('#myRaphaelDiv').html($('#myRaphaelDiv').html());

答案 3 :(得分:0)

因此,在找到Raphael here的补丁并对补丁进行小调整后,它正在运行。我仍然不确定我错过了什么,但textPaths现在呈现,每个人都很高兴。感谢大家的帮助。