Howto create a zoomable Salem map?

Forum for game modifications and custom clients.

Re: Howto create a zoomable Salem map?

Postby imrielle » Sun Dec 02, 2012 4:32 am

Update, working grids. I split the Javascripting out into a separate file for easier editing for myself, so here is the HTML file:
Code: Select all
<!DOCTYPE html>
<html>
<head>
<title>Maps - Roanoke</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
   html { height: 100% }
   body { height: 100%; margin: 0px; padding: 0px }
   #map_canvas { height: 100% }
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var currentSession = 0;
var salemserver = 'roa';
</script>
<script type="text/javascript" src="smap.js"></script>
</head>
<body onload="initialize()">
   <div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>


And the smap.js file:
Code: Select all
function myProjection() {
   var MAP_RANGE = 51200;
   this.worldOrigin_ = new google.maps.Point(0, 0);
   this.pixelsPerLonDegree_ = MAP_RANGE / 360;
   this.pixelsPerLatDegree_ = MAP_RANGE / 180;
};
 
myProjection.prototype.fromLatLngToPoint = function(latLng) {
   var origin = this.worldOrigin_;
   var x = origin.x + latLng.lng() * this.pixelsPerLonDegree_;
   var y = origin.y + latLng.lat() * this.pixelsPerLatDegree_;
   return new google.maps.Point(x, y);
};
 
myProjection.prototype.fromPointToLatLng = function(point) {
   var origin = this.worldOrigin_;
   var lng = (point.x - origin.x) / this.pixelsPerLonDegree_;
   var lat = (point.y - origin.y) / this.pixelsPerLatDegree_;
   return new google.maps.LatLng(lat, lng);
};

function CoordMapType(tileSize) {
   this.tileSize = tileSize;
}

CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
   var div = ownerDocument.createElement('DIV');
   div.innerHTML = coord;
   div.style.width = this.tileSize.width + 'px';
   div.style.height = this.tileSize.height + 'px';
   div.style.fontSize = '16px';
   div.style.borderStyle = 'solid';
   div.style.borderWidth = '1px';
   div.style.borderColor = '#999999';
   div.style.color = '#999';
   return div;
};

function HomeControl(controlDiv, map) {
   controlDiv.style.padding = '5px';
   var controlUI = document.createElement('DIV');
   controlUI.style.backgroundColor = 'white';
   controlUI.style.borderStyle = 'solid';
   controlUI.style.borderWidth = '2px';
   controlUI.style.cursor = 'pointer';
   controlUI.style.textAlign = 'center';
   controlUI.title = 'Click to go to start point';
   controlDiv.appendChild(controlUI);
   var controlText = document.createElement('DIV');
   controlText.style.fontFamily = 'Arial,sans-serif';
   controlText.style.fontSize = '12px';
   controlText.style.paddingLeft = '4px';
   controlText.style.paddingRight = '4px';
   controlText.innerHTML = 'Go to start point';
   controlUI.appendChild(controlText);
   google.maps.event.addDomListener(controlUI, 'click', function() {
      map.setCenter(new google.maps.LatLng(0, 0))
   });
}


CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
    switch(zoom) {
        case 6:
    default:
       var factor = Math.pow(3,(6-zoom))
       var grid_div = ownerDocument.createElement("DIV");
       grid_div.style.outlineStyle = "dotted";
       grid_div.style.outlineWidth = "1px";
       grid_div.style.outlineColor = "#AAA";
       grid_div.innerHTML = "<span class=\"coords\">("+coord.x*factor+", "+coord.y*factor+")</span>";
      grid_div.style.width = this.tileSize.width + "px";
      grid_div.style.height = this.tileSize.height + "px";
      grid_div.my_x = coord.x;
      grid_div.my_y = coord.y;
      grid_div.zoom = zoom;
      return grid_div;
       break;
    }
};

function GridControl(controlDiv, map) {
   controlDiv.style.padding = '5px';
   var controlUI = document.createElement('DIV');
   controlUI.style.backgroundColor = '#666';
   controlUI.style.borderStyle = 'solid';
   controlUI.style.borderWidth = '1px';
   controlUI.style.cursor = 'pointer';
   controlUI.style.textAlign = 'center';
   controlUI.title = 'Click to show or hide grid';
   controlDiv.appendChild(controlUI);
   var controlText = document.createElement('DIV');
   controlText.style.fontFamily = 'Arial,sans-serif';
   controlText.style.fontSize = '12px';
   controlText.style.paddingLeft = '4px';
   controlText.style.paddingRight = '4px';
   controlText.innerHTML = 'Show/Hide grid';
   controlUI.appendChild(controlText);
   google.maps.event.addDomListener(controlUI, 'click', function() {
      if (map.overlayMapTypes.getLength()) {
         map.overlayMapTypes.pop();
      }
      else {
         map.overlayMapTypes.push(new CoordMapType(new google.maps.Size(100, 100)))
      }
   });
}


function initialize() {

   var map;

   var myMapType = new google.maps.ImageMapType({
      tileSize: new google.maps.Size(256, 256),
      minZoom: 3,
      maxZoom: 6,
      getTileUrl: function(coord, zoom) {
         return './maps/' + salemserver + '/'+ zoom + '/' + 'tile_' + coord.x + '_' + coord.y + '.png';
      },
      isPng: true
   });

   myMapType.projection = new myProjection();

   var mapOptions = {
      center: new google.maps.LatLng(0, 0),
      mapTypeControl: false,
      backgroundColor: '#212121',
      zoom: 6
   }

   map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
   map.mapTypes.set('myMapType', myMapType);
   map.setMapTypeId('myMapType');

   var homeControlDiv = document.createElement('DIV');
   var homeControl = new HomeControl(homeControlDiv, map);
   homeControlDiv.index = 1;
   map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv);
   
   var gridControlDiv = document.createElement('DIV');
   var gridControl = new GridControl(gridControlDiv, map);
   gridControlDiv.index = 2;
   map.controls[google.maps.ControlPosition.TOP_RIGHT].push(gridControlDiv);
}


*clears sleepy gunk out of the corners of her eyes* Ugh, so tired, almost forgot. In the JS, find this line:
Code: Select all
tileSize: new google.maps.Size(256, 256),

Change it to match the size of your images - 100, 100 for 100px, 500, 500 for 500px and so on. I was experimenting with sizing to see how it affected load time and overall performance, and have not marked up and commented anything in the HTML and Javascript yet.

The grid works nicely now, and regardless of image size, is 100 by 100 (minimap tile sizes, coordinates would coincide with ingame sizing this way).

I may change more things in the JS later on to allow for settings variables for all of this. More user friendly that way.
Need more hours in a day. :(
Image
User avatar
imrielle
Customer
 
Posts: 491
Joined: Sat Nov 10, 2012 5:57 pm
Location: Ohio, USA

Re: Howto create a zoomable Salem map?

Postby Jamilian » Sun Dec 30, 2012 6:11 pm

Hey imrielle,

i just updated my whole map; but i see another problem with the zoom / coordinates.

The coordinates are changing in the different zoom levels. So if you want to describe someone a position, then you need to say the zoom level as well right now.
You can just test it if you take a lake at (-50, 0) for example, zoom in one level and recheck the coordinates.

And sorry if i am asking like a leecher, but are you able to add the marker-stuff? Would be really great.

Or can you say me where i have to look to implement both myself?
James,
mayor of Great Axton on Jamestown

You want to join us? Click >>here<<
Jamilian
 
Posts: 33
Joined: Fri Sep 07, 2012 10:33 am

Re: Howto create a zoomable Salem map?

Postby imrielle » Sun Dec 30, 2012 8:25 pm

Jamilian wrote:The coordinates are changing in the different zoom levels. So if you want to describe someone a position, then you need to say the zoom level as well right now.
You can just test it if you take a lake at (-50, 0) for example, zoom in one level and recheck the coordinates.

And sorry if i am asking like a leecher, but are you able to add the marker-stuff?


Try finding this line in smap.js:
Code: Select all
tileSize: new google.maps.Size(256, 256),

and changing it to
Code: Select all
tileSize: new google.maps.Size(100, 100),


Thats what my local server is set to, with 200px by 200px image files and the zooming works fine with coords. It does kind of bug on the comlu page, too.

Markers I have not had the chance to code yet. I'm currently 200 miles from my computer, snowed in at my parents house. :cry: I was supposed to return home on the 26th, but we got hit with this ****. Its still snowing. :evil:
Image
User avatar
imrielle
Customer
 
Posts: 491
Joined: Sat Nov 10, 2012 5:57 pm
Location: Ohio, USA

Re: Howto create a zoomable Salem map?

Postby Jamilian » Sun Dec 30, 2012 11:47 pm

I already changed it like that, and that doesn't solve the problem.
The problem is the same on your map.

I think the problem is the following:

the smap.js says (if i am right) in this part:

Code: Select all
function GridControl(controlDiv, map) {
       controlDiv.style.padding = '5px';
       var controlUI = document.createElement('DIV');
       controlUI.style.backgroundColor = '#666';
       controlUI.style.borderStyle = 'solid';
       controlUI.style.borderWidth = '1px';
       controlUI.style.cursor = 'pointer';
       controlUI.style.textAlign = 'center';
       controlUI.title = 'Click to show or hide grid';
       controlDiv.appendChild(controlUI);
       var controlText = document.createElement('DIV');
       controlText.style.fontFamily = 'Arial,sans-serif';
       controlText.style.fontSize = '12px';
       controlText.style.paddingLeft = '4px';
       controlText.style.paddingRight = '4px';
       controlText.innerHTML = 'Show/Hide grid';
       controlUI.appendChild(controlText);
       google.maps.event.addDomListener(controlUI, 'click', function() {
          if (map.overlayMapTypes.getLength()) {
             map.overlayMapTypes.pop();
          }
          else {
             map.overlayMapTypes.push(new CoordMapType(new google.maps.Size(100, 100)));
          }
       });


especially here:
Code: Select all
map.overlayMapTypes.push(new CoordMapType(new google.maps.Size(100, 100)));


That anytime 100px is 1 unit. On each zoom level. well - it at least looks like that.
So if my thesis is right, then the grid is the same like the tiles in the belonging map folder.

So maybe there should be something like this for the sizing of the grid as well?
[codegrid_div.innerHTML = "<span class=\"coords\">("+coord.x*factor+", "+coord.y*factor+")</span>";[/code]

Hmmm... its not that easy, even if i like some programming and scripting myself :P
Do you see the problem what i have? Or is it not explained well? ^^
James,
mayor of Great Axton on Jamestown

You want to join us? Click >>here<<
Jamilian
 
Posts: 33
Joined: Fri Sep 07, 2012 10:33 am

Re: Howto create a zoomable Salem map?

Postby Jamilian » Mon Dec 31, 2012 1:04 am

Ha, I got at least the wrong zoom, and i think it was just a typo:

In your smap.js you have this here:
Code: Select all
[...]
var factor = Math.pow(3,(6-zoom))
[...]


But the factor is wrong, because your tiling script does a 0.5 (or 2.0) tiling.
Soo.. thats it.

Code: Select all
[...]
var factor = Math.pow(2,(6-zoom))
[...]



Now ill look if I can do something for "markers" ;-)
James,
mayor of Great Axton on Jamestown

You want to join us? Click >>here<<
Jamilian
 
Posts: 33
Joined: Fri Sep 07, 2012 10:33 am

Re: Howto create a zoomable Salem map?

Postby Jamilian » Mon Dec 31, 2012 4:06 pm

Sooooo, how do Jorb and Lofter say some times?

I "have been developing, and here is whats new":

I added a right click listener, which opens a infowindow with LatLng coordinates for the right clicked position (for markers very senceful...)
Code: Select all
      google.maps.event.addListener(map, "rightclick", function(e) {
      var infowindow = new google.maps.InfoWindow(
          {
               content: ""+e.latLng,
                size: new google.maps.Size(500,100)
          });
      infowindow.setPosition(e.latLng);
      infowindow.open(map);
      });


And after that i started digging around with some marker-things...

To add a simple marker you can just use this code, using the latLng coordinates from right-clicking the map:

Code: Select all
var myLatlng = new google.maps.LatLng(-0.0028564453125, -0.23247070312504547);
       var marker2 = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: "west of here, Darkness",
            });


But I didn't really like that marker, because it is just a marker in a red color with a dot and without any text (except in the marker tooltip). In addition to that i wanted to have different colors for different stuff. Thats also possible with this snippets here:

Code: Select all
var blueIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/blue/blank.png";
       var redIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/red/blank.png";
       var greenIncon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/green/blank.png";
       var orangeIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/orange/blank.png";
       var pinkIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/pink/blank.png";
       
       var bluecircleIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/bluecirclemarker.png";
       var greencircleIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/greencirclemarker.png";
       var yellowcircleIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/yellowcirclemarker.png";


And for a marker:

Code: Select all
var myLatlng = new google.maps.LatLng(-0.0028564453125, -0.23247070312504547);
       var marker2 = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: "west of here, Darkness",
            icon: orangeIcon
       });


With this two additions (icon: orangeIcon and definition of orangeIcon) it was possible to have colored markers - but the text-stuff had not been good enough for that what i wanted.

So I looked for more possebilities, and found really nice dynamic markers. But that needed some more changes:

In the map.html include this
Code: Select all
<script type="text/javascript" src="StyledMarker.js"></script>


Then create and save the StyledMarker.js (http://code.google.com/p/google-maps-ut ... r.js?r=143) with this content:
Code: Select all
/**
 * @name StyledMarkerMaker
 * @version 0.5
 * @author Gabriel Schneider
 * @copyright (c) 2010 Gabriel Schneider
 * @fileoverview This gives you static functions for creating dynamically
 *     styled markers using Charts API outputs as well as an ability to
 *     extend with custom types.
 */

/**
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var StyledIconTypes = {};
var StyledMarker, StyledIcon;

/**
 * @param {Function} childCtor Child class.
 * @param {Function} parentCtor Parent class.
 */
function inherits(childCtor, parentCtor) {
  /** @constructor */
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  childCtor.superClass_ = parentCtor.prototype;
  childCtor.prototype = new tempCtor();
  /** @override */
  childCtor.prototype.constructor = childCtor;
}
 
(function() {
  var bu_ = 'https://chart.googleapis.com/chart?chst=';
  var gm_ = google.maps;
  var gp_ = gm_.Point;
  var ge_ = gm_.event;
  var gmi_ = gm_.MarkerImage;
 

  /**
  * This class is an extended version of google.maps.Marker. It allows
  * styles to be applied that change it's appearance.
  * @extends google.maps.Marker
  * @param {StyledMarkerOptions} StyledMarkerOptions The options for the Marker
  */
  StyledMarker = function(styledMarkerOptions) {
    gm_.Marker.call(this);
    var me=this;
    var ci = me.styleIcon = styledMarkerOptions.styleIcon;
    me.bindTo('icon',ci);
    me.bindTo('shadow',ci);
    me.bindTo('shape',ci);
    me.setOptions(styledMarkerOptions);
  };
  inherits(StyledMarker, gm_.Marker);
 
  /**
  * This class stores style information that can be applied to StyledMarkers.
  * @extends google.maps.MVCObject
  * @param {StyledIconType} styledIconType The type of style this icon is.
  * @param {StyledIconOptions} styledIconOptions The options for this StyledIcon.
  * @param {StyledIcon} styleClass A class to apply extended style information.
  */
  StyledIcon = function(styledIconType,styledIconOptions,styleClass) {
    var k;
    var me=this;
    var i_ = 'icon';
    var sw_ = 'shadow';
    var s_ = 'shape';
    var a_ = [];

    function gs_() {
      var image_ = document.createElement('img');
      var simage_ = document.createElement('img');
      ge_.addDomListenerOnce(simage_, 'load', function() {
        var w = simage_.width, h = simage_.height;
        me.set(sw_,new gmi_(styledIconType.getShadowURL(me),null,null,styledIconType.getShadowAnchor(me,w,h)));
        simage = null;
      });
      ge_.addDomListenerOnce(image_, 'load', function() {
        var w = image_.width, h = image_.height;
        me.set(i_,new gmi_(styledIconType.getURL(me),null,null,styledIconType.getAnchor(me,w,h)));
        me.set(s_,styledIconType.getShape(me,w,h));
        image_ = null;
      });
      image_.src = styledIconType.getURL(me);
      simage_.src = styledIconType.getShadowURL(me);
    }

    /**
    * set:
    * This function sets a given style property to the given value.
    * @param {String} name The name of the property to set.
    * @param {Object} value The value to set the property to.
    * get:
    * This function gets a given style property.
    * @param {String} name The name of the property to get.
    * @return {Object}
    */
    me.as_ = function(v) {
      a_.push(v);
      for(k in styledIconOptions) {
        v.set(k, styledIconOptions[k]);
      }
    }

    if (styledIconType !== StyledIconTypes.CLASS) {
      for (k in styledIconType.defaults) {
        me.set(k, styledIconType.defaults[k]);
      }
      me.setValues(styledIconOptions);
      me.set(i_,styledIconType.getURL(me));
      me.set(sw_,styledIconType.getShadowURL(me));
      if (styleClass) styleClass.as_(me);
      gs_();
      me.changed = function(k) {
        if (k!==i_&&k!==s_&&k!==sw_) {
          gs_();
        }
      };
    } else {
      me.setValues(styledIconOptions);
      me.changed = function(v) {
        styledIconOptions[v] = me.get(v);
        for (k = 0; k < a_.length; k++) {
          a_[k].set(v,me.get(v));
        }
      };
      if (styleClass) styleClass.as_(me);
    }
  };
  StyledIcon.prototype = new gm_.MVCObject();
 
  /**
  * StyledIconType
  * This class holds functions for building the information needed to style markers.
  * getURL:
  * This function builds and returns a URL to use for the Marker icon property.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @return {String}
  * getShadowURL:
  * This function builds and returns a URL to use for the Marker shadow property.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @return {String{
  * getAnchor:
  * This function builds and returns a Point to indicate where the marker is placed.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @param {Number} width The width of the icon image.
  * @param {Number} height The height of the icon image.
  * @return {google.maps.Point}
  * getShadowAnchor:
  * This function builds and returns a Point to indicate where the shadow is placed.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @param {Number} width The width of the shadow image.
  * @param {Number} height The height of the shadow image.
  * @return {google.maps.Point}
  * getShape:
  * This function builds and returns a MarkerShape to indicate where the Marker is clickable.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @param {Number} width The width of the icon image.
  * @param {Number} height The height of the icon image.
  * @return {google.maps.MarkerShape}
  */
 
  StyledIconTypes.CLASS = {};
 
  StyledIconTypes.MARKER = {
    defaults: {
      text:'',
      color:'00ff00',
      fore:'000000',
      starcolor:null
    },
    getURL: function(props){
      var _url;
      var starcolor_=props.get('starcolor');
      var text_=props.get('text');
      var color_=props.get('color').replace(/#/,'');
      var fore_=props.get('fore').replace(/#/,'');
      if (starcolor_) {
        _url = bu_ + 'd_map_xpin_letter&chld=pin_star|';
      } else {
        _url = bu_ + 'd_map_pin_letter&chld=';
      }
      if (text_) {
        text_ = text_.substr(0,2);
      }
      _url+=text_+'|';
      _url+=color_+'|';
      _url+=fore_;
      if (starcolor_) {
        _url+='|'+starcolor_.replace(/#/,'');
      }
      return _url;
    },
    getShadowURL: function(props){
      if (props.get('starcolor')) {
        return bu_ + 'd_map_xpin_shadow&chld=pin_star';
      } else {
        return bu_ + 'd_map_pin_shadow';
      }
    },
    getAnchor: function(props,width,height){
      return new gp_(width / 2,height);
    },
    getShadowAnchor: function(props,width,height){
      return new gp_(width / 4,height);
    },
    getShape: function(props,width,height){
      var _iconmap = {};
      _iconmap.coord = [
        width / 2, height,
        (7 / 16) * width, (5 / 8) * height,
        (5 / 16) * width, (7 / 16) * height,
        (7 / 32) * width, (5 / 16) * height,
        (5 / 16) * width, (1 / 8) * height,
        (1 / 2) * width, 0,
        (11 / 16) * width, (1 / 8) * height,
        (25 / 32) * width, (5 / 16) * height,
        (11 / 16) * width, (7 / 16) * height,
        (9 / 16) * width, (5 / 8) * height
      ];
      for (var i = 0; i < _iconmap.coord.length; i++) {
        _iconmap.coord[i] = Math.round(_iconmap.coord[i]);
      }
      _iconmap.type = 'poly';
      return _iconmap;
    }
  };
  StyledIconTypes.BUBBLE = {
    defaults: {
      text:'',
      color:'00ff00',
      fore:'000000'
    },
    getURL: function(props){
      var _url = bu_ + 'd_bubble_text_small&chld=bb|';
      _url+=props.get('text')+'|';
      _url+=props.get('color').replace(/#/,'')+'|';
      _url+=props.get('fore').replace(/#/,'');
      return _url;
    },
    getShadowURL: function(props){
      return bu_ + 'd_bubble_text_small_shadow&chld=bb|' + props.get('text');
    },
    getAnchor: function(props,width,height){
      return new google.maps.Point(0,42);
    },
    getShadowAnchor: function(props,width,height){
      return new google.maps.Point(0,44);
    },
    getShape: function(props,width,height){
      var _iconmap = {};
      _iconmap.coord = [
        0,44,
        13,26,
        13,6,
        17,1,
        width - 4,1,
        width,6,
        width,21,
        width - 4,26,
        21,26
      ];
      _iconmap.type = 'poly';
      return _iconmap;
    }
  };
})();


And after that, you can add really interesting markers which fullfill each of my requirements:

Code: Select all
styleIcon = new StyledIcon(StyledIconTypes.BUBBLE,{color:"#004eff",text:"Great Axton"});
       var styleMarker1 = new StyledMarker({
           styleIcon:styleIcon,
           position:new google.maps.LatLng(0.00142822265625, 0.0017578125000454747),
           map:map,
           draggable:false
       });



Unfortunetly I added all my markers right now hardcoded. Marker by marker. Maybe it would be better to organize the markers in an array, just thinking of a "Toggle-Markers" function for example...

If there are any questions, or if I missed something, just tell.
James,
mayor of Great Axton on Jamestown

You want to join us? Click >>here<<
Jamilian
 
Posts: 33
Joined: Fri Sep 07, 2012 10:33 am

Re: Howto create a zoomable Salem map?

Postby imrielle » Mon Dec 31, 2012 10:15 pm

Jamilian wrote:
Sooooo, how do Jorb and Lofter say some times?

I "have been developing, and here is whats new":

I added a right click listener, which opens a infowindow with LatLng coordinates for the right clicked position (for markers very senceful...)
Code: Select all
      google.maps.event.addListener(map, "rightclick", function(e) {
      var infowindow = new google.maps.InfoWindow(
          {
               content: ""+e.latLng,
                size: new google.maps.Size(500,100)
          });
      infowindow.setPosition(e.latLng);
      infowindow.open(map);
      });


And after that i started digging around with some marker-things...

To add a simple marker you can just use this code, using the latLng coordinates from right-clicking the map:

Code: Select all
var myLatlng = new google.maps.LatLng(-0.0028564453125, -0.23247070312504547);
       var marker2 = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: "west of here, Darkness",
            });


But I didn't really like that marker, because it is just a marker in a red color with a dot and without any text (except in the marker tooltip). In addition to that i wanted to have different colors for different stuff. Thats also possible with this snippets here:

Code: Select all
var blueIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/blue/blank.png";
       var redIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/red/blank.png";
       var greenIncon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/green/blank.png";
       var orangeIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/orange/blank.png";
       var pinkIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/pink/blank.png";
       
       var bluecircleIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/bluecirclemarker.png";
       var greencircleIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/greencirclemarker.png";
       var yellowcircleIcon = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/yellowcirclemarker.png";


And for a marker:

Code: Select all
var myLatlng = new google.maps.LatLng(-0.0028564453125, -0.23247070312504547);
       var marker2 = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: "west of here, Darkness",
            icon: orangeIcon
       });


With this two additions (icon: orangeIcon and definition of orangeIcon) it was possible to have colored markers - but the text-stuff had not been good enough for that what i wanted.

So I looked for more possebilities, and found really nice dynamic markers. But that needed some more changes:

In the map.html include this
Code: Select all
<script type="text/javascript" src="StyledMarker.js"></script>


Then create and save the StyledMarker.js (http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/styledmarker/src/StyledMarker.js?r=143) with this content:
Code: Select all
/**
 * @name StyledMarkerMaker
 * @version 0.5
 * @author Gabriel Schneider
 * @copyright (c) 2010 Gabriel Schneider
 * @fileoverview This gives you static functions for creating dynamically
 *     styled markers using Charts API outputs as well as an ability to
 *     extend with custom types.
 */

/**
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var StyledIconTypes = {};
var StyledMarker, StyledIcon;

/**
 * @param {Function} childCtor Child class.
 * @param {Function} parentCtor Parent class.
 */
function inherits(childCtor, parentCtor) {
  /** @constructor */
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  childCtor.superClass_ = parentCtor.prototype;
  childCtor.prototype = new tempCtor();
  /** @override */
  childCtor.prototype.constructor = childCtor;
}
 
(function() {
  var bu_ = 'https://chart.googleapis.com/chart?chst=';
  var gm_ = google.maps;
  var gp_ = gm_.Point;
  var ge_ = gm_.event;
  var gmi_ = gm_.MarkerImage;
 

  /**
  * This class is an extended version of google.maps.Marker. It allows
  * styles to be applied that change it's appearance.
  * @extends google.maps.Marker
  * @param {StyledMarkerOptions} StyledMarkerOptions The options for the Marker
  */
  StyledMarker = function(styledMarkerOptions) {
    gm_.Marker.call(this);
    var me=this;
    var ci = me.styleIcon = styledMarkerOptions.styleIcon;
    me.bindTo('icon',ci);
    me.bindTo('shadow',ci);
    me.bindTo('shape',ci);
    me.setOptions(styledMarkerOptions);
  };
  inherits(StyledMarker, gm_.Marker);
 
  /**
  * This class stores style information that can be applied to StyledMarkers.
  * @extends google.maps.MVCObject
  * @param {StyledIconType} styledIconType The type of style this icon is.
  * @param {StyledIconOptions} styledIconOptions The options for this StyledIcon.
  * @param {StyledIcon} styleClass A class to apply extended style information.
  */
  StyledIcon = function(styledIconType,styledIconOptions,styleClass) {
    var k;
    var me=this;
    var i_ = 'icon';
    var sw_ = 'shadow';
    var s_ = 'shape';
    var a_ = [];

    function gs_() {
      var image_ = document.createElement('img');
      var simage_ = document.createElement('img');
      ge_.addDomListenerOnce(simage_, 'load', function() {
        var w = simage_.width, h = simage_.height;
        me.set(sw_,new gmi_(styledIconType.getShadowURL(me),null,null,styledIconType.getShadowAnchor(me,w,h)));
        simage = null;
      });
      ge_.addDomListenerOnce(image_, 'load', function() {
        var w = image_.width, h = image_.height;
        me.set(i_,new gmi_(styledIconType.getURL(me),null,null,styledIconType.getAnchor(me,w,h)));
        me.set(s_,styledIconType.getShape(me,w,h));
        image_ = null;
      });
      image_.src = styledIconType.getURL(me);
      simage_.src = styledIconType.getShadowURL(me);
    }

    /**
    * set:
    * This function sets a given style property to the given value.
    * @param {String} name The name of the property to set.
    * @param {Object} value The value to set the property to.
    * get:
    * This function gets a given style property.
    * @param {String} name The name of the property to get.
    * @return {Object}
    */
    me.as_ = function(v) {
      a_.push(v);
      for(k in styledIconOptions) {
        v.set(k, styledIconOptions[k]);
      }
    }

    if (styledIconType !== StyledIconTypes.CLASS) {
      for (k in styledIconType.defaults) {
        me.set(k, styledIconType.defaults[k]);
      }
      me.setValues(styledIconOptions);
      me.set(i_,styledIconType.getURL(me));
      me.set(sw_,styledIconType.getShadowURL(me));
      if (styleClass) styleClass.as_(me);
      gs_();
      me.changed = function(k) {
        if (k!==i_&&k!==s_&&k!==sw_) {
          gs_();
        }
      };
    } else {
      me.setValues(styledIconOptions);
      me.changed = function(v) {
        styledIconOptions[v] = me.get(v);
        for (k = 0; k < a_.length; k++) {
          a_[k].set(v,me.get(v));
        }
      };
      if (styleClass) styleClass.as_(me);
    }
  };
  StyledIcon.prototype = new gm_.MVCObject();
 
  /**
  * StyledIconType
  * This class holds functions for building the information needed to style markers.
  * getURL:
  * This function builds and returns a URL to use for the Marker icon property.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @return {String}
  * getShadowURL:
  * This function builds and returns a URL to use for the Marker shadow property.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @return {String{
  * getAnchor:
  * This function builds and returns a Point to indicate where the marker is placed.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @param {Number} width The width of the icon image.
  * @param {Number} height The height of the icon image.
  * @return {google.maps.Point}
  * getShadowAnchor:
  * This function builds and returns a Point to indicate where the shadow is placed.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @param {Number} width The width of the shadow image.
  * @param {Number} height The height of the shadow image.
  * @return {google.maps.Point}
  * getShape:
  * This function builds and returns a MarkerShape to indicate where the Marker is clickable.
  * @param {StyledIcon} icon The StyledIcon that holds style information
  * @param {Number} width The width of the icon image.
  * @param {Number} height The height of the icon image.
  * @return {google.maps.MarkerShape}
  */
 
  StyledIconTypes.CLASS = {};
 
  StyledIconTypes.MARKER = {
    defaults: {
      text:'',
      color:'00ff00',
      fore:'000000',
      starcolor:null
    },
    getURL: function(props){
      var _url;
      var starcolor_=props.get('starcolor');
      var text_=props.get('text');
      var color_=props.get('color').replace(/#/,'');
      var fore_=props.get('fore').replace(/#/,'');
      if (starcolor_) {
        _url = bu_ + 'd_map_xpin_letter&chld=pin_star|';
      } else {
        _url = bu_ + 'd_map_pin_letter&chld=';
      }
      if (text_) {
        text_ = text_.substr(0,2);
      }
      _url+=text_+'|';
      _url+=color_+'|';
      _url+=fore_;
      if (starcolor_) {
        _url+='|'+starcolor_.replace(/#/,'');
      }
      return _url;
    },
    getShadowURL: function(props){
      if (props.get('starcolor')) {
        return bu_ + 'd_map_xpin_shadow&chld=pin_star';
      } else {
        return bu_ + 'd_map_pin_shadow';
      }
    },
    getAnchor: function(props,width,height){
      return new gp_(width / 2,height);
    },
    getShadowAnchor: function(props,width,height){
      return new gp_(width / 4,height);
    },
    getShape: function(props,width,height){
      var _iconmap = {};
      _iconmap.coord = [
        width / 2, height,
        (7 / 16) * width, (5 / 8) * height,
        (5 / 16) * width, (7 / 16) * height,
        (7 / 32) * width, (5 / 16) * height,
        (5 / 16) * width, (1 / 8) * height,
        (1 / 2) * width, 0,
        (11 / 16) * width, (1 / 8) * height,
        (25 / 32) * width, (5 / 16) * height,
        (11 / 16) * width, (7 / 16) * height,
        (9 / 16) * width, (5 / 8) * height
      ];
      for (var i = 0; i < _iconmap.coord.length; i++) {
        _iconmap.coord[i] = Math.round(_iconmap.coord[i]);
      }
      _iconmap.type = 'poly';
      return _iconmap;
    }
  };
  StyledIconTypes.BUBBLE = {
    defaults: {
      text:'',
      color:'00ff00',
      fore:'000000'
    },
    getURL: function(props){
      var _url = bu_ + 'd_bubble_text_small&chld=bb|';
      _url+=props.get('text')+'|';
      _url+=props.get('color').replace(/#/,'')+'|';
      _url+=props.get('fore').replace(/#/,'');
      return _url;
    },
    getShadowURL: function(props){
      return bu_ + 'd_bubble_text_small_shadow&chld=bb|' + props.get('text');
    },
    getAnchor: function(props,width,height){
      return new google.maps.Point(0,42);
    },
    getShadowAnchor: function(props,width,height){
      return new google.maps.Point(0,44);
    },
    getShape: function(props,width,height){
      var _iconmap = {};
      _iconmap.coord = [
        0,44,
        13,26,
        13,6,
        17,1,
        width - 4,1,
        width,6,
        width,21,
        width - 4,26,
        21,26
      ];
      _iconmap.type = 'poly';
      return _iconmap;
    }
  };
})();


And after that, you can add really interesting markers which fullfill each of my requirements:

Code: Select all
styleIcon = new StyledIcon(StyledIconTypes.BUBBLE,{color:"#004eff",text:"Great Axton"});
       var styleMarker1 = new StyledMarker({
           styleIcon:styleIcon,
           position:new google.maps.LatLng(0.00142822265625, 0.0017578125000454747),
           map:map,
           draggable:false
       });



Unfortunetly I added all my markers right now hardcoded. Marker by marker. Maybe it would be better to organize the markers in an array, just thinking of a "Toggle-Markers" function for example...

If there are any questions, or if I missed something, just tell.

I love spolier tags for big quotes. xD

Yes, generally speaking markers are hardcoded. Its one of the reasons I'm using PHP, and why I will probably use something like PHPBB or MyBB to handle a few things - users, registration, permissions and to identify who 'owns' what markers. I've used both of them before in both personal projects (a roster system for the MMO Rift) and in projects for clients (lol, so very few people wanted SimpleMachines or VBulletin).

Markers can be saved into a database, and called per person, and/or per usergroup. PHP and JavaScript can talk to each other pretty easily, so PHP can dynamically create a group of markers, and JS can use them in the map - I did start playing around with it, I just didn't have time to finish or implement it.

Handling usergroups with both of the softwares I mentioned is pretty easy, and I'm thinking of just creating a group per registered 'village', and giving a leader of these groups the ability to add or remove members from their usergroups, so that, say...

Mushibag and Chief are both registered. A group for Gallows Hill and the Tribe are created. Mushi can add X person to group, they can see the Gallows markers - and add, remove or otherwise modify them - but Chiefs Tribe cannot, and vice versa. Markers and permissions database would simply have a field that says X group # can see these.

In the advent that multiple groups want to share their markers with each other, a second field will probably be there, to allow for this. An array could be called to check for extra permissions for other groups markers or something, I haven't quite gotten that far in planning. :p
Image
User avatar
imrielle
Customer
 
Posts: 491
Joined: Sat Nov 10, 2012 5:57 pm
Location: Ohio, USA

Re: Howto create a zoomable Salem map?

Postby liren » Thu Jan 31, 2013 3:32 am

Hi Imrielle,

Would you be willing to post your code in GitHub so anyone could fork it to create their own? I would love a local version running on my mac while playing.

Best,
Liren
liren
 
Posts: 13
Joined: Mon Dec 17, 2012 5:17 am
Location: Mountain View, CA, US

Previous

Return to Artifice & Arcana

Who is online

Users browsing this forum: No registered users and 14 guests