【问题标题】:Modifying Raphael SVG image with jQuery使用 jQuery 修改 Raphael SVG 图像
【发布时间】:2011-10-03 23:59:05
【问题描述】:

我有一个小应用程序,我需要在其中为弧生成 textPath 标签。我正在通过 Raphael 绘制弧线,效果很好。但是 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);
                };

我得到一个 0x0 的 textPath 边界框,但没有 textPath。

【问题讨论】:

    标签: jquery svg raphael


    【解决方案1】:

    您可能需要删除第一个示例中出现的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:但是,它仍然无法正确绘制,这很奇怪。

    【讨论】:

    • 啊。不知何故没有注意到这一点。在有效的示例中,您拥有&lt;textPath xlink:href="#Arc"&gt;This is an Arc&lt;/textPath&gt; ,而在无效的示例中,您拥有&lt;textpath xlink:href="#This_is_a_test_entry"&gt;This is a test entry&lt;/textpath&gt; `。第二个中的元素名称不同(全部小写而不是驼峰式)。我假设 SVG 在这里是区分大小写的。
    • 你一开始是对的。我修复了我的帖子以反映实际代码,不确定错字来自哪里。我已经用一个单词 id 尝试过它,但由于某种原因它仍然没有呈现。我唯一能确定的不同之处在于,Raphael 附加到未完全渲染的 svg 而不是另一个。
    • @LeakyBucket,你错过了 Femi 的编辑吗?正如他所说,应该是textPath(注意大写P)。
    • 啊,是的,我做到了。我必须弄清楚如何让 jQuery 正确命名元素。但是,我只使用 jQuery 设置了另一个测试,并且路径在添加时也不会呈现,所以我不确定是否会修复它。不过我一定会试一试的。
    • 是的,它也不适合我。虽然我现在得到了一个 0x0 的边界框,这是一个改进。我怀疑这是因为您无法在 Raphael 中分配 id 而我做得不对。我必须弄清楚这一点。
    【解决方案2】:

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

    如果您希望在路径上显示文本而不用每个字母都弄脏曲线,那么您可以继续使用 Rap 并使用它...http://irunmywebsite.com/raphael/additionalhelp.php?v=1&q=anglebannersoncurves

    请原谅拼写 iPod 新手

    【讨论】:

    • 目前还不确定浏览器的要求是什么。我们的营销部门已要求这样做,因此我们可能不得不就该细节进行“谈判”。我不确定 jQuery SVG 插件是否仍然存在或当前。我找不到比 2008 年更新的任何信息,而且它的谷歌代码网站没有任何文件。
    • 是的,很遗憾,这不适用于此应用程序。不过,似乎还有其他事情发生。无论我是否使用 Raphael,我都无法获得 svg 更改来渲染。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      我无法弄清楚根本原因,但它一定是 Raphael 的核心部分阻止了 SVG 画布更新,因为修复绘图所需要做的就是通过快速删除然后读取来强制重绘来自 DOM 的 svg 元素:

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

      应该注意的是,任何对 SVG 属性的直接攻击都会破坏与使用 VML 的浏览器(sigh、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());
      

      【讨论】:

      • 是的,那个补丁很有魅力!请注意,为文本路径设置动画将需要您为路径元素设置动画,而不是 Raphael.textPath() 返回的文本元素。您可以通过返回元素的“.path”属性访问它。我会投票,但我的声誉不会让我:p
      • 是的,最后我只是为每个标签制作了另一个路径,并将标签绑定到在 defs 部分中生成但未渲染的路径。
      猜你喜欢
      • 2012-10-02
      • 2023-01-29
      • 1970-01-01
      • 1970-01-01
      • 2011-08-04
      • 2023-03-05
      • 2017-06-10
      • 2012-08-12
      相关资源
      最近更新 更多