Dojo + OpenLayers = New Challenges

Recently, the new Dojo 1.7 was released with many improvements and important changes.

As a developer, I’m pleased to work with Dojo on RIA application because simple reasons:

It offers almost all I need: module organization, an extensive set of widgets to create interfaces, manipulation of DOM elements, AJAX communications, etc.

It is relatively easy to use and learn. Here I found the declarative way to work really useful because helps developers and designers work together but on different things.

Creating custom widgets, after some relatively easy learning curve, brings you more power and flexibility.

Yes, Dojo is a great project, but as I mentioned at the beginning I like it for RIA projects, that is, for big or complex CRUD applications. For small things, like nice web pages, I prefer jQuery plus some plugins.

Looking at the new features of Dojo 1.7 I found a new module dojox.geo.openlayers which acts as a wrapper around OpenLayers GIS library and extends with some Dojo capabilities.

Now, add Dojo GFX shapes or Dojo widgets on top OpenLayers is possible, opining new possibilities. With this merge we can do things like add pie charts to our maps to show to statistics information. It is awesome !!!

A very short introdutcion to dojox.geo.openlayers package

Before making a little demo playing with all this new things, we need a short description.

The main class in the package is dojox.geo.openlayers.Map which acts as a kind of wrapper around the OpenLayers.Map class. You can access at any time to the OpenLayers underline object with the getOLMap() method.

Next, there is the dojox.geo.openlayers.Layer class which is a wrapper around the OpenLayers.Layer class. It allows to attach to the map any Dojo element.

The dojox.geo.openlayers.GfxLayer is a subclass of the previous class specially designed to work with GFX shapes and render them on top of OpenLayers map.

The dojox.geo.openlayers.Feature class represents the features we can attach to a dojox.geo.openlayers.Layer. The subclass dojox.geo.openlayers.GeometryFeature is designed to render LineString, Points and Collections of geometries.

Because GeometryFeature works with dojox.gfx package to render the geometries you need to add it always to a dojox.geo.openlayers.GfxLayer layer.

Hands on code

We are going to create a map with three features:

a dojox.gfx shape feature, with an animation attached to it to change it fill color,

a pie chart and

a stacked area chart.

You can see the demo in action here, and it should looks something like:

Dojo + OpenLayers

Lets go. Start creating new HTML page and paste the next code, which correspond to the skeleton of our demo:

We want to animate the fill color of the geometry feature so we need to create a couple of animation. The first one will change the fill color from the original color to transparent, while the second will change from transparent to the original color again.

The trick is once the first animation ends we start the second animation (using the ‘onEnd‘ method) and the same for the second animation. This way we create an infinite animation effect.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

// Add an animation to change the color of the feature

varanimA=dojox.gfx.fx.animateFill({

shape:feature,

duration:700,

color:{

start:"#999",

end:"transparent"

},

onAnimate:function(){

// Required to update the layer while feature change it fill color

gfxLayer.redraw();

},

onEnd:function(){

animB.play();

}

});

varanimB=dojox.gfx.fx.animateFill({

shape:feature,

duration:700,

color:{

start:"transparent",

end:"#999"

},

onAnimate:function(){

// Required to update the layer while feature change it fill color

gfxLayer.redraw();

},

onEnd:function(){

animA.play();

}

});

animA.play();

Now, we are going to create a pie chart widget feature. We are going to use the dojox.geo.openlayers.WidgetFeature class which required an object in the constructor defining the widget to create, the lat/lon where to place the widget and some more parameters. You can find all the available parameters in the source code documentation:

// * _longitude_: The longitude, in decimal degrees where to place the widget.

// * _latitude_: The latitude, in decimal degrees where to place the widget.

The pie chart widget have a 100×100 size and will we located at (lon,lat)=(5, 40). The createWidget property must point to a function responsible to create the appropriate widget:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

// Add a widget feature

varchartSize1=100;

varco1=[5,40];

vardescr1={

// location of the widget

longitude:co1[0],

latitude:co1[1],

// the function which creates the widget

createWidget:function(){

vardiv=dojo.create("div",{},dojo.body());

varchart=newdojox.charting.widget.Chart({

margins:{

l:0,

r:0,

t:0,

b:0

}

},div);

varc=chart.chart;

c.addPlot("default",{

type:"Pie",

radius:chartSize1/2,

labelOffset:chartSize1,

fontColor:"black"

});

varser=[2,8,12,43,56,23,43,1,33];

c.addSeries("Series",ser);

c.setTheme(dojox.charting.themes.PlotKit.blue);

c.render();

c.theme.plotarea.fill=undefined;// Transparent background

returnchart;

},

width:chartSize1,

height:chartSize1

};

vargraphFeature1=newdojox.geo.openlayers.WidgetFeature(descr1);

gfxLayer.addFeature(graphFeature1);

Similarly, we create a second widget feature with a stacked area chart with different dimensions and location:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

// Add a second plot feature

varchartSize2=[300,200];

varco2=[15,45];

vardescr2={

// location of the widget

longitude:co2[0],

latitude:co2[1],

// the function which creates the widget

createWidget:function(){

vardiv=dojo.create("div",{},dojo.body());

varchart=newdojox.charting.widget.Chart({

margins:{

l:0,

r:0,

t:0,

b:0

}

},div);

varc=chart.chart;

c.addPlot("default",{type:"StackedAreas",tension:3})

.addAxis("x",{fixLower:"major",fixUpper:"major"})

.addAxis("y",{vertical:true,fixLower:"major",fixUpper:"major",min:0})

.addSeries("Series A",[1,2,0.5,1.5,1,2.8,0.4])

.addSeries("Series B",[2.6,1.8,2,1,1.4,0.7,2])

.addSeries("Series C",[6.3,1.8,3,0.5,4.4,2.7,2])

.setTheme(dojox.charting.themes.PlotKit.blue);

c.render();

returnchart;

},

width:chartSize2[0],

height:chartSize2[1]

};

vargraphFeature2=newdojox.geo.openlayers.WidgetFeature(descr2);

gfxLayer.addFeature(graphFeature2);

Once we have all the features in the layer, it is a good idea to refresh it:

1

gfxLayer.redraw();

Conclusions

I think the fusion of Dojo with OpenLayers opens new possibilities to create rich content and behavior mapping applications. We can create dojo features and make them really amazing using effects, animation and events (like this).

I usually work with OpenLayers and, because Dojo simply acts as a wrapper on some OpenLayers classes, we can access them and work directly adding data from WFS server, GML files, etc

Is it a perfect solution? As always it depends on your needs but for all of us which work in complex RIA applications that needs some GIS features the dojox.geo.openlayers package offers a new spot light

9 Responses

Thanks for that post (although it’s mostly an explanation of what’s going on in dojox/geo/openlayers/tests/widgetFeature/test_widgetFeature.html). It’s strange that we can do amazing things with those frameworks and sometimes there are absurd limitations. For instance, I want to show a georeferenced png version of an svg icon (because Android does not support SVG) so I did something like this, and it does not show anything (and no errors either); Any idea how to do this?
var markers = new OpenLayers.Layer.Markers( “Markers” );
map.map.getOLMap().addLayer(markers);
var size = new OpenLayers.Size(210,250);
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
var icon = new OpenLayers.Icon(‘js/OpenLayers/img/marker.png’,size,offset);
markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(-72.1003,48.4003),icon));
markers.redraw();

Thanks Al.
Really I can’t help you too much.
I test your code on desktop Chrome and Firefox browsers and it works fine, in my case without using a Map widget which make the code change in line “map.getOLMap().addLayer(markers);”.
Maybe you can put the question on Dojo or OpenLayers forums if it seems a problem on mobiles.
Let me know if you found the problem !!!

I want to thank you because your taking the time to do that test with success pushed me to revisit that coding. At first, I thought the widget/not-widget nature of the map was the explanation since it appeared to be the only difference. After trying that change without more success, I had a flash (I must say I had that doubt before). It turns out the answer is more trivial: OpenLayers doc says you provide a LongLat object (+icon) to create the marker; that’s WRONG. What you provide is a coordinate in WHATEVER system the map is currently in; so the solution was as trivial as this (given I use Google as provider):
po1=new OpenLayers.LonLat(-72.1,48.4).transform(geo,mercator);
markers.addMarker(new OpenLayers.Marker(po1,icon));
Bad documentation again, that’s the plague. Thanks again for your help, A.R.

Yes, you must take into account always express lonlat values (on markers, points, etc) in the same coordinate system of the layer it contains or, if the layer has no projection indicated, in the map’s projection.
Thanks for your comments !!!

Hi.
Thanks for the nice explanation, it helped me a lot in putting dijits inside an openlayer map. There’s one really stupid problem that I can’t seem to solve directly:
If I don’t use the animated blob, the two graph widgets are no longer locked to the map! Dragging the map will cause the widgets to return to their previous screen position after you let go of the mouse. You can very easily test this by commenting out animA.play() (dojoGeo.html:101).
I’m trying to find out what’s actually happening here, but any help would be appreciated.

Thanks much for your post. It helped me solved my problem. I was wondering, you mentioned that for simple web pages, it is preferrable to use jQuery and some plugin instead. Specifically, I am into merging map and pie charts. I want to use OpenLayers for the map. As for the pie chart, I am not sure what to use. I looked for several alternatives and ended up in jqPlot, but haven’t figured out how to merge with the OpenLayers.
Do you think this is a good idea?, otherwise, please kindly point me to some useful resources to learn from.