【问题标题】:Scripting <path> data in SVG (reading and modifying)在 SVG 中编写 <path> 数据脚本(读取和修改)
【发布时间】:2011-11-08 16:11:04
【问题描述】:

请问有人真的可以帮助我吗? 我一直在寻找为我的 SVG 运行脚本的方法。 但是我得到的所有东西都不匹配!它没有包含足够的信息,为什么他使用了那组代码。例如,一个使用 event.target,另一个使用 event.getTarget(),另一个使用 event.target.firstchild.data。 谁能帮帮我?

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <path d="M150 0 L75 200 L225 200 Z" />
</svg>

是路径 svg 的示例,对吗?我需要的是获取这些坐标,可能将其放入变量中,并将其用作另一个 svg 的坐标。那么我该怎么做呢?另一件事是如何通过在界面中输入数字来更改这些坐标。

所以我试图寻找答案,但就像我说的那样,我没有找到我需要的信息,或者我只是不明白它向我展示了什么。

【问题讨论】:

  • 您需要就您的问题提供更多信息。你的问题具体是什么?你想要完成什么,你的代码是什么,你看到的结果是什么?您是否只是在寻找任何显示脚本工作的 SVG 模板?您是在 XHTML 中嵌入 SVG,还是这是一个独立的 SVG 文件?等

标签: javascript graphics svg scalable


【解决方案1】:

听起来您可能有四个问题:

  1. 如何在 SVG 文件中嵌入脚本?
  2. 如何在 SVG 文件中运行脚本?
  3. 如何从脚本访问 &lt;path&gt; 元素的数据?
  4. 如何从脚本中操作 &lt;path&gt; 元素的数据?

让我们一次解决一个问题:


如何在 SVG 文件中嵌入脚本?

the SVG specification 中所述,您可以在文档中放置&lt;script&gt; 元素以包含JavaScript 代码。根据最新的 SVG 规范,you do not need to specify a type attribute 为您的脚本。它将默认为type="application/ecmascript"

  • 其他常见的 mime 类型包括 "text/javascript""text/ecmascript"(在 SVG 1.1 中指定)、"application/javascript""application/x-javascript"。我没有关于浏览器支持所有这些的详细信息,或者完全省略type 属性。我在text/javascript 上一直很成功。

与 HTML 一样,您可以将脚本代码直接放在文档中,也可以引用外部文件。执行后者时,您必须为 URI 使用 href 属性(而不是 src),并且该属性位于 xlink 命名空间中。

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <script xlink:href="/js/mycode.js" />
  <script><![CDATA[
    // Wrap the script in CDATA since SVG is XML and you want to be able to write
    // for (var i=0; i<10; ++i )
    // instead of having to write
    // for (var i=0; i&lt;10; ++i )
  ]]></script>
</svg>

如何在 SVG 文件中运行脚本?

与 HTML 一样,包含在 SVG 文档中的代码将在遇到时立即运行。如果您将 &lt;script&gt; 元素放在文档的其余部分之上(就像将 &lt;script&gt; 放在 HTML 文档的 &lt;head&gt; 中一样),那么当您的代码运行时,您的任何文档元素都将不可用。

避免这种情况的最简单方法是将&lt;script&gt; 元素放在文档底部:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <!-- all SVG content here, above the script -->
  <script><![CDATA[
    // Now I can access the full DOM of my document
  ]]></script>
</svg>

或者,您可以在文档顶部创建一个回调函数,该函数仅在文档的其余部分准备好时调用:

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
  <title>SVG Coordinates for Embedded XHTML Elements</title>
  <script>document.documentElement.addEventListener('load',function(){
    // This code runs once the 'onload' event fires on the root SVG element
    console.log( document.getElementById('foo') );
  },false)</script>
  <path id="foo" d="M0 0" />
</svg>

如何从脚本中访问 &lt;path&gt; 元素的数据?

有两种方法可以访问有关 SVG 中元素的大多数信息:您可以通过标准 DOM 级别 1 核心方法 getAttribute() 以字符串形式访问属性,或者您可以使用 SVG DOM objects and methods。让我们看看两者:

通过getAttribute()访问路径数据

使用getAttribute() 返回的字符串与查看源代码时看到的字符串相同:

<path id="foo" d="M150 0 L75 200 L225 200 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');
  var data = path.getAttribute('d');
  console.log(data);
  //-> "M150 0 L75 200 L225 200 Z"
]]></script>
  • 优点:调用非常简单;您无需了解 SVG DOM
  • Con:因为你得到一个字符串,你必须自己解析属性;对于 SVG &lt;path&gt; 数据,这可能非常痛苦。

通过 SVG DOM 方法访问路径数据

<path id="foo" d="M150 0 L75 200 L225 200 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');

  // http://www.w3.org/TR/SVG/paths.html#__svg__SVGAnimatedPathData__normalizedPathSegList
  // See also path.pathSegList and path.animatedPathSegList and path.animatedNormalizedPathSegList
  var segments = path.normalizedPathSegList ;

  for (var i=0,len=segments.numberOfItems;i<len;++i){
    var pathSeg = segments.getItem(i);
    // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSeg
    switch(pathSeg.pathSegType){
      case SVGPathSeg.PATHSEG_MOVETO_ABS:
        // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSegMovetoAbs
        console.log("Move to",pathSeg.x,pathSeg.y);
      break;
      case SVGPathSeg.PATHSEG_LINETO_ABS:
        // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSegLinetoAbs
        console.log("Line to",pathSeg.x,pathSeg.y);
      break;
      case SVGPathSeg.PATHSEG_CLOSEPATH:
        // http://www.w3.org/TR/SVG/paths.html#InterfaceSVGPathSegClosePath
        console.log("Close Path");
      break;
    }
  }
]]></script>

以上脚本产生以下输出:

Move to 150 0
Line to 75 200
Line to 225 200
Close Path
  • 优点:为您解析路径数据;您可以从 API 本身获得准确的数字; using normalizedPathSegList 接受相对命令并使它们对您来说是绝对的;如果 SMIL 动画正在更改路径数据,则使用非动画 pathSegList 可以让您访问通过 getAttribute() 无法获得的基本非动画信息。

  • 缺点:可爱的黑猩猩,看看那个代码!这甚至不能处理所有可能的路径段。

因为很难阅读 SVG DOM 的 W3C 规范,所以多年前我创建了一个在线工具来浏览存在的属性和对象。你可以在这里使用它:http://objjob.phrogz.net/svg/hierarchy


如何从脚本中操作 &lt;path&gt; 元素的数据

与上述类似,您可以创建一个新字符串并使用setAttribute() 将其推送到对象上,也可以操作 SVG DOM。

使用setAttribute()处理路径数据

<path id="foo" d="M150 0 L75 200 L225 200 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');
  path.setAttribute('d','M150,0 L150,100 200,300 Z');
]]></script>

使用 SVG DOM 操作路径数据

<path id="foo" d="M150,0 L75,200 l150,0 Z" />
<script><![CDATA[
  var path = document.getElementById('foo');
  var segments = path.pathSegList;
  segments.getItem(2).y = -10;
]]></script>

一般来说,你只需要修改各种SVGPathSeg子类实例的属性即可;更改会立即在 DOM 中进行。 (在上面的例子中,原来的三角形是倾斜的,因为最后一点稍微向上移动。)

当您需要创建新的路径段时,您需要使用var newSegment = myPath.createSVGPathSegArcAbs(100,200,10,10,Math.PI/2,true,false) 之类的方法,然后使用其中一种方法将此段粘贴到列表中,例如segments.appendItem(newSegment).

【讨论】:

【解决方案2】:

支持 Javascript 和 Css 的 SVG 中的动态路径元素

var XMAX = 500;
    var YMAX = 500;
    var _xx=10;
    var _reg=100;
    var _l=10;
    // Create PATH element
    for(var x=1;x<20;x++)
    {
    var pathEl = document.createElementNS("http://www.w3.org/2000/svg", "path");
    pathEl.setAttribute('d','M'+_l+' 100 Q 100  300 '+_l+' 500' );
    pathEl.style.stroke = 'rgb('+(_reg)+',0,0)';
    pathEl.style.strokeWidth = '5';
    pathEl.style.fill = 'none';
        $(pathEl).mousemove(function(evt){$(this).css({"strokeWidth":"3","stroke":"#ff7200"}).hide(100).show(500).css({"stroke":"#51c000"})});

    document.querySelector('svg').appendChild(pathEl);
    _l+=50;
    }

Demo in jsfiddle

【讨论】:

  • 一个奇怪的例子,但我会接受它。
  • 同意@Kennedy... 这个例子有一些好处,但它有点古怪(XMAXYMAX_xx 是什么?为什么是 svg 元素没有用边界框声明?所以我们得到了一个默认的 300x150 视图,显示了那些很酷的二次曲线的几乎线性的部分......)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
  • 2012-11-01
相关资源
最近更新 更多