Wednesday, November 10, 2010

SVG on iPhone !!

We at Kontera are beginning to develop an iPhone version of our application.

Since our current version is based on flash, it obviously needs a redesign to support this exciting platform. During investigation I decided to try out SVG. I would like to share this interesting experience with you all.

SVG has quite a few advantages as a graphic engine. Here are some:
1. SVG is programmable quite easily. I can take an SVG file that I know has an element called 'buttonX', and place an onclick callback that closes the app. I don't really care where this button is situated or how it looks like.
2. Our creative department can handle SVG quite well. This means that I can receive creative assets and incorporate them right into the new code.

The alternative - pure HTML - would have a hard time achieving these advantages. I am also guessing that since SVG is better defined than HTML, the amount of cross browser issues will be smaller (when going past iphone).

However, there were some challenging issues:
1. Cross domain - since our SVG is not from the domain of the site owner (we are more like a library or plugin) - when we tried to access the SVG contents from our javascript we received cross domain issues.
2. <embed> and transparency - there is a bug in Safari (and Chrome, and probably other WebKit based browsers) that when you <embed> an SVG file, the stage can not be transparent. This was somewhat of a disappointment to our design team. This bug does not happen in Firefox.

Our initial workaround was to place the SVG in an iframe (which has a source in our domain). We were figuring we would solve the cross-iframe issues using postmessage, but this is only takes you so far. For instance, if you want to open a new window from the iframe during a user click without having the popup blocker block you, this can be a problem. We also had JSON serialization issues, and in short the iframe was starting to become a can of worms.

On further exploration, we noticed that if you create the SVG dynamically (using document.createElementNS, element.setAttribute) instead of embedding a static XML file, both problems disappear. The cross domain issues are gone, and also the stage can be transparent.

Obvious asking our creative department to work this way was not going to work. Instead, we wrote a cute little tool in ruby that reads the XML file, and generates the appropriate JavaScript code to re-create this XML structure at runtime. The generated code looks something like:

function createLayer(_parent) {
var svgns='http://www.w3.org/2000/svg';
var node0=document.createElementNS(svgns, 'svg');
node0.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
node0.setAttribute('ontouchmove','event.preventDefault()');
node0.setAttribute('height','178');
node0.setAttribute('xmlns','http://www.w3.org/2000/svg');
node0.setAttribute('width','286');
var node1=document.createElementNS(svgns, 'g');
node1.setAttribute('id','main_group');
var node2=document.createElementNS(svgns, 'title');
node2.appendChild(document.createTextNode('Layer 1'));
node1.appendChild(node2);
.....
_parent.append(node0);
return node0;
}

This did place some limitations on the SVG. We have some problems working with <defs> , but the easiest workaround was to remove them from the SVG and move on. So far, all is well. Hoping to release soon so you can all see it on your iphones ;-)

Noam