Login: Pwd:
Bar search:

Add the New York skyline to your site or blog

It's simple. Just copy the code below and paste it into your blog or site.
As the conditions change in New York City, so will the picture on your blog. A simple mouseover will give the current temperture and the chance of rain during the day, or the reason for the current Empire State Building lighting at night.

Or add it as a Google Gadget

Add to Google

How's it done?


Well, the short answer is by PNG images, and varying the opacity to gently fade in one time of day to the next. For instance at 40 mins to sundown the sunset PNG is at 30% opacity, but at 10 mins it's at 90%. So what is PNG?

The PNG format
Portable Network Graphics is some pretty amazing stuff:
  • It's lossless - Open a jpg save it again repeat a dozen times and what you get is a mess, but with PNG it looks shiny and new just like the original
  • Alpha channel transparency - Allows for semi-transparency, unlike GIF which allows for only absolute transparency, or JPG which has no transparency at all

The Alpha transparency is the magic bullet here. Even if I didn't try and fade one time of day into the next, the rain and snow effects would look atrocious in GIF format - full opacity just doesn't suit a drop of rain.

On the client or on the server?

This is the big question. The work of compositing the images could be handled by a chron running on the server which composites the various PNG and exports a single JPG, or the PNGs could be fed to the client and we can let the browser do the compositing work.

Advantages of server side compositing

  • File size - Since JPEG is lossy and doesn't need space for an alpha channel the files are much smaller than PNG and we only need to send one image instead of up to 8. (For example if between sunset and night when it's cloudy, half raining and half snowing, and all three levels of ESB lights are lit up)
  • Simplicity - Nearly every single browser handles PNGs and variable opacity differently. With server side processing this becomes a non issue. Showing the picture is as simple as an image tag.

Advantages of client side compositing

  • Caching - This is huge. Even though the images are bigger and there are more of them, we only have to load them once. Just because the opacity of a layer changes as the day goes on doesn't mean we need to reload the image.

If the goal is to minimize bandwith and keep NewYorkOnTap.com's costs down, and browser load speeds fast then the right choice is a function of how many pages each visitor loads, and how many visitors are return visitors. Luckily those numbers are easy to garner from our logs. Since most visitors are return visitors, client side compositing is the way to go. Well, that is unless it snows a lot since the image for heavy snow is a painful 144k PNG.

However, for the image we share with the world the equation looks a little different. I have no idea what the usage pattern looks like, but I do know I'm not going to be able to do any real controled testing, it just needs to work. For that a server side solution is the way to go.


Doing the client side work

This can get tricky, especially considering that until version 7 IE hasn't natively supported PNG alpha channels. To show a tranparent PNG image in IE you've got to make use of the Microsoft proprietary AlphaImageLoader filter. To vary opacity you've got to use another proprietary Microsoft filter.

On top of that if you want to implement a javascript solution you've somehow got to get pull in the condition data. This means either making an AJAX call, or dynamically generating the Javascript file from a server side script. As fun as that sounds, there's a much simpler solution.

Dynamically Generated Conditional Style Sheets

Luckily, there's a an elegant solution to the problem. Internet Explorer allows you to conditionally declare a style sheet for IE only. Know, hacks, no convoluted if(isIE){ Javascript, just two seperate and distinct style sheets. One for IE and one for everybody else.

Our declaration looks like this:
<link rel="stylesheet" type="text/css" href="Weather.css">
<!--[if IE]>
        <link rel="stylesheet" type="text/css" href="Weather_ie.css" />
<![endif]-->
Both style sheeets, Weather.css and Weather_ie.css are generated at regular intervals by a program running on the server - in our case a .NET worker process, but it would be just as easy (but less efficient) to have the css be a direct call to a server side script (php, aspx, etc..) via @Import with something like this:
				
<style type="text/css">@import "weather.php";</style> 
The script queries the database and gathers info such as the time until sunset, weather conditions, etc and then creates an appropriate stylesheet.

Something like this (weather.css):
#skyline{background-image:url('images/Sunset.jpg');height:83px;width:929px}
#skyline2{background-image:url(images/Night.jpg');height:83px;width:929px;               -moz-opacity:.85; opacity:.85; -khtml-opacity:.85;} #weather1{background-image:url('weather/RainLight.png');height:83px;width:929px;}
and for Internet Explorer (weather_ie.css):
#skyline{background-image:url('images/Sunset.jpg');height:83px;width:929px}
#skyline2{background-image:url(images/Night.jpg');height:83px;width:929px;               filter:progid:DXImageTransform.Microsoft.Alpha(opacity=" & SkyOpacity & "); #weather1{background: none;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader
(src='images/rainLight.png',sizingMethod='scale');
height:83px;width:928px;}
These styles act upon a series of nested DIVs overlapping each PNG one on top of another and hopefully achieving a composite image that shares a few things in common with the real deal.
				
<div id=skyline>
	<div id=skyline2>
			<div id=weather1>
			</div>
		</div>
	</div>
</div>			
				


How about a server side solution?

A server side solution cuts through all the complexity above and leaves the client with nothing more complicated to resolve than a simple <IMG tag>. But now the difficulty is finding a free API to do the kind of heavy graphical lifting required. .NET has some pretty advanced graphical rendering abilities, but compositing multiple PNGs and returning a JPG is beyond its capacity. Luckily there's an open source solution to come to the rescue.
Image Magick, an amazingly robust command line graphic manipulater with a GPL compatible license does a beautiful job of compositing the images.
composite -blend [opacity] images\Night.png images\Sunset.png Skyline.png
composite Skyline.png images\RainLight.png Skyline.png
composite Skyline.png Skyline.jpg
A script that creates and executes a batch file containing commands similar to the one above should be all that's necessary. It's the technique used to create the picture you can add to your own site, and the resulting image ends up being <9k.


Sheesh...and I thought this was an original idea

When I started this project I was sure someone must have done something similar to this, but all the Google searches I could come up with turned up nothing, and I was starting to actually feel pretty cutting edge. Then as I was doing this very write up I did a Google search for the syntax of the @import directive and lo and behold I found Dunstan Orchard's blog. He built his panorama of his parents home in Dorset, England over 5 years ago! Of course it's not exactly the same since he uses 90 hand drawn images instead of overlaid PNGs, but what beautiful images!
<- Back to what can it do       Check out the subway/bar map AJAX craziness ->