Sunday, April 22, 2012

Dart Language for Interactive SVG Documents

Dynamic SVG Documents using Dart
(Scalable Vector Graphics files)



I am deep in the midst of migrating a Javascript and SVG UI-Components/Widgets set to Dart Language SVG / CSS. As I prepare to publish my rather experimental Dart/SVG widgets source code and examples, I figured I would start with a super-simple example of how to replace JavaScript with Dart (as used in SVG).
UPDATE: I have pushed an initial release of my Dart/SVG GUI Components to github — see my newer blog post about "Introducing dart-squid: Dart/SVG UI Controls" for details — the source-code there will much better demonstrate the potential of Dart / SVG.

Note: the easiest way to run any Dart code, from my experience, is to download the latest Dart-enabled Chromium Browser build — Dartium (from its continuous-build directory) — I use the Dartium-Win version and it is amazingly stable for this early in a development cycle.

A Simple SVG document with Dart-Language

This example is going to be perhaps way too unsophisticated to cause much excitement, but the idea is simply to get you to consider trying Dart Language (instead of JavaScript), as I believe Dart Language has fantastic potential for browser-based business applications among other things. 

Coming from a Delphi, C#, and JS development background, I find Dart to be much closer to Delphi for development productivity than JavaScript.  I.e., I can write much more functionality in the same time using Dart than I could ever do with JavaScript; and, the code quality is immensely improved, more maintainable, extensible, and polished.

Step 1: create a .SVG file — name it whatever you want... perhaps SVG-using-external-Dart.svg or something similar. Copy and paste the following into that file and save it.


<svg    xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        id="testContainer"
        width="1000"
        height="800"
        xml:space="preserve">
    <script type="application/dart" xlink:href="external-code.dart"/>
    <svg id="testSVGCanvas">
        <rect   id="MySVGRectID" x='10' y='10' width='300' height='150'
                fill='tan' fill-opacity='1' stroke='black' stroke-width='3'/>
        <text stroke='black' x='100' y='100' >Click on Rectangle</text>
    </svg>
</svg>


Step 2: create a .dart file in the same directory — name it to match the xlink:href value we specified in our SVG file — in this case, external-code.dart. Copy and paste the following dart code into that file and save it.


#library("Test");
#import('dart:html');
void setSVGAttributes(SVGElement svgEl, var attributesPairs) {
    attributesPairs.forEach((attr, value){
        svgEl.attributes[attr] = value;
    });
}


//***********************************************************
//********** MAIN FUNCTION CALLED FROM SVG ONLOAD ***********
//***********************************************************
main() {
    SVGElement rectReference = null;
    void MouseDown(Event e) {
        setSVGAttributes(rectReference, {
            'fill': 'purple',
            'opacity': '0.6'
        });
    }
    void MouseUp(Event e) {
        setSVGAttributes(rectReference, {
            'fill': 'tan',
            'opacity': '1'
        });
    }
    print("main loaded");
    
    rectReference = document.query('#MySVGRectID');
    rectReference.on.mouseDown.add(MouseDown);
    rectReference.on.mouseUp.add(MouseUp);
}


Now, you should be able to open that .SVG file using the Dartium browser and you will see a very simple demonstration of using Dart to manipulate the SVG DOM at runtime for some simple interactivity.

In this example, a rectangle will change from tan to purple (while the mouse button is depressed).  You can get a taste for how the dart:html library exposes element events and such here at least (I suggest looking at the APIs on the dart language site; even that base dart:core library is enough to get exited about with real, and quite handy and functional, built-in collections for starters).

Notice that the code I provided here is just one approach, and ridiculously simplified.  Here is another very simple variation on that code, placing the event callbacks within main() if we want.


#library("Test");
#import('dart:html');


void setSVGAttributes(SVGElement svgEl, var attributesPairs) {
    attributesPairs.forEach((attr, value){
        svgEl.attributes[attr] = value;
    });
}


//***********************************************************
//********** MAIN FUNCTION CALLED FROM SVG ONLOAD ***********
//***********************************************************
main() {
    SVGElement rectReference = null;


    void MouseDown(Event e) {
        setSVGAttributes(rectReference, {
            'fill': 'purple',
            'opacity': '0.6'
        });
    }


    void MouseUp(Event e) {
        setSVGAttributes(rectReference, {
            'fill': 'tan',
            'opacity': '1'
        });
    }


    print("main loaded");
    
    rectReference = document.query('#MySVGRectID');
    rectReference.on.mouseDown.add(MouseDown);
    rectReference.on.mouseUp.add(MouseUp);
}



Although I am not demonstrating Dart's full potential here, keep in mind that Dart is a fully object-oriented class-based development language with a very useful optional typing system that make RAD (Rapid Application Development) possible unlike anything you'll experience with JavaScript.  Try it, you may like it!

This super-basic example demonstrates how a dart application can be built within an SVG document. And, trust me, the component set I am programming goes well beyond such simplicity. Stay tuned for more about that...

Continue to read this Software Development and Technology Blog for computer programming articles (including useful free / OSS source-code and algorithms), software development insights, and technology Techniques, How-To's, Fixes, Reviews, and News — focused on Dart Language, SQL Server, Delphi, Nvidia CUDA, VMware, TypeScript, SVG, other technology tips and how-to's, plus my varied political and economic opinions.

3 comments:

Will de la Vega said...

Great work, but my concern not only about this good initiative but regarding dart in general is, will it be truly compatible with IE? specifically IE for Windows 8 ? Are these SVG components (or will be these SVG components) compatible with Windows?

Are you testing against multiple browsers? Sorry for asking but I do because I see real value in the work you are doing (and in the Dart platform).

Will de la Vega said...

Are these components compatible with IE on Windows 8? I have seen with pain in my heart that many dart libraries simply don't run in IE. I am becoming a real fan of Dart but I cannot invest (as many others will probably think) any serious effort until making sure that Safari, IE and Firefox (to mention the main players) will support the JavaScript produced by it (and SVG btw). Will your SVG components render well in all browsers using dart?

Mike Eberhart said...

Will,
I have not tested with IE on Win8, and I am not sure I ever will. I have only made sure my SVG-Dart components work with the Dartium browser (Chromium with the native Dart-language VM in it), though the Dart2JS code does seem to work fine as JS running in Chromium. FF does not work for me due to a lot of outstanding FF-SVG bugs (like, no browser-resize-event firing), and more. IE was just terrible last time I checked, and that was IE10 on Win7. There were too many missing SVG-related features yet in IE.

Also, since I first wrote my Dart/SVG widgets (I have them on Github), I have been updating to use the Dart-Polymer (webcomponents / shadow-DOM) technology, which I doubt works in IE at all yet. I have the shadow-DOM version working on my local computer in Dartium, and plan to create another Github project showing how I used that technology. But, I have not had any luck getting JS builds to work with the polymer version (Polymer-Dart is in alpha or beta state yet).

If you have any particular thing you want to discuss, post another comment here with your email (and I will not publish it), and I can respond directly. Thanks. mike