Results 1 to 10 of 10

Thread: Make your maps explorable using the Google Maps API (work in progress)

  1. #1
    Guild Novice Facebook Connected Owen Borseth's Avatar
    Join Date
    Nov 2012
    Location
    Denver, Colorado, United States
    Posts
    6

    Tutorial Make your maps explorable using the Google Maps API (work in progress)

    Hi guys. I'm a ridiculously horrible artists, but I am a pretty decent web developer. So, I'm going to write up a tutorial on how to make your maps explorable with the Google Maps API. You can see a working example on my website. As I learn more about creating more advanced maps, etc I'll update this thread. Without further ado, let's jump right in and get started.

    Your Map

    Your map should be pretty big and it needs to have a height and width in pixels that are divisible by 256. I personally created a map that was 3072 x 3072 and it works pretty well. However; the bigger the better. At 100% the map should be clear and of good quality or it will look pretty crappy when zoomed in. If you've ever used Google Maps, and I know you all have, you know that there are zoom levels that you can control. For what I know so far, the map will be a 256 x 256 pixel image at zoom 0. At zoom 1 it will be a 2 x 2 matrix of 256 x 256 pixel images. Basically, for every zoom level the map will consist of 2*(2^zoom) 256 pixel images. I'm working with other tile makers, including a command line one that will automatically cut up an uploaded map, but so far the following one works best for what I've been doing:

    Tiles Generator

    It's a windows app, so sorry if you have a Mac or use Linux. I'll find other options eventually as I play around more. To split your map you run it like so:

    TilesGenerator.exe [maxzoom] [filename]

    It will go to work creating all of the necessary tiles from zoom levels 0 through whatever zoom level you specified for [maxzoom]. Remember, if your map is 3072 x 3072 like mine and you specify a [maxzoom] of 4 you will end up with a fully zoomed image that is 4096 x 4096 (256*(2^4)). So, a 4096 x 4096 image would actually be perfect for a map with a [maxzoom] of 4. A smaller map will end up stretching the tiles and become distorted. How much it distorts depends on the size difference and the quality of the image of course.

    The command line app will create an "output" directory with images named something like tile_0_0-0.png. Basically, tile_[zoom]_[x]-[y].png. You'll need to upload all of those images to a directory on a web server if you're going to use them via the Google Maps API.

    The Code

    I put up a basic page with only what's required for the map here. I documented the **** out of it so it should be pretty self explanatory. You could literally copy and paste the source of that page, change the path to your map tiles, modify or remove the marker information, and have everything work out pretty well. Depending on the size of the map you might need to tweak the min and max zoom levels, but that's pretty much it.

    Here's is the HTML and javascript code with comments (let me know if you have any questions):

    <html>
    <head>
    <!-- Load the Google Maps API javascript file -->
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?libraries=geometry&sensor=false"></script>
    <!-- Load the Google info bubble javascript file -->
    <script type="text/javascript">
    var script = '<script type="text/javascript" src="http://google-maps-' +
    'utility-library-v3.googlecode.com/svn/trunk/infobubble/src/infobubble';
    if (document.location.search.indexOf('compiled') !== -1) {
    script += '-compiled';
    }
    script += '.js"><' + '/script>';
    document.write(script);
    </script>
    <style>
    // you'll need this for IE if using bootstrap or some other frameworks
    // also, IE sucks ass
    #nuvia-map img
    {
    max-width: none;
    }
    </style>
    </head>
    <body>
    <!-- Container for displaying latitude longitude coordinates when you click on the map. This is handy for when you are needing to get the lat/lng values for markers. -->
    <div id="latLng"></div>
    <!-- Container for the actual map. -->
    <div id="nuvia-map" style="width:512px; height:512px; margin: 0px auto; border:2px solid #000;"></div>
    <script type="text/javascript">
    /* <![CDATA[ */

    /* Array of marker data for creating your markers and marker info bubbles. */
    var markers =
    {
    "Steelwell\'s Landing":{lat:56.02, lng:-11.16, title:'Steelwell\'s Landing', flat:true, type:'city1', zoom:{3:true,4:true}, image:'/images/nicubunu/sign_post.svg.png',
    info:"Small oasis village in the middle of the Great Gozal Desert."},

    "Gozal":{lat:69.47, lng:-76.42, title:'Gozal', flat:true, type:'city2', zoom:{3:true,4:true}, image:'/images/nicubunu/sign_crossroad.svg.png',
    info:"Rebel stronghold and capital city of Gozal (rebel) controlled lands. Gozal is a sprawling city with five distinct districts each ruled by descendants of the Imperial traitor Karazal."}
    };
    /* Array for markers that are loaded onto the map. */
    var activeMarkers = [];

    /* Global variable that will contain the Google Maps object. */
    var map = null

    // Google Maps Demo object
    var Demo = Demo || {};
    // The path to your tile images.
    Demo.ImagesBaseUrl = '/images/map/tiles/';

    // NuviaMap class
    Demo.NuviaMap = function (container)
    {
    // Create map
    // This sets the default info for your map when it is initially loaded.
    map = new google.maps.Map(container,
    {
    zoom: 1,
    center: new google.maps.LatLng(-2, 2),
    mapTypeControl: false,
    streetViewControl: false,
    zoomControl: true,
    zoomControlOptions:
    {
    style: google.maps.ZoomControlStyle.SMALL
    }
    });

    // Set custom tiles
    map.mapTypes.set('nuvia', new Demo.ImgMapType('nuvia', '#4E4E4E'));
    map.setMapTypeId('nuvia');

    // Loop through the marker info array and load them onto the map.
    for (var key in markers)
    {
    var markerData = markers[key];

    var marker = new google.maps.Marker(
    {
    position:new google.maps.LatLng(markerData.lat, markerData.lng),
    map:map,
    title:markerData.title,
    flat:markerData.flat,
    visible:false,
    infoBubble:new InfoBubble({
    maxWidth: 300,
    contentmarkerData.image ? '<img src="'+markerData.image+'" width="80" align="left">' : '')+'<h3>'+markerData.title+'</h3>'+(markerData.info ? '<p>'+markerData.info+'</p>' : ''),
    shadowStyle: 1,
    padding: '10px'
    }),
    // You can use custom icons, default icons, etc. In my case since a city was a marker the circle icon works pretty well.
    // I adjust the scale / size of the icon depending on what kind of city it is on my map.
    icon:
    {
    path: google.maps.SymbolPath.CIRCLE,
    scale: markerData.type == 'city1' ? 3 : 5
    }
    });

    // We need to trap the click event for th emarker so we can pop up an info bubble.
    google.maps.event.addListener(marker, 'click', function()
    {
    this.infoBubble.open(map, this);
    });

    activeMarkers.push(marker);
    }

    // This is dumb. We only want the markers to display at certain zoom levels so this handled that.
    // Google should have a way to specify zoom levels for markers. Maybe they do but I could not find them.
    google.maps.event.addListener(map, 'zoom_changed', function()
    {
    var currentZoom = map.getZoom();

    for(var i = 0; i < activeMarkers.length; i++)
    {
    var thisTitle = activeMarkers[i].title;

    if(markers[thisTitle]['zoom'][currentZoom])
    activeMarkers[i].setVisible(true);
    else
    activeMarkers[i].setVisible(false);
    }
    });

    // This handles the displaying of lat/lng info in the lat/lng info container defined above in the HTML.
    google.maps.event.addListener(map, 'click', function(event)
    {
    $('#latLng').html("Latitude: "+event.latLng.lat()+" "+", longitude: "+event.latLng.lng());
    });
    };

    // ImgMapType class
    Demo.ImgMapType = function (theme, backgroundColor)
    {
    this.name = this._theme = theme;
    this._backgroundColor = backgroundColor;
    };

    // Let Google know what size our tiles are and what our min/max zoom levels should be.
    Demo.ImgMapType.prototype.tileSize = new google.maps.Size(256, 256);
    Demo.ImgMapType.prototype.minZoom = 1;
    Demo.ImgMapType.prototype.maxZoom = 4;

    // Load the proper tile.
    Demo.ImgMapType.prototype.getTile = function (coord, zoom, ownerDocument)
    {
    var tilesCount = Math.pow(2, zoom);

    if (coord.x >= tilesCount || coord.x < 0 || coord.y >= tilesCount || coord.y < 0)
    {
    var div = ownerDocument.createElement('div');
    div.style.width = this.tileSize.width + 'px';
    div.style.height = this.tileSize.height + 'px';
    div.style.backgroundColor = this._backgroundColor;
    return div;
    }

    var img = ownerDocument.createElement('IMG');
    img.width = this.tileSize.width;
    img.height = this.tileSize.height;
    // This tells what tile image to load based on zoom and coord info.
    img.src = Demo.Utils.GetImageUrl('tile_' + zoom + '_' + coord.x + '-' + coord.y + '.png');

    return img;
    };

    // Just basically returns the image using the path set way above and the name of the actual image file.
    Demo.Utils = Demo.Utils || {};
    Demo.Utils.GetImageUrl = function (image)
    {
    return Demo.ImagesBaseUrl + image;
    };

    // Opacity.
    Demo.Utils.SetOpacity = function (obj, opacity /* 0 to 100 */ )
    {
    obj.style.opacity = opacity / 100;
    obj.style.filter = 'alpha(opacity=' + opacity + ')';
    };

    // Create ye ol' map.
    google.maps.event.addDomListener(window, 'load', function ()
    {
    var nuviaMap = new Demo.NuviaMap(document.getElementById('nuvia-map'));
    });

    /* ]]> */
    </script>
    <script data-rocketsrc="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/rocketscript"></script>
    </body>
    </html>
    P.S. Ya'll should really be using Chrome
    Last edited by Owen Borseth; 11-28-2012 at 11:09 PM. Reason: More info.

  2. #2
      Redrobes is offline
    Software Dev/Rep Redrobes's Avatar
    Join Date
    Dec 2007
    Location
    England
    Posts
    4,763
    Blog Entries
    4

    Default

    Cool - will follow this and make a CWBP map with the zoom if it works out.

  3. #3
    Guild Novice Facebook Connected Owen Borseth's Avatar
    Join Date
    Nov 2012
    Location
    Denver, Colorado, United States
    Posts
    6

    Default

    Quote Originally Posted by Redrobes View Post
    Cool - will follow this and make a CWBP map with the zoom if it works out.
    Yes! I would be more than happy to help out with that.

  4. #4
    Professional Artist Facebook Connected Schwarzkreuz's Avatar
    Join Date
    Oct 2011
    Location
    Leipzig/Berlin
    Posts
    1,369

    Default

    I only see a grey space, on your website, with firefox, that is wrong I guess?

  5. #5
      Sapiento is offline
    Professional Artist Gracious Donor Sapiento's Avatar
    Join Date
    Jul 2009
    Location
    Salzburg, Austria
    Posts
    2,175

    Default

    Same for me, with Opera.

  6. #6
    Guild Journeyer
    Join Date
    Oct 2012
    Posts
    222

    Default

    I can't see anything.!!!
    "Our greatest glory is not in never falling, but in rising every time we fall."-Confucius
    Old map and Historic map

  7. #7
      waldronate is offline
    Software Dev/Rep Gracious Donor waldronate's Avatar
    Join Date
    Mar 2007
    Location
    The High Desert
    Posts
    1,393

    Default

    With IE9, I see a mostly off-white map. If I zoom in two mousewheel clicks, I can see two markers. I don't know if it's missing map data, or just a demonstration of how to do markers at varying levels. The JavaScript of the site is interesting in how it handles the markers, though. One of these years I need to get that sort of functionality working for my own projects.

  8. #8
    Guild Novice Facebook Connected Owen Borseth's Avatar
    Join Date
    Nov 2012
    Location
    Denver, Colorado, United States
    Posts
    6

    Default

    Hmm. It's running on a micro instance at Amazon AWS. Sometimes those things get loaded down and don't perform too well. If you refresh it should hopefully load the tiles of the map.

    Edit: IE issues and issues with map tiles loading should be resolved. IE was affected by some bootstrap CSS that I needed to override. Other tile loading issues I believe were related to CloudFlare CDN / caching stuff.
    Last edited by Owen Borseth; 11-28-2012 at 11:11 PM. Reason: IE, etc fix

  9. #9
      Patti is offline
    Guild Novice
    Join Date
    Nov 2012
    Posts
    5

    Default

    This sounds really interesting.

  10. #10
      Tviksas is offline
    Guild Applicant Facebook Connected
    Join Date
    Sep 2012
    Location
    Lithuania
    Posts
    4

    Default

    O-hell, this is nice, gonna try to use it for my encyclopedia.

    Though is it possible and if so how can I make the map window on website bigger? On 1920px resolution it looks just a little too small.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •