Saturday 2 April 2011

Graphically Displaying Yahoo Weather API Data in Flash



In my last post I looked at querying the Yahoo GEO and Weather APIs from within flash in order to return an XML file containing weather and forecast information.

Last time I simply pulled out the location and the weather condition text that gave a general description of the current weather. But actually the XML contains many more items than that. One of which is the prevailing temperature of the location being queried.

Displaying the temperature as text is relatively easy but you can also be more graphic, as in my virtual thermometer above.

In this prototype I am simply using the temperature data, which Yahoo provides as an integer, to determine the length of the 'mercury' in the thermometer.

How it was done

The Graphics

First I made all the pretty graphics in Fireworks (but you could use Photoshop, Paint.net, PhotoPlus etc.), and imported the assets into Flash. The important thing is that your scale (that's the Celcius and Farenheit rulers are correctly in line with each other, and the increments are spaced evenly on each scale).

To do this you need to understand the following:

-40C is the same as -40F (that's where the two scales meet)
0C is the same as +32F
+50C is the same as +122F

On that basis you should be able to construct C and F scales that line up the way they should. I did it by making two the same and then scaling the F scale smaller vertically so that -40 F and 122 F lined up with -40 C and 50 C respectively.

I also chose to run my scales from -40C to +50C because using the Yahoo Weather API I needed a scale that would reasonably take all global temperatures. I figure that somewhere might get close to -40C and somewhere might get up to +50C. If it turns out my scale isn't big enough I can always ammend it.

The 'Mechanics'

Once the graphics are in Flash I create a small red rectangle for the 'mercury' and turn it into a MovieClip (press F8) with the registration point at the bottom left, and with the instance name "liquid_mc". Then I create a transparent rectangle for the tube in which the 'mercury' travels and turn it into a MovieClip with the instance name "tube_mc" - this needs to be exactly the same height as the distance between the lowest temperature on your graphical scale (in my case -40C) and the highest temperature (in my case +50C) - for me this turned out to be 360 pixels, but it will vary depending on the size and shape of your graphical representation of the scale.

I place the two MovieClips on top of the graphic in the right place at the bottom of the graphical glass tube so when the the 'mercury' grows it will grow up from the bottom.

Then I select the graphic, the "tube_mc" and the "liquid_mc" and turn them all into a MovieClip with the instance name "thermometer_mc", so that "tube_mc" and "liquid_mc" are inside "thermometer_mc".

Finally, create a button, and add it to the stage with the instance name "submit_btn". Users will need to press this to run the query of the Yahoo API and display the result.

The Code

Then I create a new layer, give it the name 'actions' (so all my code is neatly in one place), and put in the following actionscript. Read my comments in the code to see what is happening:


stop ();
/*Thermometer*/
/*calculate the pixel height of 1 degree c by dividing the height of the thermometer tube by the number of degrees c it covers*/
var degree:Number = _root.thermometer_mc.tube_mc._height / 90;
/*calculate zero - because our thermometer starts at -40C we use this to ensure future calculations take account of this fact*/
var zero:Number = degree * 40;
/*Accessing the Yahoo API to find out the weather in any location using postcode and country code*/
/*set the search terms as variables, you can pull these from user input with some different ActionScript */
_root.submit_btn.onPress = function () {
var zip = "SW1A 1AA";
var country = "UK";
/*Find the WOEID*/
woeidXml = new XML ();
woeidXml.ignoreWhite = true;
/* run the loadWoeid function when the XML file loads that contains Yahoo's reply to our query below*/
woeidXml.onLoad = loadWoeid;
/* ASK QUESTION 1 - query the Yahoo API using YQL and the search terms above */
woeidXml.load ("http://query.yahooapis.com/v1/public/yql?q=select%20woeid%20from%20geo.places%20where%20text%3D%22" + zip + "%2C" + country + "%22&diagnostics=true");
/* this function will run when the XML file loads that contains Yahoo's reply to our query */
function loadWoeid () {
/*parse the XML response and store the woeid value as a variable in Flash called 'woeid'*/
woeid = woeidXml.childNodes[0].childNodes[1].childNodes[0].childNodes[0].childNodes[0];
/*find the WEATHER from the WOEID just gathered*/
/* we nest this function for question 2 within the function for question 1 because doing it this way means that question 2 is not asked until question 1 has an answer*/
weatherXml = new XML ();
weatherXml.ignoreWhite = true;
/* run the loadWeather function when the XML file loads that contains Yahoo's reply to our query below*/
weatherXml.onLoad = loadWeather;
/* ASK QUESTION 2 - query the Yahoo Weather API using the woeid we found out in question 1 above */
weatherXml.load ("http://weather.yahooapis.com/forecastrss?w=" + woeid + "&u=c");
/* this function will run when the XML file loads that contains Yahoo's reply to our query */
function loadWeather () {
/*parse the XML response and store the current temperature condition value as a variable in Flash called 'temp_xml'*/
temp_xml = weatherXml.childNodes[0].childNodes[0].childNodes[12].childNodes[5].attributes.temp;
/*set current temperature variable from XML*/
var temp_c:Number = temp_xml;
/*set height of the thermometer liquid_mc graphic based on the temperature extracted from the XML*/
_root.thermometer_mc.liquid_mc._height = (temp_c * degree) + zero;
}
}
};


As you will see, this is virtually the same code as in my previous post, the main difference is how we use the extracted data to change the height of a MovieClip that represents the 'mercury' in the thermometer. To find the temperature of a different location simply change the values of zip and country on lines 10 and 11.

I went a bit further (not explained in this post) and put in some text input fields so that the user can define their own location (maybe I will get time to explain that in a future post).

Meanwhile, happy temperature... er... displaying.

No comments:

Post a Comment