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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8053487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:32:16  来源:igfitidea点击:

Scripting <path> data in SVG (reading and modifying)

javascriptgraphicssvgscalable

提问by Lei Leyba

Can anyone really really help me, please? I've been searching for ways to run scripts for my SVG. But all the things i got doesn't match up! And it doesn't contain enough information why he used that set of codes. For example, one used event.target, another had event.getTarget(), and another had event.target.firstchild.data. Can anyone help me, please?

真的有人能帮我吗?我一直在寻找为我的 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>

is an example of a path svg right? What i need is to get those coordinates, probably put it in a variable, and use it as coordinates for another svg. So how can i do that? Another thing is how can i change those coordinates by entering numbers in an interface.

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

So i tried to look for answers, but like i said, i didn't find the info i needed or maybe i just didn't i understand what it showed me.

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

回答by Phrogz

It sounds like you may have four questions:

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

  1. How do I embed script inside an SVG file?
  2. How do I run script inside an SVG file?
  3. How do I access data for a <path>element from script?
  4. How can I manipulate data for a <path>element from script?
  1. 如何在 SVG 文件中嵌入脚本?
  2. 如何在 SVG 文件中运行脚本?
  3. 如何<path>从脚本访问元素的数据?
  4. 如何<path>从脚本操作元素的数据?

Let's tackle them one at a time:

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



How do I embed script inside an SVG file?

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

As described in the SVG specificationyou can place a <script>element in your document to contain JavaScript code. According to the latest SVG specifications, you do not need to specify a typeattributefor your script. It will default to type="application/ecmascript".

SVG 规范中所述,您可以<script>在文档中放置一个元素以包含 JavaScript 代码。根据最新的 SVG 规范,您无需type为脚本指定属性。它将默认为type="application/ecmascript".

  • Other common mime types include "text/javascript", "text/ecmascript"(specified in SVG 1.1), "application/javascript", and "application/x-javascript". I do not have detailed information on browser support for all of these, or for omitting the typeattribute altogether. I have always had good success with text/javascript.
  • 其他常见的 mime 类型包括"text/javascript", "text/ecmascript"(在 SVG 1.1 中指定)"application/javascript"、 和"application/x-javascript"。我没有关于浏览器支持所有这些或type完全省略属性的详细信息。我一直很成功text/javascript

As with HTML, you may either put the script code directly in the document, or you may reference an external file. When doing the latter, you must use an hrefattribute (not src) for the URI, with the attribute in the xlinknamespace.

与 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>


How do I run script inside an SVG file?

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

As with HTML, code included in your SVG document will be run as soon as it is encountered. If you place your <script>element above the rest of your document (as you might when putting <script>in the <head>of an HTML document) then none of your document elements will be available when your code is running.

与 HTML 一样,SVG 文档中包含的代码将在遇到时立即运行。如果您将<script>元素放置<script>在文档的其余部分之上(就像您将<head>.

The simplest way to avoid this is to place your <script>elements at the bottom of your document:

避免这种情况的最简单方法是将<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>

Alternatively, you can create a callback function at the top of your document that is only invoked when the rest of the document is ready:

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

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


How do I access data for a <path>element from script?

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

There are two ways to access most information about elements in SVG: you can either access the attribute as a string through the standard DOM Level 1 Core method getAttribute(), or you can use the SVG DOM objects and methods. Let's look at both:

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

Accessing path data through getAttribute()

通过访问路径数据 getAttribute()

Using getAttribute()returns the same string as you would see when you view source:

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

<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>
  • Pros: very simple to call; you don't have to know anything about the SVG DOM
  • Con: since you get back a string you have to parse the attribute yourself; for SVG <path>data, this can be excruciating.
  • 优点:调用非常简单;你不必了解 SVG DOM
  • 缺点:因为你得到一个字符串,你必须自己解析属性;对于 SVG<path>数据,这可能会令人难以忍受。

Accessing path data through SVG DOM methods

通过 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>

The above script produces the following output:

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

Move to 150 0
Line to 75 200
Line to 225 200
Close Path
  • Pros: path data is parsed for you; you get exact numbers from the API itself; using normalizedPathSegListtakes relative commands and makes them absolute for you; if SMIL animation is changing the path data, using the non-animated pathSegList can give you access to the base, non-animated information not available via getAttribute().

  • Cons: Sweet chimpunks a-flame, look at that code! And that doesn't even handle all the possible path segments available.

  • 优点:为您解析路径数据;您可以从 API 本身获得确切的数字;usingnormalizedPathSegList接受相对命令并使它们对你来说是绝对的;如果 SMIL 动画正在更改路径数据,则使用非动画 pathSegList 可以让您访问无法通过getAttribute().

  • 缺点:甜蜜的黑猩猩着火了,看看那个代码!这甚至无法处理所有可能的可用路径段。

Because it can be hard to read the W3C specs for SVG DOM, many years ago I created an online tool for browsing what properties and objects exist. You may use it here: http://objjob.phrogz.net/svg/hierarchy

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



How can I manipulate data for a <path>element from script

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

Similar to the above, you can either create a new string and use setAttribute()to shove it onto the object, or you can manipulate the SVG DOM.

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

Manipulating path data using setAttribute()

使用路径数据操作 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>

Manipulating path data using SVG DOM

使用 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>

In general, you just have to modify the properties of the various SVGPathSegsubclass instances; the changes are made immediately in the DOM. (With the above example, the original triangle is skewed as the last point is moved up slightly.)

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

When you need to create new path segments, you need to use methods like var newSegment = myPath.createSVGPathSegArcAbs(100,200,10,10,Math.PI/2,true,false)and then use one of the methods to stick this segment into the list, e.g. segments.appendItem(newSegment).

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

回答by Godly Mathew

Dynamic Path elements in SVG with Javascript and Css support

具有 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

在 jsfiddle 中演示