Monday, August 20, 2012

SVG Simplified

SVG has some really complex examples.

This post is intended to explain using SVG with javascript for the non-expert.


Here is a full working example showing how to place an svg element on an html page, create an svg image element, refer to it in javascript thru the SVG-DOM, and move an svg image element on the page such as one might in an arcade game.

This example is available as a jsfiddle here: http://jsfiddle.net/uponthecouch/pK84Y/

Sometimes it is handy to have the entire thing in a single file such as you could put in an eclipse Static Web Project and try out by just pressing the play button right on our own machine:

<!DOCTYPE html>
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>SVG attempt</title>
  <style>
   #svgContainer 
   {
       width:600px;
       height:200px;
       background-color:#EEEEEE;
       border:1px solid #c3c3c3;
   }
  </style>
 </head>
 <body>
  <svg id="svgContainer" xmlns="http://www.w3.org/2000/svg" version="1.1">
  </svg>
   <p>X coordinate: <span id="xcoor"></span>
   <p>Y coordinate: <span id="ycoor"></span>
   <script type="text/javascript">
    var container = document.getElementById("svgContainer");
    var x = 0;
    var y = 0;
    var image = document.createElementNS("http://www.w3.org/2000/svg", "image");
    image.setAttribute('height','10');
    image.setAttribute('width', '10');
    image.setAttribute('id','testimg');
    image.setAttribute('x', x);
    image.setAttribute('y', y);
    image.setAttributeNS('http://www.w3.org/1999/xlink','href',"http://i50.tinypic.com/24c8twj.jpg");
    container.appendChild(image);
    var timer = self.setInterval(function() 
    {
        move_image(x += 2, y += 2);
    }, 100);
    
    function move_image(x, y)
    {
        if (y>200)
        {
            timer = window.clearInterval(timer)
            return;
        }
        image.setAttribute('x', x);
        image.setAttribute('y', y);
        document.getElementById("xcoor").innerHTML = x;
        document.getElementById("ycoor").innerHTML = y;
    }
​  </script>
 </body>
</html>

Questions to ask might be: 

Why use namespace specific methods for creating the element, and specifying the image source, but not the other attributes?

Can SVG, html, and even canvas elements exist on the same page? On top of one another?

A question to be answered (hopefully) in a future post: 

Which is better for moving things like ships around on a page, Canvas or SVG? Things like hit detection, bullets/projectiles, enemies all seem to point to SVG, surprisingly depending on the simplicity of the background Canvas may be more performant ...

Here is a link to my post about using Canvas to do the same thing.

Here is the same thing, done differently: 

The svg image element is moved by deleting the existing one and creating a whole new one: this serves to show how to locate an svg element and delete it if nothing else. It is surprisingly hard to find simple examples of how to do this sort of thing.

Here is the Jsfiddle showing this alternative technique:
http://jsfiddle.net/uponthecouch/M9LF7/

This is the javascript, the html and css is unchanged from the first example:
var container = document.getElementById("svgContainer");
var x = 0;
var y = 0;
var image = null;
var timer = self.setInterval(function() 
{
    create_image(x += 2, y += 2);
}, 100);

function create_image(x, y) 
{
    if (y>200)
    {
        timer=window.clearInterval(timer)
        return;
    }
    console.log("x,y = " + x + "," + y);
    if (image != null) 
    {
        var parent = image.parentNode;
        console.log(parent);
        parent.removeChild(image);
    }
    image = document.createElementNS("http://www.w3.org/2000/svg", "image");
    image.setAttribute('height', '10');
    image.setAttribute('width', '10');
    image.setAttribute('id', 'testimg');
    image.setAttribute('x', x);
    image.setAttribute('y', y);
    image.setAttributeNS('http://www.w3.org/1999/xlink', 'href', "http://i50.tinypic.com/24c8twj.jpg");
    container.appendChild(image);
    document.getElementById("xcoor").innerHTML = x;
    document.getElementById("ycoor").innerHTML = y;
}​

No comments: