32

Here is the SVG path:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="sss" viewBox="0 0 500 300">
  <path id="s3" d="M 10,90 Q 100,15 200,70 Z"/>
</svg>

How can I change the d value?

Why does alert(document.getElementById('s3').d); give me undefined?

BarryCap
  • 326
  • 3
  • 11
Victor Marchuk
  • 13,045
  • 12
  • 43
  • 67

4 Answers4

35

Attributes can be set another way:

alert(document.getElementById('s3').getAttribute('d'));

That seems to work. To set use setAttribute.

There is a difference between attributes and properties. Attributes are set like <elem attr='value'> and properties are dynamically set.

For example, an input element will not change its attribute when entering something in it. The property, however, will change. So .value would return the correct result, whereas .getAttribute('value') would return the initial value as set with value="something".

In your case, it's an explicit attribute and not a property. Hence, .d does not work whilst .getAttribute('d') does.

http://jsfiddle.net/Kdp4v/

pimvdb
  • 151,816
  • 78
  • 307
  • 352
30

The SVGPathElement interface does not have a d property:

As others have said, you can access the data as a big ugly string by using the standard DOM 2 Core method available to all XML applications, myPath.getAttribute('d').

Note that while SVG elements are in the SVG namespace, SVG attributes are not; you should not use myPath.getAttributeNS('http://www.w3.org/2000/svg','d').

However, if you want an object-oriented representation of the path data, you want one of these attributes:

All of these attributes give you a SVGPathSegList, which is an ordered list (not an array) of SVGPathSeg objects that you can enumerate using numberOfItems and getItem().

Note that SVGPathSeg is a base interface inherited by the more specific objects you get back from getItem():

Here's what the usage might look like:

var segments = myPath.pathSegList;
for (var i=0,len=segments.numberOfItems;i<len;++i){
  var segment = segments.getItem(i);
  switch(segment.pathSegType){
    case SVGPathSeg.PATHSEG_LINETO_ABS:
      // segment is a SVGPathSegLinetoAbs object
      console.log( "Absolute Line To", segment.x, segment.y );
    break;
    case SVGPathSeg.PATHSEG_CLOSEPATH:
      // ...
    break;
    // see http://www.w3.org/TR/SVG11/paths.html#DOMInterfaces for constants
  }
}
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • Incidentally, the reason I want it, is because I'm about to embark on a Javascript solution for projective transformation of an SVG. I would prefer a fully SVG solution, but I can't think of one. I feel like you're a person to check with though. Can YOU think of a pure SVG way? (I can't see why SVG transformations don't just take a few more numbers. Homogenous 3-vectors to represent 2-points, and 3x3 matrices to transform them, would be perfect.) – Thomas Poole Apr 29 '17 at 01:41
  • 2
    I just realised that this uses a deprecated interface, and no longer works. See http://stackoverflow.com/questions/34352624/alternative-for-deprecated-svg-pathseglist and in particular "there will be a new API https://svgwg.org/specs/paths/#InterfaceSVGPathData and a polyfill for that https://github.com/jarek-foksa/path-data-polyfill.js as well as a polyfill for the old API https://github.com/progers/pathseg Also see the official chromium bug https://code.google.com/p/chromium/issues/detail?id=539385 " – Thomas Poole Apr 29 '17 at 02:03
1

Try using getAttribute():

alert(document.getElementById('s3').getAttribute("d"));
James Wiseman
  • 29,946
  • 17
  • 95
  • 158
1

Hello to contemporaries with the same problem. I don’t know about how it be in 2011, but we now have setAttribute to solve such problems

document.getElementById('id').setAttribute("nameOfAttribute", "valueOfAttribute")

let foo = () => {document.getElementById('btn').setAttribute("d", "M42,2.98v43.54c0,0.54-0.71,0.98-1.59,0.98h-7.08c-0.88,0-1.59-0.44-1.59-0.98V2.98 c0-0.54,0.71-0.98,1.59-0.98h7.08C41.29,2,42,2.44,42,2.98z M18.62,2.98v43.54c0,0.54-0.71,0.98-1.59,0.98H9.96c-0.88,0-1.59-0.44-1.59-0.98V2.98C8.37,2.44,9.08,2,9.96,2 h7.08C17.91,2,18.62,2.44,18.62,2.98z")}
<style>
   svg{
   width: 25px; 
   height: 25px;
}
</style>
<svg viewBox="0 0 50 50"> 
   <path id="btn" d="M8.5,2.99v43.88c0,0.66,0.74,1.05,1.29,0.68l31.73-21.87c0.47-0.33,0.47-1.03,0-1.35L9.79,2.31 C9.25, 1.93, 8.5, 2.32, 8.5, 2.99z"/>
</svg>
<button onclick="foo()">change</button>
Dokoa
  • 25
  • 6