rss
amazon
    javod.combottom
Two methods for circular overlays with Google Maps sunday, 21st june

Here are two examples of how to create a circular overlay using the Google Map's API. One method involves creating a circular polygon, and I know I've pulled this knowledge from some random site a while back, but for the life of me I can't figure out where. I did a google search using some of the code as the query, but the earliest post I could find containing the code was a post I made on a Google group discussion board.

Both of the maps use version 2 of the API. I was going to rewrite the code using the recently released version 3, but according to a member of Google's development team, version 3 is not meant as a replacement for 2. It's meant to be used as an MVC framework focusing on mobile devices. The feature set on 3 is way behind that of 2 as well... just food for thought.

Demo of Map1, created using a polygonal approach.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Google Maps Circular Polygon Example</title>
     <script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=YOUR_KEY_GOES_HERE" type="text/javascript"></script>
    <script type="text/javascript">
    //<![CDATA[
	
	// This is the initialized function when the document loads
    function load() {
	
	  // he Maps API provides a global method (GBrowserIsCompatible()) to check compatibility
	  // but it does not have any automatic behavior when it detects an incompatible browser
      if (GBrowserIsCompatible()) {
		 
		 // create new map with element id = map
        var map = new GMap2(document.getElementById("map"));
		//set center of map, along with zoom level
        map.setCenter(new GLatLng(36.0713471, -97.15), 9);
		
		//Creates a new 3D-style control with buttons to pan in four directions, and zoom in and zoom out, and a zoom slider
		map.addControl(new GLargeMapControl3D());
		map.addControl(new GMenuMapTypeControl());
		
		// Perkins, OK - marker	
		var marker = new GMarker(new GLatLng(36.0713471, -97.15));
		map.addOverlay(marker);

		//Perkins, OK - circle center (in this case it is the same as the marker location, we're creating our circle around our marker)
		var center = new GLatLng(36.0713471, -97.15);
		// Although our calculations are technically in kilometeres, we input it here in miles.
		// We convert this number in the next step to accurately reflect our desired output.
		var radius = 10;
	
		//convert kilometers to miles-diameter
		var radius = radius * 1.609344;
		
		// The offset creates an, ummm... offset around the center to help build the polygon
		var latOffset = 0.01;
		var lonOffset = 0.01;
		var latConv = center.distanceFrom(new GLatLng(center.lat()+0.1, center.lng()))/100;
    	var lngConv = center.distanceFrom(new GLatLng(center.lat(), center.lng()+0.1))/100; 
		
		// nodes = number of points to create polygon
		var nodes = 40;
		
		// Create an array of points
        var points = [];
		
		// set the amount of steps from node
        var step = parseInt(360/nodes);
        
		// the for loop creates a series of points that define the circle, counting by the amount of steps, by 9 in the case of 40 nodes
		for(var i=0; i<=360; i+=step){
			var point = new GLatLng(center.lat() + (radius / latConv * Math.cos(i * Math.PI / 180)), 
						center.lng() + (radius / lngConv * Math.sin(i * Math.PI / 180)));
			// push "point" onto the points array 
			points.push(point);
        }//end for statement
		
		// GPolygon creates a polygon from an array of vertices, in this example, points is our array
		// GPolygon(array of points, stroke color, stroke weight(from 0-1), stroke opacity(from 0-1), fill color, fill opacity (from 0-1))
		var polygon = new GPolygon(points, "#f33f00", 1, 1, "#ff0000", 0.1);
    	map.addOverlay(polygon); 
		}//end if statement
	}//end function load

	//]]>
    </script>
  </head>
  <body onload="load()" onunload="GUnload()">
  	<p style="font-weight:bold">This is our map using a polygon to create a circle</p>
  	<!-- using the element id "map" we will set the map in a div tag -->
    <div id="map" style="width: 500px; height: 400px"></div>
    
  </body>
</html>

 

Demo of Map2, created using a transparent image (PNG) overlay with the GGroundOverlay() function.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Google Maps Circlular Image Ground Overlay Example</title>
     <script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=YOUR_KEY_GOES_HERE" type="text/javascript"></script>
    <script type="text/javascript">
    //<![CDATA[
	
	// This is the initialized function when the document loads
    function load() {
	
	  // The Maps API provides a global method (GBrowserIsCompatible()) to check compatibility
	  // but it does not have any automatic behavior when it detects an incompatible browser
      if (GBrowserIsCompatible()) {
		 
		// create new map with element id = map
        var map = new GMap2(document.getElementById("map"));
		//set center of map, along with zoom level
        map.setCenter(new GLatLng(36.0713471, -97.15), 9);
		
		//Creates a new 3D-style control with buttons to pan in four directions, zoom in and zoom out, and a zoom slider
		map.addControl(new GLargeMapControl3D());
		map.addControl(new GMenuMapTypeControl());
		
		// Perkins, OK - marker	
		var marker = new GMarker(new GLatLng(36.0713471, -97.15));
		map.addOverlay(marker);

		// sw and ne are the lower and upper bounds of the box that we define our overlay image: in GGroundOverlay
		// Finding the correct coordinates for an image's bounding box can be a bit tricky, we'll tackle that one some other day.
		var sw = new GLatLng(35.904625,-97.327881);
		var ne = new GLatLng(36.206607,-96.965332);
		
		//Perkins, OK - PNG image overlay
		var groundOverlay = new GGroundOverlay("http://www.javod.com/blog/files/images/circle_marker.png", new GLatLngBounds(sw, ne));
		map.addOverlay(groundOverlay); 

		
		}//end if statement
	}//end function load

	//]]>
    </script>
  </head>
  <body onload="load()" onunload="GUnload()">
  	<p style="font-weight:bold">This is our map using a PNG file as a ground overlay</p>
  	<!-- using the element id "map" we will set the map in a div tag -->
    <div id="map" style="width: 500px; height: 400px"></div>
    
  </body>
</html>

Although Map2 looks much easier to implement, I must caution that currently there does not seem to be an easy way to determine the bounding box for the image. I used a topography program to estimate the southwest and northeast points. Not entirely successful either I may add, since my coordinates were circular, and I was trying to find the square points. The image itself will scale according to the bounding box, which is convenient. Another thing to consider: the png file we've loaded has a transparency of 25%, we're not defining the transparency in the code, as we did with the polygon.

Run times are another concern. I tested both maps and although Map2 was a smaller size than Map1 (about 1KB smaller), the load times were about the same. I'm inclined to believe, that if we had numerous circles, Map2 would win out purely on computational merit. But with the increased speeds of javascript engines on browsers, and depending on how many images we're loading and how they're cached (is one image loaded once and re-used, or is it loaded everytime... I don't have an answer to that) I could be wrong.

Please feel free to leave me a note with any questions or comments!


[tagsgoogle-maps javascript]
» comment on this entryread comments, (0)

Palm Pre template for screen protector thursday, 11th june
Palm Pre TemplateAfter waiting for about two and half years since my last phone purchase for a good camera phone to come out for the Sprint network, the Palm Pre has arrived. The picture quality is by far the best I've seen on any phone offered by Sprint.

I've signed up to be informed as soon as the development kit for the Pre gets released, and have some ideas about different apps to develop. (Keep posted for some tutorials as well.)

In the meantime however, and off-topic, I wanted to help protect my phone from scratches, so I purchased a screen protector. The kind you cut yourself to fit your phone. I'm a little bit obsessive about these things, so I precisely measured the dimensions and mocked up a quick template in adobe illustrator. Then, I printed it on some paper, and just followed the lines using scissors and an x-acto knife.

I figured someone else might find it handy so here it is:

EPS File - 1.14MB
PDF File - 239KB

[tagspre phone templates]
» comment on this entryread comments, (0)

Vista RSS Gadget Tutorial friday, 5th june

This is a small tutorial on something I struggled with for a few days: creating an RSS feed for a Vista gadget. I make a couple of assumptions in this tutorial:

1) You are at least a little familiar with HTML, CSS and Javascript. If you aren't but have a good eye for code, you should be able to work things out anyway.
2) You know the basic construct of a gadget. If you don't, a very simple tutorial can be found at Technical Architecture Worx

A gadget at its simplest form consists of an XML definition file called a manifest and an HTML page. The XML file contains the settings of your gadget while the HTML file is what's actually displayed to the user.

In my quest to write a gadget that displayed an RSS feed I came across a few tutorials, but they were either very convoluted or disjointed. (I came across one tutorial that had about three layers of abstraction just to use ActiveX to access a feed. Ridiculous.) So after reading a bunch of different tutorials (not one of them addressing what I really wanted) I created an RSS gadget for myself. Thinking I may need the code for future use, I stripped it down to a minimum so I could easily incorporate it into another project should I need to in the future.

Here is a zip file with all the code and images.

// page = determines what content goes into what cells on main.html
// In addition we use page to number our pages within the gadget
var page = 0;
// numpages = number of pages that we can sift through on gadget.
var numpages = 3;
// displayPerPage = How many items to display per page on the gadget. 
// The number of columns in the main.html table will need to correspond to this number 
var displayPerPage = 3;

// called onLoad in body tag of main.html
function setup() {
	getRSS();
	window.setInterval(getRSS, (5 * 60000));	
}

// getRSS loads the feed
function getRSS() {
	loading.innerText = "Connecting...";
	
	// XMLHttpRequest allows HTTP client functionality, such as loading data from a server. 
	// It's important to note that while this will work in a vista gadget for accessing remote sites,
	// in browsers, XMLHttpRequest can only access local domains 
	var request = new XMLHttpRequest();
	
	// ActiveXObject is an IE 6.0 version of XMLHttpRequest
	// (IE 6 and below did not use w3 standards for the XMLHttpRequest object) 
	// This is just here for personal-edification.
	// request = new ActiveXObject("Msxml2.XMLHTTP");
	
	// Open the client "request" using GET, followed by the URL we are getting. 
	// The third argument being passed defines whether the method is
	// asynchronous (true - method sends the request to the server and then responds immediately) or 
	// synchronous (false - does not return until the server responds).
	request.open("GET", "http://www.javod.com/blog/feeds/rssblog.php", true);
	request.onreadystatechange = function() {
		// if the request is finished
		if (request.readyState === 4) {
			// it was succussful
			if (request.status === 200) {
				// Here we display the server's response
				loading.innerText = "";		
				// ResponseXML property returns an XML document object: bascially returns values in XML format
				rssXML = request.responseXML;
				parseRSS();
				if (checkCon) { clearInterval(checkCon); }
			} else {
				var checkCon;
				// innerText functions similarly to innerHTML with the important distinction
				// that innerText does not render HTML
				// If we can not connect to the feed, display (...)
				loading.innerText = "Unable to connect...";				
				checkCon = setInterval(getRSS, 30000);
			}
    	} else {
			// gets displayed if readystate has not returned
			loading.innerText = "Connecting...";
		}
	}	
	// Sends the request to the server.
	// The argument to the send function is the body of the request,
	// with GET requests it is always null.
	request.send(null);
}

// pageNo calculates the current page being displayed in the gadget
function pageNo(offset) {
    page = (page + numpages + offset) % numpages;
    parseRSS(page);
}

// parseRSS gets the actual data from the feed. 
function parseRSS(page) {
	if (!page) { 
		page = 0; 
	}
	start = page * displayPerPage;
	end = (page * displayPerPage) + displayPerPage;
	rssItems = rssXML.getElementsByTagName("item");
	rssTitle = null; rssDates = null; rssDate = null; rssLink = null;
	
	for (i=start; i<end; i++) {
		rssTitle = rssItems[i].firstChild.text;
		rssDate = rssItems[i].getElementsByTagName("pubDate"); rssDate = rssDate[0].text.split(" ");
		rssDate = rssDate[0] + " " + rssDate[1] + " " + rssDate[2];

		rssLink = rssItems[i].getElementsByTagName("link"); rssLink = rssLink[0].text;
		cell = i - (page * displayPerPage);
		// innerHTML defines both the HTML code and the text that occurs between that element's opening and closing tag. 
		document.getElementById("cell" + (cell)).innerHTML = '<div onclick="System.Shell.execute(\'' + rssLink + '\');">' + rssDate + '<div class="title">' + rssTitle + '</div></div>';
		document.getElementById("cell" + (cell)).title = rssTitle;
	}
	// displays the current page number and the total number of pages
	pageNum.innerText = (page + 1) + "/" + numpages;
}
For the javascript, I've commented on most of the items I think might cause any confusion. Really, "out of the box", there are only three variables that might need changing. numPages, displayPerPage, and the actual feed location located in the getRSS function.
<html>
<head>
<title>Javod's Feed</title>
<link href="style.css" rel="stylesheet" type="text/css">
<script src="main.js" type="text/javascript"></script>
</head>
<body onmouseover="this.focus();" onmouseout="" onLoad="setup()">
<div id="content">
  <table width="100%" border="0" cellpadding="0" cellspacing="0">
    <tr>
    
    <td valign="middle" onmouseover="this.style.background='url(images/shade.png)';" onmouseout="this.style.background='none';"><div class="sub" title="Hello" id="cell0"></div></td>

    </tr>
    <tr>
      <td valign="middle" onmouseover="this.style.background='url(images/shade.png)';" onmouseout="this.style.background='none';"><div class="sub" id="cell1"></div></td>
    </tr>
    <tr>
      <td valign="middle" onmouseover="this.style.background='url(images/shade.png)';" onmouseout="this.style.background='none';"><div class="sub" id="cell2"></div></td>
    </tr>

	
  </table>
</div>
<div id="pageNumLoc">

  <table width="100%" border="0" cellpadding="0" cellspacing="0">
    <tr align="center" valign="middle">
      <td width="10" class="pageNumStyle" onclick="pageNo(-1);" align="right">«</td>
      <td id="pageNum" class="pageNumStyle">Loading...</td>
      <td width="10" class="pageNumStyle" onclick="pageNo(+1);" align="left">»</td>

    </tr>
  </table>
</div>
<div id="loading">Loading...</div>
</body >
</html >
The HTML page is pretty straighforward. I will point out that the number of table rows need to be adjusted according to the number that was put in the javascript variable for displayPerPage.

And finally the CSS that helps lay it all out, the XML manifest file, and the corresponding images are in the zip file.


[tagsgadgets javascript rss]
» comment on this entryread comments, (0)


xhtml valid