lode
lode

Reputation: 564

standalone svg add element dynamically with javascript

I am creating a stand alone svg. With javascript embedded. I have difficulties accessing the root element "svg". It's easy enough when it's embedded in a HTML page (getElementById), but is it possible to do as standalone?

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id ="testsvg"  width="1000" height="500" viewBox="0 0 1000 500"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example script01 - invoke an ECMAScript function from an onclick event
  </desc>
  <!-- ECMAScript to change the radius with each click -->
  <script type="application/ecmascript"> <![CDATA[
    function circle_click(evt) {
      var circle = evt.target;
      var currentRadius = circle.getAttribute("r");
      if (currentRadius == 100)
        circle.setAttribute("r", currentRadius*2);
      else
        circle.setAttribute("r", currentRadius*0.5);
    }
	
	function make_shape(evt) {
	   
		var svg =                          // <-------------  WHAT TO USE?
		console.log(svg);
		shape = svg.createElement("circle");
		shape.setAttribute("cx", 25);
		shape.setAttribute("cy", 25);
		shape.setAttribute("r",  20);
		shape.setAttribute("style", "fill: green");
		svg.appendChild(shape);
	}
    
  ]]> </script>

  <!-- Outline the drawing area with a blue line -->
  <rect x="1" y="1" width="900" height="498" fill="none" stroke="blue"/>

  <!-- Act on each click event -->
  <circle onclick="circle_click(evt)" cx="300" cy="225" r="50"
          fill="red"/>
	  <!-- Act on each click event -->
  <circle onclick="make_shape(evt)" cx="500" cy="225" r="50"
          fill="yellow"/>	  
  
  <text x="500" y="380" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on red circle to change its size.
  </text> 
  <text x="500" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on yellow circle to add a circle
  </text>
  
</svg>

Upvotes: 0

Views: 521

Answers (2)

wassona
wassona

Reputation: 329

The DOM API still works just fine, so you can use document.querySelector('svg'). I assume you could assign a class or id to the svg if you need to select it in another way. The selected svg, however, is still just an element, so rather than svg.createElement(), you'll need document.createElement(). If you do that, the code should work, but nothing will display. This, I've just learned, is because svg elements must be created with document.createElementNS(), which takes two arguments: the xmlns, and the type of element you want to create: document.createElementNS("http://www.w3.org/2000/svg", "circle").

<?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
      "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg id ="testsvg"  width="1000" height="500" viewBox="0 0 1000 500"
         xmlns="http://www.w3.org/2000/svg" version="1.1">
      <desc>Example script01 - invoke an ECMAScript function from an onclick event
      </desc>
      <!-- ECMAScript to change the radius with each click -->
      <script type="application/ecmascript"> <![CDATA[
        function circle_click(evt) {
          var circle = evt.target;
          var currentRadius = circle.getAttribute("r");
          if (currentRadius == 100)
            circle.setAttribute("r", currentRadius*2);
          else
            circle.setAttribute("r", currentRadius*0.5);
        }
        
        function make_shape(evt) {
           
            var svg =     document.querySelector('svg');                    
            
            shape = document.createElementNS( "http://www.w3.org/2000/svg", "circle");
            shape.setAttribute("cx", 25);
            shape.setAttribute("cy", 25);
            shape.setAttribute("r",  20);
            shape.setAttribute("fill", "green");
            svg.appendChild(shape);
        }
        
      ]]> </script>

      <!-- Outline the drawing area with a blue line -->
      <rect x="1" y="1" width="900" height="498" fill="none" stroke="blue"/>

      <!-- Act on each click event -->
      <circle onclick="circle_click(evt)" cx="300" cy="225" r="50"
              fill="red"/>
          <!-- Act on each click event -->
      <circle onclick="make_shape(evt)" cx="500" cy="225" r="50"
              fill="yellow"/>     
      
      <text x="500" y="380" font-family="Verdana" font-size="35" text-anchor="middle">
        Click on red circle to change its size.
      </text> 
      <text x="500" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
        Click on yellow circle to add a circle
      </text>
      
    </svg>

Upvotes: 1

somethinghere
somethinghere

Reputation: 17358

When your SVG element is displayed as the main document in your browser, it is actually an element of a generated document, so you can simply use techniques already familiar from javascript:

var svg = document.querySelector('svg')

Since the SVG is not a document, you cannot use it to create elements, but you can use the document itself to create new shapes:

var shape = document.createElementNS('http://www.w3.org/2000/svg', 'circle');

And then you can append them to your new-found svg element. I have amended your code for clarity. If this is not working, what exactly are you using to display these SVGs? Since if they have support for 'ecmascript' (aka javascript), they must also support at least the functionality described in the spec.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id ="testsvg"  width="1000" height="500" viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>
    Example script01 - invoke an ECMAScript function from an onclick event
  </desc>
  
  <!-- ECMAScript to change the radius with each click -->
  <script type="text/javascript">
    function circle_click( evt ){
    
      var circle = evt.target;
      var currentRadius = circle.getAttribute("r");
      
      if( currentRadius == 100 ){
      
        circle.setAttribute("r", currentRadius*2);
      
      } else {
      
        circle.setAttribute("r", currentRadius*0.5);
      
      }
      
    }
    
    function make_shape( evt ){
	  
      var svg = document.querySelector('svg');
      var shape = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
      
      shape.setAttribute("cx", 25);
      shape.setAttribute("cy", 25);
      shape.setAttribute("r",  20);
      shape.setAttribute("style", "fill: green");
      
      svg.appendChild( shape );
      
    }
    
  </script>

  <!-- Outline the drawing area with a blue line -->
  <rect x="1" y="1" width="900" height="498" fill="none" stroke="blue"/>

  <!-- Act on each click event -->
  <circle onclick="circle_click(evt)" cx="300" cy="225" r="50" fill="red"/>
  <!-- Act on each click event -->
  <circle onclick="make_shape(evt)" cx="500" cy="225" r="50" fill="yellow"/>	  
  
  <text x="500" y="380" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on red circle to change its size.
  </text> 
  <text x="500" y="480" font-family="Verdana" font-size="35" text-anchor="middle">
    Click on yellow circle to add a circle
  </text>
  
</svg>

Upvotes: 1

Related Questions