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$ http://chart.googleapis.com/chart?chst=d_map_pin_letter&chld=%1|ff776b|000000&.png? [R,L]

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

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

RewriteCond %{QUERY_STRING} =""
RewriteRule ^thydzikGoogleMap/markerlink\.php$ http://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.

  • Lai

    Hi, I wanna ask about the color selection on the placemarker for my maps…I find it’s a bit difficult for me to change the color selection from red to white…even I tried many times. That’s the problem for me and I’m not so keen in computer..

  • thydzik

    Hi Lai

    What maps are you referring to? as these Google maps using my WordPress plugin, or a separate Google map, can you provide a link?

    If it is the later, than unfortunately, with out being ‘so keen in computer’ it will be a little hard for you.

  • Joe Pea

    Hey, about hosting fonts on a server… How do I do that? Can I display custom fonts on my website without other having the font?

    Thanks! -Joe

  • Joe Pea

    Without othes having that font on their computer, i mean?

  • thydzik

    Joe,

    Not quite following. You will need the font uploaded onto your web server to display custom text on the markers.

  • Domingos

    Thydzik,
    Thanks for sharing this code with the comunity. That is what i was looking for months!
    About the icon size, is there any way to change it?
    Because when i try to change the parameter CHS on the png address, it doesnt change the size and bugs out the text on the icon.
    Again, thanks for this great code.

    Regards.

  • thydzik

    Domingos,

    I haven’t implemented the icon size CHS as a parameter, mainly as I like to use the default size.
    This could be changed fairly easy though.

  • Domingos

    Thydzik,
    Thanks for your reply.
    I think the original size is great, but when i implement your code to auto-generate a sequence of markers into my map (number is generated inside the javascript google map api) the icon size turns way too small.
    Take a look: http://img526.imageshack.us/my.php?image=mapv.jpg
    Any hints?
    Thank you.

    Regards.

  • thydzik

    Domingos, I’m not too sure.

    The PHP code should produce default sized markers, if you bring up just the marker image in a browser is it the correct size?

    In the JavaScript, how are you declaring your new marker icons? do you either define the size or copy the Google default marker as a base?

  • Domingos

    Thydzik,

    Yes, if i bring up the marker image in a brower it shows the correct size.

    Im declaring the icon with this method:
    iconRed.image = ‘http://www.mydomain.com/map/marker.php?text=’ + i + ‘&color=CD0000’;
    iconBlue.image = ‘http://www.mydomain.com/map/marker.php?text=’ + i + ‘&color=6b98ff’;

    So each time the gmap api insert a mark, it raise its number.
    Im didnt define any size for the icon.
    The image that im using is the same one that is used in your code:
    $image_name = “http://chart.apis.google.com/chart?cht=mm&chs=20×34&chco=$color,$color,000000&ext=.png”;

  • thydzik

    it should work, from my experience all you need to do is declare the icon as a default Google icon and then update the marker, i.e.

    iconRed new GIcon(G_DEFAULT_ICON);
    iconRed.image = ‘http://www.mydomain.com/map/marker.php?text=’ + i + ‘&color=CD0000′;

    given you are using the default size of the Google default icon the size should be the default size.

    but perhaps, if still no luck try
    iconRed.iconSize=new GSize(20, 34);

  • Domingos

    Thydzik,
    Thank you so much! It worked!
    All i had to change was iconRed.iconSize=new GSize(20, 34);
    Again, thanks for your great work!

    Best regards.

  • Hi, i worked with this fine locally using apache server, now I deployed to a iis with php5 and it does not shows the icon, move the code to a host that uses linux apache and there it shows.

    is there a workaround to make it work with IIS

    thanks

  • thydzik

    Norman,

    I believe this is a problem with the location of the font file. If you comment out header("Content-type: image/png"); you will see the error message.

    Try replacing the line $font = 'arial'; with $font = realpath('arial.ttf');

    Please let me know if this works.

  • Hi thanks Thydzik, but no error or image, here is the url

    http://74.208.77.78/ecutrak_api/gicon.php?text=A1&color=FFAAFF

    and here is phpinfo()
    http://74.208.77.78/ecutrak_api/info.php

    thanks

  • thydzik

    Norman,

    I am not sure, try coding a very basic image using the PHP image functions and adding more onto that.
    Try the example here
    http://au2.php.net/manual/en/function.imagecreate.php

  • Daryl733

    Anyway to make the color of the icon blick ?

  • thydzik

    the icon blink or black?

    black yes, blink maybe, but not sure how.

  • Hello

    I am wondering if we may directly link to your php files for our own icons ? Because it uses your bandwidth.

    I want to explain how to use your icons on my icon collection project : http://code.google.com/p/google-maps-icons/wiki/NumericIcons

  • thydzik

    Nico,

    Not a problem, but please link to this one
    http://thydzik.com/thydzikGoogleMap/markerlink.php?text=%BE&color=cb9d7c

    (changing the parameters as you wish)

    Travis

  • Hello Travis,

    Thanks for the tip.
    I explained it all, in relation with my project on the page : http://code.google.com/p/google-maps-icons/wiki/NumericIcons

    I linked/credited your work. Hope it’s Ok with you. If not, just tell me and I will remove :)


    Nico

  • thydzik

    Thanks for that.

    I have added some smarts to the php code to only allow google.com to view it correctly.

  • What if people use google in other language ? url would be maps.google.fr for the french like me.

    But it looks like I can’t link to the icons from maps.google.com either.
    It says “impossible to contact the server” when I try to save a placemark with an icon in thydzik.com/*

    Am I doing something wrong ?

  • thydzik

    I thought of that (and tried it), but I don’t think there is the equivalent Google code for other countries/languages.

    Hot linking of the images will still work (the code.google.com page still works), and saving them works. However, if you hot link on another domain, it will work but come up as a © (copyright) symbol.

    If people want the functionality, it is very easy to copy the php onto their server.

  • Ok I see, so it’s not possible to hot link from my personnal maps.google.com to thydzik.com

    The only way is to host the php file. Unfortunately, for users like me who don’t have a server, it’s a little problem :)

    Anyway, thanks a lot. I will keep my tutorial of your icons, for people who have a host.

  • thydzik

    What is your personal maps.google.com?

    I wasn’t aware of being able to add user defined icons to the maps.

    But, essentially, if the domain has ‘google.com’ in it, it will work.

  • For example this public map I created :
    http://maps.google.com/maps/ms?ptab=2&ie=UTF8&oe=UTF8&msa=0&msid=105794763617951274407.00045e3fe0d0cbe3e88e7

    I checked with Safari what URLs can call files.
    Maybe the other Google domains gmodules.com and gstatic.com need to be autorized as a referer too.

  • thydzik

    Nico,
    Thanks for the info.

    Wasn’t apply to get your link working, but tried out the Google My Maps functionality with the markers and it worked no problems.

    I have also added gmodules.com and gstatic.com incase.

  • Strange, I tried today, to add a custom icon, like he other day.

    This time, I can save the place, with a thydzik.com/* icon… But it has the copyright symbol, even if I am on maps.google.com/maps (not the google.fr domain).

    There ain’t no copyright symbol for you, I assume ?

  • thydzik

    I have removed that hotlinking code, should all work fine now.

  • @thydzik : I desist :(

    I don’t know if I am doing something wrong.

    1/ I am on the maps.google.com in english

    2/ I add a placemark to “My maps” : I take one of your examples : http://thydzik.com/thydzikGoogleMap/marker.php?text=A&color=c89bff

    3/ The icon has a copyright symbol

    4/ I manage to save the place

    … but there are copyright everywhere…
    Are you sure you cut the hotlinking code ?
    Sorry to bother you

  • thydzik
  • Well, I didn’t see you used another URL. The hotlinking removal worked. The copyright symbol is not there anymore.

    But the save bug is still here, and from what I saw on google forums (http://groups.google.com/group/google-chart-api/browse_thread/thread/b1c31d83598bb9ee), what I want (adding dynamic icons manually, in My maps), cannot be done.

    In conclusion : dynamic icons is only for Google maps API.

    Thanks for time you used on this tests.
    Regards

    Nico

  • Meena

    Hi,
    How would I add my own image marker.
    Is there anyone to help me.

    Thanks,
    Meena

  • Nick

    I’m not good with php..
    I have installed an apache on winxp.
    I have copy and paste the php code in a file named marker.php on the root directory, and copied also in the same directory arial.ttf.

    I have comment also the code of the site.
    //some smarts to prevent hotlinking
    // if (!stristr($_SERVER[‘HTTP_REFERER’], “thydzik.com”)) {
    // $string = chr(169);
    // }

    If I try to make a http://nick/marker.php?text=A it doesn’t work.

    Where is my mistake?

    Thanks for help
    Nick

  • Nick

    here is the HTML file.

    You (c) works, mine doesn’t :(

    Thanks again
    Nick

  • Nick

    IMG SRC=”marker.php?text=A”

    IMG SRC=”http://thydzik.com/thydzikGoogleMap/marker.php?text=69&color=ffed5c”

  • thydzik

    Nick,

    Hard to say, without a global link I can view. (http://nick/marker.php?text=A doesn’t work)

    What happens when you go to marker.php on your server?

    Blank page, php error message, just displays as text?

  • nick

    Hi thydzik,
    actually I have blank page…

    Thanks
    Nick

  • nick

    If I run the page alone this message appear (without including it in a img src):

    marker.php?text=A

    the browser says :

    The image “http://NICK/marker.php?text=A” cannont be displayed because contains some errors.

    maybe some error in the location of the source image??

    http://chart.apis.google.com/chart?cht=mm&amp;;chs=20×34&chco=$color,$color,000000&ext=.png

    Thank You Again

  • nick

    Hi thydzik,
    I found the error :)

    It is the ; in the URL from google apis after mm&, it must be deleted.

    The right URL to put in the code is this.

    http://chart.apis.google.com/chart?cht=mm&chs=20×34&chco=$color,$color,000000&ext=.png

    Thanks Again
    Nick

  • jesu

    Hi thydzik,
    I’ve tried to download the arial.ttf file that is hosted on this page, but it seems to be corrupt and therefore I can’t display and characters over the marker!
    Please help!

  • thydzik

    jesu, I have confirmed that Windows won’t open the font file (it produces an error), but it will still work with the code.

  • Nice job, but google has its own method to build custom icons.

    See here:
    http://groups.google.com/group/google-chart-api/web/chart-types-for-map-pins?pli=1

    Cheers

  • @Koen (December 23, 2009 at 7:33 pm)
    thydzik did a fantastic job!
    The Google method you mention does not apply to Google “My Maps” as it cannot be saved (googlit for users’ issues or just try) but thydzik’s does!!! This is critical because most of people use only “My Maps” to create maps stuffed with lots of info.

    The key issue with Google method is that provides the url with some “|”s which “My Maps” do not accept (during “save”).

    I am not familiar with php and I will use thydzik’s page like this:
    http://thydzik.com/thydzikGoogleMap/marker.php?color=fdabff&text=a

  • Oz

    Labeled Marker sample … have a look guys… something fantastic..
    set text functionality of marker.

    var marker = new LabeledMarker(myPoint, {icon: myIcon, labelText: “A”});

    http://googlemapsapi.blogspot.com/2007/04/labeledmarker-v10-do-more-with-your.html

  • I’m having some troubles getting this to work – the way I need.

    I have the php set up on my server and it does work:
    http://digitalarborist.com/markers.php?text=1&color=97ec7d

    I have a map that I use to display tree locations:
    http://digitalarborist.com/maps/index.php

    My webmap accepts variable f=’feed url’. I have a script that creates a kml feed dynamically. My script contains this code (coldfusion):

    #placeName#
    #placeDescription#
    #th_id#
    #formatIconUrl#

    #getTreeHistory.th_gps#

    The map correctly draws the points on the map with info displayed in the infowindow, but the dynamic icons are not there, just default blue with dots. Example from dynamic feed:
    http://digitalarborist.com/maps/?f=http%3A%2F%2Fwww.austintreeexperts.com%2Fkml-rss.cfm%3Fu%3D558%26ad%3D23719

    Any help would be much appreciated.

  • keith,

    I haven’t tried kml files before. but two things to try;
    your source has ‘&amp ;’ in the marker html, try removing that.

    also try appending ‘&.png’ to the end.

  • kml is xml doctype so ‘&’ symbols have to be encoded or gmaps won’t display any markers at all. Maybe I need to edit the icon generating script so that text and color are passed as one variable and the php cuts it apart to create the $text and $color variables. If color was always passed first it could work since the first 6 characters in the string go to $color and the rest goes to $text. I’m no good at php so this will take me some time to figure out. If is easy for you, would you be willing to help?

  • keith,

    I think it is something else. You have used static markers 1green.png, yet it is still generating the blue bullet ones. I can’t see where you have set this?

    The default marker should be a red bullet, not a blue bullet so it looks like the markers are from a different source.

  • The blue marker is google maps default; not coming from marker.php.

    You are right. I wrote the marker.php file as described above to get the & symbol out of the in my kml and still not working.
    http://digitalarborist.com/new_markers.php?icon=97EC7D6

    I tried adding &.png to the end of url call and it short-circuits the feed (nothing displays). The & symbol cannot appear anywhere in the feed or google maps won’t display the kml.

    I added an image to the description box to confirm that I got some sort of image to load, and it worked:
    http://digitalarborist.com/maps/?f=http%3A%2F%2Fwww.austintreeexperts.com%2Fkml-rss.cfm%3Fu%3D684%26ad%3D29927

    But, still no luck on the dynamic icon.

  • keith,

    first try it with static markers. I have seen the 1green.png marker in the kml, but not working on the google map.

  • Got it! It was formatting problems with my kml. I was trying to embed IconSyle tag inside placemark tag instead of inside Style tag.

    It was an issue having & symbol in kml file as kml is xml and must be encoded. I changed my php marker script to accept one variable where first six characters in string are $color and any remaining characters are $string:

    $color = substr($_GET[‘icon’],0,6);
    $string = substr($_GET[‘icon’],6);

    Working good now!:
    http://digitalarborist.com/maps/?f=http%3A%2F%2Fwww.austintreeexperts.com%2Fkml-rss.cfm%3Fu%3D684%26ad%3D29927

  • One other thing about kml files in google maps. The smarts to prevent hotlinking in the marker.php file does not work for kml. Google maps actually retrieves your icon images from Google’s servers and sends them to the map with the map tiles as one big overlay (they are not conventional map markers).

  • I want to display all parameters between two location with distance and driving hours. if it possible

  • Karry

    Hi i tried to execute the above code but i was unable to do it. how to run the above code on a local server in my college campus because we are not allowed to access http://thydzik.com. Any help is appreciated..

  • Karry,

    You need to copy the code to a php file and install it on your web server. You will also need to include the modified Aerial font to the same directory.

  • Karry

    Hi i copied the font file, made a php file of the code above and put them in www directory but when i executed the local web page the page was appearing blank, i am using Wampp server, Evey i passed the address bar parameters test.php?text=8&color=#551A8B to it but it didnt work, when i didnt pass tha parameters then this is the error “Notice: Undefined index: color in C:\wamp\www\t2.php on line 1” please help me..

  • Karry

    This was the new error The image “http://localhost:8080/t2.php?text=8&color=#FF34B3” cannot be displayed, because it contains errors. Please help me..

  • Karry,

    I need further information on the produced errors.

    remove this line “header(“Content-type: image/png”);” and tell me what errors are produced.

  • Karry

    Hi this was the error when i removed header(“Content-type: image/png”);” and executed the code.
    ( ! ) Notice: Undefined index: color in C:\wamp\www\t2.php on line 2
    Call Stack
    # Time Memory Function Location
    1 0.0010 695512 {main}( ) ..\t2.php:0

    ( ! ) Notice: Undefined index: text in C:\wamp\www\t2.php on line 5
    Call Stack
    # Time Memory Function Location
    1 0.0010 695512 {main}( ) ..\t2.php:0

    ( ! ) Notice: Undefined index: HTTP_REFERER in C:\wamp\www\t2.php on line 8
    Call Stack
    # Time Memory Function Location
    1 0.0010 695512 {main}( ) ..\t2.php:0

    ( ! ) Warning: imagettfbbox() [function.imagettfbbox]: Invalid font filename in C:\wamp\www\t2.php on line 47
    Call Stack
    # Time Memory Function Location
    1 0.0010 695512 {main}( ) ..\t2.php:0
    2 0.0708 696440 imagettfbbox ( ) ..\t2.php:47

    ( ! ) Notice: Undefined variable: offset in C:\wamp\www\t2.php on line 57
    Call Stack
    # Time Memory Function Location
    1 0.0010 695512 {main}( ) ..\t2.php:0

    ( ! ) Warning: imagettftext() [function.imagettftext]: Invalid font filename in C:\wamp\www\t2.php on line 57
    Call Stack
    # Time Memory Function Location
    1 0.0010 695512 {main}( ) ..\t2.php:0
    2 0.3633 712624 imagettftext ( ) ..\t2.php:57

  • Karry, I am really not sure what is going on.

    what version of PHP do you use?

  • Pingback: In search of the elusive Google default marker | Blog of Travis Hydzik()

  • John

    Hi,this is a great tuto!
    I have a webpage that shows a small window of a dynamic map on it. Now i want to load the same map in a light box so when a button is clicked i can show a big map in the light box,any idea where i can find help.thanks!