在SVG中编写<path>数据(读取和修改)

Lei*_*yba 28 javascript graphics svg scalable

有人真的可以帮助我吗?我一直在寻找为我的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>
Run Code Online (Sandbox Code Playgroud)

是svg路径的一个例子吗?我需要的是得到那些坐标,可能把它放在一个变量中,并用它作为另一个svg的坐标.那我该怎么做呢?另一件事是我如何通过在界面中输入数字来更改这些坐标.

所以我试图寻找答案,但就像我说的,我没有找到我需要的信息,或者我只是不知道它给我的信息.

Phr*_*ogz 99

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

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

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


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

SVG规范中所述,您可以<script>在文档中放置一个元素以包含JavaScript代码.根据最新的SVG规范,您无需type为脚本指定属性.它将默认为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>
Run Code Online (Sandbox Code Playgroud)

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

与HTML一样,SVG文档中包含的代码将在遇到时立即运行.如果你把你的<script>元素你的文档的其余部分上面(正如你可能时,把<script><head>HTML文档的),那么不关你的文档元素会在你的代码运行时可用.

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

<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>
Run Code Online (Sandbox Code Playgroud)

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

<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>
Run Code Online (Sandbox Code Playgroud)

如何<path>从脚本访问元素的数据?

有两种方法可以访问SVG中有关元素的大部分信息:您可以通过标准DOM Level 1 Core方法将该属性作为字符串访问getAttribute(),也可以使用SVG DOM对象和方法.让我们看看两者:

通过访问路径数据 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>
Run Code Online (Sandbox Code Playgroud)
  • 优点:打电话很简单; 您不必了解SVG DOM的任何信息
  • Con:因为你得到一个字符串,你必须自己解析属性; 对于SVG <path>数据,这可能是令人难以忍受的.

通过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>
Run Code Online (Sandbox Code Playgroud)

上面的脚本产生以下输出:

Move to 150 0
Line to 75 200
Line to 225 200
Close Path
Run Code Online (Sandbox Code Playgroud)
  • 优点:为您解析路径数据; 你从API本身得到确切的数字; 使用normalizedPathSegList相对命令并使它们绝对适合你; 如果SMIL动画正在更改路径数据,则使用非动画pathSegList可以访问不可用的基本非动画信息getAttribute().

  • 缺点:甜蜜的黑猩猩火焰,看看那个代码!而这甚至不能处理所有可用的路径段.

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


如何<path>从脚本中操作元素的数据

与上面类似,您可以创建一个新字符串并使用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>
Run Code Online (Sandbox Code Playgroud)

使用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>
Run Code Online (Sandbox Code Playgroud)

通常,您只需修改各种SVGPathSeg子类实例的属性; 更改将立即在DOM中进行.(在上面的示例中,原始三角形倾斜,因为最后一点略微向上移动.)

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

  • 已弃用的 SVG pathSegList 的替代方案:http://stackoverflow.com/questions/34352624/alternative-for-deprecated-svg-pathseglist (2认同)
  • 建议使用新的getPathData和setPathData API而不是旧的pathSegList API.新API效率更高,可用性更高.使用[path data polyfill](https://github.com/jarek-foksa/path-data-polyfill.js)处理新API. (2认同)

小智 5

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

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;
    }
Run Code Online (Sandbox Code Playgroud)

在jsfiddle演示

  • 一个奇怪的例子,但我会接受它. (2认同)