Dynamic Google Maps circle markers/icons with PHP

A while back I posted on how to create dynamic Google maps markers which allow for any colour and any text in the classic Google map style.

Recently, I have had a need to do the same with circular markers. It uses the ‘Image Smooth Arc‘ function provided by Ulrich Mierendorff.

Similarly, I provide a little demo of some PHP code that does this that I quickly whipped up. Here are some example markers:
DefaultAZ110PQ69%BEΩ$
(Have a look at the image name)

Now that gets a little boring, how about some color:
DefaultAZ110PQ69%BEΩ$
(Again, have a look at the image name)

Again, you will need to download the modified arial font and host it in the same directory.

Have a look at the PHP source code below:

<?php
	include ("imageSmoothArc_optimized.php");

	$color = $_GET['color'];
	if (!$color) {$color = "ff776b";} //default google map color
	$color = str_replace("#", "", $color);
	$string = $_GET['text'];

	$font = realpath('arial.ttf');

	//unfortunately we still must do some offsetting
	switch (ord(substr($string,0,1))) {
		case 49: //1
			$offset = -2;
			break;
		case 55: //7
			$offset = -1;
			break;
		case 65: //A
			$offset = 1;
			break;
		case 74: //J
			$offset = -1;
			break;
		case 84: //T
			$offset = 1;
			break;
		case 99: //c
			$offset = -1;
			break;
		case 106: //j
			$offset = 1;
			break;
	}
	if (strlen($string) == 1) {
		$fontsize = 10.5;
	} else if (strlen($string) == 2) {
		$fontsize = 9;
	} else {
		$fontsize = 10.5;
		$offset = 0; //reset offset
		$string = chr(149);
	}

	$bbox = imagettfbbox($fontsize, 0, $font, $string);
	$width = $bbox[2] - $bbox[0] + 1;
	$height = $bbox[1] - $bbox[7] + 1;

	$im = imagecreatetruecolor(20, 20);

	//add the alpha
	$trans_colour = imagecolorallocatealpha($im, 0, 0, 0, 127);
	imagefill($im, 0, 0, $trans_colour);

	imageAlphaBlending($im, true);
	imageSaveAlpha($im, true);

	$bord_ellipse = array (0, 0, 0, 0);
	imageSmoothArc($im, 9, 10, 17, 17, $bord_ellipse, 0, 2*M_PI); //x, y, width, hegiht

	$fill_ellipse = array (hexdec(substr($color,0,2)), hexdec(substr($color,2,2)), hexdec(substr($color,4,2)), 0);
	imageSmoothArc($im, 9, 10, 16, 16, $fill_ellipse, 0, 2*M_PI); //x, y, width, hegiht

	$black = imagecolorallocate($im, 0, 0, 0);
	imagettftext($im, $fontsize, 0, 11 - $width/2 + $offset, 9 + $height/2, $black, $font, $string);

	header("Content-type: image/png");
	imagepng($im);
	imagedestroy($im);
?>

EDIT: 8 September 2014
Fixed a “Call-time pass-by-reference has been removed” error with ‘imageSmoothArc_optimized.php’. If you are experiencing the same with imageSmoothArc simple replace all instances of ‘&$’ with ‘$’.

Dynamic Google Maps markers/icons with PHP

I am a avid fan of Google’s Map API, have even have created my own WordPress Google Maps plug-in (thydzikGoogleMap), but one feature that I find lacking are customisable markers, with the need to include an image file for every customisable marker, now if you want a selection of colours and labels this creates a huge image database.

Google has gone in the right step their MapIconMaker allowing very customisable markers using the Charts API marker output. But why not take this a step further and add dynamically generated text as well.

Hence, I provide a little demo of some PHP code that does this that I quickly whipped up. Here are some example markers:
DefaultAZ110PQ69%BEΩ$
(Have a look at the image name)

Now that gets a little boring, how about some color:
DefaultAZ110PQ69%BEΩ$
(Again, have a look at the image name)

Unfortunately, not all symbols work (not sure why, even though they are in the font) and if the symbol doesn’t work it will default to the default bullet (this is done with a modified font file).

Also there may be an issue with alignment. All main characters 0-9 and A-Z; I have added manual offsets, this could be improved.

You will need to download the modified arial font and host it in the same directory.

Update: it looks like in Internet Explorer the transparencies are incorrectly displayed, this is not the case when displayed on a Google Map.

Have a look at the PHP source code below:

<?php
	 $color = $_GET['color'];
	 if (!$color) {$color = "ff776b";} //default google map color
	 $color = str_replace("#", "", $color);
	 $string = $_GET['text'];

	 //some smarts to prevent hotlinking
	 if (!stristr($_SERVER['HTTP_REFERER'], "thydzik.com")) {
		$string = chr(169);
	 }
	 $font = 'arial';

	 //unfortunately we still must do some offsetting
	 switch (ord(substr($string,0,1))) {
		 case 49: //1
			$offset = -2;
			break;
		 case 55: //7
			$offset = -1;
			break;
		 case 65: //A
			$offset = 1;
			break;
		 case 74: //J
			$offset = -1;
			break;
		 case 84: //T
			$offset = 1;
			break;
		 case 99: //c
			$offset = -1;
			break;
		 case 106: //j
			$offset = 1;
			break;
	 }
	 if (strlen($string) == 1) {
		$fontsize = 10.5;
	 } else if (strlen($string) == 2) {
		$fontsize = 9;
	 } else {
		$fontsize = 10.5;
		$offset = 0; //reset offset
		$string = chr(149);
	 }

	 $bbox = imagettfbbox($fontsize, 0, $font, $string);
	 $width = $bbox[2] - $bbox[0] + 1;
	 $height = $bbox[1] - $bbox[7] + 1;

	 $image_name = "http://chart.apis.google.com/chart?cht=mm&chs=20x34&chco=$color,$color,000000&ext=.png";
	 $im = imagecreatefrompng($image_name);
	 imageAlphaBlending($im, true);
	 imageSaveAlpha($im, true);
	 $black = imagecolorallocate($im, 0, 0, 0);

	 imagettftext($im, $fontsize, 0, 11 - $width/2 + $offset, 9 + $height/2, $black, $font, $string);

	 header("Content-type: image/png");
	 imagepng($im);
	 imagedestroy($im);
?>

EDIT: 27th January 2010

I have experienced some users with errors produced by the imagecreatefrompng, either due to versions <4.3.0 disabling remote file access or allow_url_fopen being disabled.

A greater supported alternative is to use curl to fetch the Google marker. Replace the above with the below modification;

	$image_name = "http://chart.apis.google.com/chart?cht=mm&chs=20x34&chco=$color,$color,000000&ext=.png";

	$ch = curl_init();
	curl_setopt ($ch, CURLOPT_URL, $image_name);
	curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 0);

	// Getting binary data
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);

	$image_string = curl_exec($ch);
	curl_close($ch);

	$im = imagecreatefromstring ($image_string);

EDIT: 30th November 2011

Hosting of these dynamic markers, linked on NumericIcons is using all my allocated hosting server resources. I have modified the script to redirect to Google’s dynamic markers (yes, Google has the equivalent) hopefully that will take some of the load off, and I won’t need to remove it totally.

They look slightly different to mine;
DefaultAZ110PQ69%BEO$

DefaultAZ110PQ69%BEO$

	if (!$color = $_GET['color']) {
		$color = "ff776b"; //default google map color
	}
	$color = str_replace("#", "", $color);
	
	if (!$text = $_GET['text']) {
		$text = "%e2%bc%80"; //default google map icon
	}
	
	header("Location: http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld={$text}|{$color}|000000&.png");

EDIT: 6 December 2011
I now have implemented an Apache Mod_Rewrite solution, which will take all load off the php processing, existing users should see no difference.

RewriteCond %{QUERY_STRING} ^text=([^&]*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%1|ff776b|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} ^color=([^&]*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=â¼€|%1|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} ^text=(.*)\&color=(.*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%1|%2|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} ^color=(.*)\&text=(.*)$
RewriteRule ^thydzikGoogleMap/markerlink\.php$ https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%2|%1|000000&.png? [R,L]

RewriteCond %{QUERY_STRING} =""
RewriteRule ^thydzikGoogleMap/markerlink\.php$ https://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=â¼€|ff776b|000000&.png? [R,L]

EDIT: 14 September 2014
Unfortunately I have had to remove all working examples, as those that were hot-linking to the markers directly were causing server loading, which Hostgator doesn’t like.

thydzik Google Map version 1.4.6.1

Latest offering has cleaned up JavaScript, improved error handling, improved RoboGEO handling of XML, but main features are.

  • Icons now support letters ‘A’ to ‘Z’.
  • Non clickable markers if no ‘html’ element is present.

In the below example Marker Z is not clickable.

thydzikgooglemap(example.xml)

Download the latest from the WordPress repository.