Hi everybody,

I need to setup different marker per every single location (node). Each of my node has integer number in a particular CCK field called Number and what I want is to have this number displayed in gmap marker, like this:

> http://cl.ly/2Y3T3J2B2X1M2w2d0u2n

Is that doable? How?

Just to be clear - the numbers dont go from 1 to n in sequence. There are ranges, for example, from 100 to 125, then a gap, and then from 200 to 264, gap, 300 to 311, etc... So I cant use the sequence feature of Gmap markers .ini file.

Thanks for any help.

Comments

johnv’s picture

Status: Active » Postponed (maintainer needs more info)

Did you find a solution already?
You can add the number to the list of fields, and show this field in the marker. Then, theme it as you like.

petiar’s picture

Status: Postponed (maintainer needs more info) » Fixed

Hi johnv,

yes, I got the solution which I am quite proud of. :-)

I have this callback function which return all locations on the map. It is actually a view containing title, latitude, longitude and that number. This view is json encoded and provided to .js script which displays google map. In this script I go through all locations and place it on the map and for each image marker I call small standalone script which generates number as a image using some php functions.

It would be even more elegant provide another callback function and return image generated by ImageCache module, but this works alright, so there was no reason to bother with that.

You can check the result on http://mpba.sk/en/mapa

Thanks for your interest.
Petiar.

johnv’s picture

Nice result,
would you mind to share your code, so others can use it as an example?

petiar’s picture

Ok, no problem mate!

This is the jquery stuff. I took most of it from somewhere on Gmail API document pages, can't remember where exactly, unfortunately. Check the AJAX call at the end of initialize() function and subsequent setMarkers() function call.

jQuery(document).ready(function(){                   

	function initialize() {

		if (Drupal.settings.mapa == 'small') {
			var latlng = new google.maps.LatLng(Drupal.settings.lat, Drupal.settings.lng);

		  var myOptions = {
		    zoom: 17,
		    center: latlng,
		    mapTypeId: google.maps.MapTypeId.HYBRID
		  };
		  
			var map = new google.maps.Map(document.getElementById("small-map"), myOptions);
		}
		else if (Drupal.settings.mapa == 'node-map') {
			var latlng = new google.maps.LatLng(Drupal.settings.lat, Drupal.settings.lng);

		  var myOptions = {
		    zoom: 17,
		    center: latlng,
		    mapTypeId: google.maps.MapTypeId.HYBRID
		  };
		  
			var map = new google.maps.Map(document.getElementById("mpba-mapa"), myOptions);  		
		}
		else {
			var latlng = new google.maps.LatLng(48.145431, 17.107657);

		  var myOptions = {
		    zoom: 12,
		    center: latlng,
		    mapTypeId: google.maps.MapTypeId.SATELLITE
		  };
		  
			var map = new google.maps.Map(document.getElementById("mpba-mapa"), myOptions);
		  
		}
	
		var locations = new Array();
	
		jQuery.ajax({
			url:'http://mpba.sk/mpba-mapa-locations',
			dataType: 'json',
			async: false,
			success: function(data) {
				locations = data;
			}
		});	
		setMarkers (map, locations);
	}

	function setMarkers(map, locations) {
	  // Add markers to the map

	  // Marker sizes are expressed as a Size of X,Y
	  // where the origin of the image (0,0) is located
	  // in the top left of the image.

	  // Origins, anchor positions and coordinates of the marker
	  // increase in the X direction to the right and in
	  // the Y direction down.
	  var image = new google.maps.MarkerImage('images/beachflag.png',
	      // This marker is 20 pixels wide by 32 pixels tall.
	      new google.maps.Size(20, 32),
	      // The origin for this image is 0,0.
	      new google.maps.Point(0,0),
	      // The anchor for this image is the base of the flagpole at 0,32.
	      new google.maps.Point(0, 32));
	  var shadow = new google.maps.MarkerImage('images/beachflag_shadow.png',
	      // The shadow image is larger in the horizontal dimension
	      // while the position and offset are the same as for the main image.
	      new google.maps.Size(37, 32),
	      new google.maps.Point(0,0),
	      new google.maps.Point(0, 32));
	      // Shapes define the clickable region of the icon.
	      // The type defines an HTML <area> element 'poly' which
	      // traces out a polygon as a series of X,Y points. The final
	      // coordinate closes the poly by connecting to the first
	      // coordinate.
	  var shape = {
	      coord: [1, 1, 1, 22, 40, 22, 40, 1],
	      type: 'poly'
	  };

	  for (var i = 0; i < locations.length; i++) {
	    var beach = locations[i];
	    var myLatLng = new google.maps.LatLng(beach[1], beach[2]);

            // *** getting marker image ***
	    var image = new google.maps.MarkerImage('http://image.mpba.sk/?c='+beach[3],
				// This marker is 20 pixels wide by 32 pixels tall.
	      new google.maps.Size(40, 22),
	      // The origin for this image is 0,0.
	      new google.maps.Point(0,0),
	      // The anchor for this image is the base of the flagpole at 0,32.
	      new google.maps.Point(20, 22)
			);
	    var marker = new google.maps.Marker({
	        position: myLatLng,
	        map: map,
					url: 'http://mpba.sk/'+beach[3],
	        //shadow: shadow,
	        icon: image,
	        shape: shape,
	        title: beach[0],
	        zIndex: 10
	    });
			var info = new google.maps.InfoWindow({
				content: 'Holding...',
			});

			google.maps.event.addListener(marker, 'click', function() {
				info.setContent('<a href="'+this.url+'">'+this.title+'</a');
			  info.open(map,this);
			});
	  }		
	}
	
	initialize();
	
});

In the AJAX call I am receiving list of locations from this function (which is the appropriate hook_menu's callback function):

function mpba_mapa_locations() {
	$mapa = views_get_view_result('cela_mapa', 'page_2');
	$locations = array();
	foreach ($mapa as $location) {
		$locations[] = array($location->node_title,$location->location_latitude,$location->location_longitude,$location->node_data_field_lokalita_stav_field_lokalita_cislo_value, $location->nid);
	}
	echo drupal_json($locations);
}

As you can see I am literary getting appropriate view, taking the needed fields from it and print it as JSON what actually means that I am sending them back as an AJAX call result. Now back to the javascript file - look at the line bellow the *** getting marker image *** and you can see that I am getting an image from file. This file is not a image though, but very simple php script which generates one according the content of the "c" parameter. This is the script:


	$cislo = $_GET['c'];
	$force = $_GET['f'];

	$path = 'files/'.$cislo.'.png';
	if (file_exists($path) && !$force) {
		$image = file_get_contents($path);
		header("Content-type: image/png");
		echo $image;
	}
	else {
		$image = imagecreatetruecolor(40, 22);
		$white = imagecolorallocate($image, 255, 255, 255);
		$red = imagecolorallocate($image, 255, 0, 0);
		$black = imagecolorallocate($image, 0, 0, 0);
		imagecolortransparent($image, $black);
		ImageRectangleWithRoundedCorners($image, 0, 0, 39, 21, 2, $white);
		$text1_size = imagettfbbox(13, 0, 'font_bold.otf', substr($cislo, 0, 1));
		$text2_size = imagettfbbox(13, 0, 'font.otf', substr($cislo, 1, 2));
		
		// sirka = sirka prveho pismena + sirka druheho pismena + este pridavam jeden pixel
		$sirka = ($text1_size[2] - $text1_size[0]) + ($text2_size[2] - $text2_size[0]) + 1;
		
		$medzera = floor((40 - $sirka) / 2);
		
		$text1 = imagettftext($image, 13, 0, $medzera, 17, $red, 'font_bold.otf', substr($cislo, 0, 1));
		$text2 = imagettftext($image, 13, 0, $text1[2]+1, 17, $red, 'font.otf', substr($cislo, 1, 2));
		
		header("Content-type: image/png");
		imagepng($image);
		imagepng($image, $path);
		imagedestroy($image);
	}
	
	function ImageRectangleWithRoundedCorners(&$im, $x1, $y1, $x2, $y2, $radius, $color)
	{
	    // Draw rectangle without corners
	    ImageFilledRectangle($im, $x1+$radius, $y1, $x2-$radius, $y2, $color);
	    ImageFilledRectangle($im, $x1, $y1+$radius, $x2, $y2-$radius, $color);
	    // Draw circled corners
	    ImageFilledEllipse($im, $x1+$radius, $y1+$radius, $radius*2, $radius*2, $color);
	    ImageFilledEllipse($im, $x2-$radius, $y1+$radius, $radius*2, $radius*2, $color);
	    ImageFilledEllipse($im, $x1+$radius, $y2-$radius, $radius*2, $radius*2, $color);
	    ImageFilledEllipse($im, $x2-$radius, $y2-$radius, $radius*2, $radius*2, $color);
	}
	

The cherry on the top is that this script actually does the caching - so if the image already exists in dedicated folder, it does not get generated again (unless the "f" (force generate) option is specified when calling the script).

I hope it'll help someone. :-)
Petiar

johnv’s picture

Title: CCK field value in Gmap marker » How-to / Example: custom (CCK/Field) value in Gmap marker
Version: 6.x-1.1 » 7.x-2.x-dev
Component: User interface » Documentation
Status: Fixed » Active

Nice work!
Let's keep this alive for future reference. (Not sure how, yet)
Perhaps via a link on the project page, or d.o. documentation pages.
(I guess this is in essence a version-proof solution)

petiar’s picture

It depends if the function views_get_view_result() is the same in D7 version of VIews, that means as far as I know the Views 3. And if drupal_json() still exists. If that's the case then everything should be version-proof.

petiar’s picture

Issue summary: View changes

More details added.