Difference between revisions of "Linden Lab Official:Map API Advanced Examples"

From Second Life Wiki
Jump to navigation Jump to search
Line 243: Line 243:


=== Getting current map center and bounds ===
=== Getting current map center and bounds ===
These features will let you see where the map is currently centered and what the current bounds of the map are. If you'd like, skip to the example.
 
Use the map object's getViewportBounds() method to get the bounds of the map. This method returns a [[Webmap_API_Reference#Bounds|Bounds]] object that has xMin, xMax, yMin, and yMax properties for the current viewport.
 
Use the map object's getMapCenter() method to get the coordinates of map.  This method returns an [[Webmap_API_Reference#XYPoint|XYPoint]] object representing the center of the map.
 
For example:


<pre>
<pre>
Line 250: Line 255:
</pre>
</pre>


The '''getViewportBounds()''' method  returns a [[Webmap_API_Reference#Bounds|Bounds]] object that has xMin, xMax, yMin, and yMax properties for the current viewport. The '''getMapCenter()''' method returns an XYPoint object representing the center of the map.
These methods are handy to display only markers inside the current map viewport, or display markers based on the proximity from the map center.
 
'''Example source code'''
 
<pre>
<!-- Insert common HTML header -->
<script>
var mapInstance;
 
function loadmap() {
  // creates the map
  mapInstance = new SLMap(document.getElementById('map-container'));
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(998.5,1001),2);
 
  var mapWindow1 = new MapWindow("This is (997,1002)");
  var mapWindow2 = new MapWindow("This is (1000,1000)");
  var mapWindow3 = new MapWindow("This is (1020,1020)");
 
  mapInstance.addMapWindow(mapWindow1, new XYPoint(997,1002));
  mapInstance.addMapWindow(mapWindow2, new XYPoint(1000,1000));
  mapInstance.addMapWindow(mapWindow3, new XYPoint(1020,1020));
 
  checkBounds();
}


Tips: These methods may handy if to display only markers inside the current map viewport, or display markers based on the proximity from the map center.
function checkBounds() {
  var bounds = mapInstance.getViewportBounds();
  var center = mapInstance.getMapCenter();
 
  document.getElementById('cent').innerHTML = "(" + center.x + "," + center.y + ")";
  document.getElementById('xMin').innerHTML = bounds.xMin;
  document.getElementById('xMax').innerHTML = bounds.xMax;
  document.getElementById('yMin').innerHTML = bounds.yMin;
  document.getElementById('yMax').innerHTML = bounds.yMax;
}
</script>
</head>
<body onload="loadmap()">
<p>Drag/zoom the map and then <a href="javascript: checkBounds();">click here</a>
to check the current viewport bounds and center coordinate</p>
 
<p>Center: <span id='cent'></span></p>
<p>X-Min: <span id='xMin'></span></p>
 
<p>X-Max: <span id='xMax'></span></p>
<p>Y-Min: <span id='yMin'></span></p>
<p>Y-Max: <span id='yMax'></span></p>
<div id="map-container"></div>
</body>
</pre>


== Working with markers ==
== Working with markers ==

Revision as of 18:41, 28 January 2009

Update notice

We've made improvements and changes to the webmap, effective January 15, 2009.
Some information here may be out of date as we update this wiki with the changes. Thanks for your patience.


Linking to a Second Life coordinate using x and y coordinates (NEW)

Teleport window.png

The new gotoSLURL() global function enables the user to teleport to the specified coordinate, given a valid SLMap instance. It first opens a window displaying the region name and a "Teleport" button, for example:

For example, the following method call will pop-up the window illustrated here; the user can the click the "Teleport" button to open the Second Life Viewer and teleport to (997,1002).

gotoSLURL(997,1002, mapInstance);

The example code below provides several similar examples.

Source code

<!-- Insert HTML header here -->
<script>
var mapInstance;
function loadmap() {
  // creates the map
  mapInstance = new SLMap(document.getElementById('map-container'));
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(997,1002),2);
}
</script>
</head>
<body onload="loadmap()">
<div id="map-container"></div>
<p>Click on these links to be teleported into Second Life via a SLURL:
<p><a href="javascript:gotoSLURL(997, 1002, mapInstance)"> Go to (997, 1002) </a>(where the welcome fountain is) <br />
<a href="javascript:gotoSLURL(996.5, 1001.6, mapInstance)"> Go to (996.5, 1001.6) </a> <br />

<a href="javascript:gotoSLURL(1000, 1000, mapInstance)"> Go to (1000, 1000) </a><br />
</body>

Working with maps

Customizing zoom and pan controls

It's easy to remove all the zoom and pan controls or create your own. When you create the SLMap object, simply specify false for the SLMapOptions properties hasZoomControls and hasPanningControls, for example:

mapInstance = new SLMap(document.getElementById('map-container'), 
                        {hasZoomControls: false, 
                         hasPanningControls: false});

This code creates a map with no zoom and pan controls.

To create your own zoom controls use the SLMap methods:

  • setCurrentZoomLevel()
  • getCurrentZoomLevel()
  • zoomIn()
  • zoomOut()

To create your own panning controls, use the SLMap methods:

  • panLeft()
  • panRight()
  • panUp()
  • panDown()

The following example contains a set of anchored links that call a function when clicked.

Example source code

<!-- Insert common HTML header -->
<script>
var mapInstance;

function loadmap() {
  // creates the map
  mapInstance = new SLMap(document.getElementById('map-container'), 
                          {hasZoomControls: false, hasPanningControls: false});
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(997,1002),2);
  
  (document.getElementById('zoom_level')).innerHTML = mapInstance.getCurrentZoomLevel();
}

function setZoom(level) {
  mapInstance.setCurrentZoomLevel(level);
  (document.getElementById('zoom_level')).innerHTML = mapInstance.getCurrentZoomLevel();
}

function zoomIn() {
  mapInstance.zoomIn();
  (document.getElementById('zoom_level')).innerHTML = mapInstance.getCurrentZoomLevel();
}

function zoomOut() {
  mapInstance.zoomOut();
  (document.getElementById('zoom_level')).innerHTML = mapInstance.getCurrentZoomLevel();
}
</script>
</head>
<body onload="loadmap()">
<p>This map has the usual pan/zoom controls disabled, and the hyperlinks 
below implement custom pan/zoom controls via SLMap Javascript calls.
<h2>Set the zoom level</h2>
<h3>The Current Zoom Level is <span style='color:red' id='zoom_level'></span></h3>

<a href="javascript: setZoom(1);">1</a>
<a href="javascript: setZoom(2);">2</a>
<a href="javascript: setZoom(3);">3</a>
<a href="javascript: setZoom(4);">4</a>
<a href="javascript: setZoom(5);">5</a>
<a href="javascript: setZoom(6);">6</a>
<a href="javascript: setZoom(7);">7</a>
<a href="javascript: setZoom(8);">8</a>
<a href="javascript: zoomIn();">zoom in</a>
<a href="javascript: zoomOut();">zoom out</a>

<h2>Pan Around</h2>

<a href="javascript: mapInstance.panLeft();">left</a>
<a href="javascript: mapInstance.panRight();">right</a>
<a href="javascript: mapInstance.panUp();">up</a>
<a href="javascript: mapInstance.panDown();">down</a>
<br><br>
<div id="map-container"></div>
</body>

Disabling and enabling dragging

To disable dragging on the map, simply call disableDragging() on the map object.

mapInstance.disableDragging();

When you are done call enableDragging() on the map object to re-enable dragging.

Example source code

<!-- Insert common HTML header -->
<script>
var mapInstance;

function loadmap() {
  mapInstance = new SLMap(document.getElementById('map-container'));
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(997, 1002), 2);
}

</script>
</head>
<body onload="loadmap()">
<p><a href="javascript: mapInstance.disableDragging();">Click to disable dragging map</a>
<p><a href="javascript: mapInstance.enableDragging();">Click to enable dragging map</a>

<div id="map-container"></div>
</body>

Panning or re-centering the map

Use the map object's panOrRecenterToSLCoord() method to pan the map to a specific point, providing the following parameters:

  • An XYPoint object, that identifies a specific x, y point.
  • Whether to recenter the map if the specified point is not currently visible. This parameter is optional and defaults to false.

For example:

mapInstance.panOrRecenterToSLCoord(new XYPoint(1000, 1000), true);

The above code pans or recenters to (1000, 1000) depending on the current view.

Example source code

<!-- Insert common HTML header --> 
<script>
var mapInstance;

function loadmap() {
  // creates the map
  mapInstance = new SLMap(document.getElementById('map-container'));
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(998.5, 1001), 2);
  
  var mapWindow1 = new MapWindow("This is (997, 1002)");
  var mapWindow2 = new MapWindow("This is (1000, 1000)");
  var mapWindow3 = new MapWindow("This is (1010.5, 1000.5)");
  
  mapInstance.addMapWindow(mapWindow1, new XYPoint(997, 1002));
  mapInstance.addMapWindow(mapWindow2, new XYPoint(1000, 1000));
  mapInstance.addMapWindow(mapWindow3, new XYPoint(1010.5, 1000.5));
}

</script>
</head>
<body onload="loadmap()">
<p>Click the links to pan or re-center the map on the indicated co-ordinates:
<p><a href="javascript: mapInstance.panOrRecenterToSLCoord(new XYPoint(1000, 1000), true);">
Pan or recenter to (1000, 1000)</a></p>
<p><a href="javascript: mapInstance.panOrRecenterToSLCoord(new XYPoint(1010.5, 1000.5), true);">
Pan or recenter to (1010.5, 1000.5)</a></p>

<div id="map-container"></div>
</body>

Setting a onStateChangedHandler event handler

The map object has an onStateChangedHandler that is a function called whenever the user pans or zooms the map. Specify it in the options when you initially create the map object. For example:

mapInstance = new SLMap(document.getElementById('map-container'), {onStateChangedHandler: doSomething});

Whenever the user zooms or pans the map, the Webmap API will call the doSomething function.

Hint: This feature is handy when you want to show markers only currently in the user's viewport: in the event handler function, simply remove all the current markers, then place a new set of markers on the map based on the current map bounds.

Example source code

<!-- Insert common HTML header -->  
<script>
function loadmap() {
  // creates the map
  mapInstance = new SLMap(document.getElementById('map-container'), 
                          {onStateChangedHandler: doSomething});
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(997, 1002), 2);
}
function doSomething() {
  alert("The map state has changed!!");
}
</script>
</head>
<body onload="loadmap()">
<p>This map will display an alert whenever the map's state changes (i.e. the map is panned or zoomed)
<div id="map-container"></div>
</body>

Getting current map center and bounds

Use the map object's getViewportBounds() method to get the bounds of the map. This method returns a Bounds object that has xMin, xMax, yMin, and yMax properties for the current viewport.

Use the map object's getMapCenter() method to get the coordinates of map. This method returns an XYPoint object representing the center of the map.

For example:

var bounds = mapInstance.getViewportBounds();
var center = mapInstance.getMapCenter(); 

These methods are handy to display only markers inside the current map viewport, or display markers based on the proximity from the map center.

Example source code

<!-- Insert common HTML header -->
<script>
var mapInstance;

function loadmap() {
  // creates the map
  mapInstance = new SLMap(document.getElementById('map-container'));
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(998.5,1001),2);
  
  var mapWindow1 = new MapWindow("This is (997,1002)");
  var mapWindow2 = new MapWindow("This is (1000,1000)");
  var mapWindow3 = new MapWindow("This is (1020,1020)");
  
  mapInstance.addMapWindow(mapWindow1, new XYPoint(997,1002));
  mapInstance.addMapWindow(mapWindow2, new XYPoint(1000,1000));
  mapInstance.addMapWindow(mapWindow3, new XYPoint(1020,1020)); 
  
  checkBounds();
}

function checkBounds() {
  var bounds = mapInstance.getViewportBounds();
  var center = mapInstance.getMapCenter();
  
  document.getElementById('cent').innerHTML = "(" + center.x + "," + center.y + ")";
  document.getElementById('xMin').innerHTML = bounds.xMin;
  document.getElementById('xMax').innerHTML = bounds.xMax;
  document.getElementById('yMin').innerHTML = bounds.yMin;
  document.getElementById('yMax').innerHTML = bounds.yMax;
}
</script>
</head>
<body onload="loadmap()">
<p>Drag/zoom the map and then <a href="javascript: checkBounds();">click here</a>
 to check the current viewport bounds and center coordinate</p>

<p>Center: <span id='cent'></span></p>
<p>X-Min: <span id='xMin'></span></p>

<p>X-Max: <span id='xMax'></span></p>
<p>Y-Min: <span id='yMin'></span></p>
<p>Y-Max: <span id='yMax'></span></p>
<div id="map-container"></div>
</body>

Working with markers

There are a variety of window options you can set. Please refer to the API Classes and Methods page for a complete explanation.

Setting a marker's event handlers

The following two features enable you great flexibility in customizing the behavior of maps.

Lets say you want to something else to happen besides a window opening when a marker is clicked. Like, for example, to retrieve a page about that specific coordinate or to show trigger some other javascript functionality you have on your page? Well, all this is possible.

// creates a function that we will bind to the marker click action
var doMarkerAction = function(marker) {
alert("an event occured at (" + marker.slCoord.x + "," + marker.slCoord.y + ")");
};

// creates the marker and sets its event handlers
var marker = new Marker(all_images, 
                        new XYPoint(997,1002), 
                        {clickHandler: doMarkerAction, 
                         onMouseOutHandler: doMarkerAction, 
                         onMouseOverHandler: doMarkerAction});

The code above simple sets the click handler, onmouseover, and onmouseout handlers of the marker to a function we've defined: doMarkerAction(). The marker is passed as a parameter to this function, so, if we want, we can remove it from the map, or just see what coordinate it lies on.

Setting a double click handler

This feature of the map is very similar to the previous example, except it instead of the user having to click on a marker, he can click on anywhere on the map. Cool? Yes we think so. Heres an simpler example to look at.

// creates a function that we will bind to the double click action
var doubleClickHandlerFunction = function(x,y) {
alert("you double clicked at (" + x + "," + y + ")");
};

// creates the map
var mapInstance = new SLMap(document.getElementById('map-container'),
                            {doubleClickHandler: doubleClickHandlerFunction});
mapInstance.centerAndZoomAtSLCoord(new XYPoint(997.5,1001.5),2);

The above code will fire off a javascript alert with the X and Y coordinate clicked. The X and Y coordinate will be passed as parameters to the function you specify to be the double click handler.

Similarly to the doubleClickHandler option, you can now set the singleClickHandler option. Please refer to this example

Removing a marker

Call the map object's removeMarker() method to remove a marker, passing the marker object as the parameter. For example:

mapInstance.removeMarker(myMarker);

The above code removes the marker myMarker.


Example source code

<script>
<!-- Insert common HTML header -->
// mapInstance and marker are global, so removeMarker() can access them.
var mapInstance, marker;

function loadmap() {
  // Creates the map
  mapInstance = new SLMap(document.getElementById('map-container'), {disableVoiceInfo: true});
  mapInstance.centerAndZoomAtSLCoord(new XYPoint(997,1002),2);
  
  // Creates the icons
  var yellow_dot_image = new Img("b_map_yellow.gif",9,9);
  var yellow_icon = new Icon(yellow_dot_image);
  var all_images = [yellow_icon, yellow_icon, yellow_icon, yellow_icon, yellow_icon, yellow_icon];
  
  // Creates the marker
  marker = new Marker(all_images, new XYPoint(997,1002));
  mapInstance.addMarker(marker);
}

function removeMarker() {
  // Removes the marker
  mapInstance.removeMarker(marker);
}
</script>
</head>
<body onload="loadmap()">
<a href="javascript: removeMarker();">Click to remove the yellow marker from the map</a>
<div id="map-container"></div>
</body>

Triggering a marker click

This feature simulates clicking a certain marker. If the marker currently isn't in the map viewport, it will recenter the map to this coordinate. If you'd like, skip to the example.

mapInstance.clickMarker(marker);

Tips: This feature can come in handy if you are listing links somewhere else on the page, and want links to open up markers with more information.

Using PNG images and shadows with markers

You can also use PNG Images to make your icons even more pretty. If you'd like, skip to the example.

// creates the icons
var forsale_sign = new Img("forsale.png",80,83, true); // note how the fourth parameter is set true!
var forsale_shadow = new Img("forsale-shadow.png",98,83, true);
var forsale_icon = new Icon(forsale_sign, forsale_shadow);
var all_images = [forsale_icon, forsale_icon, forsale_icon, forsale_icon, forsale_icon, forsale_icon];

// creates the marker
var marker = new Marker(all_images, new XYPoint(995,1004));
mapInstance.addMarker(marker);

The above code is almost identical to example two, except that when we define an Img, we specify a fourth argument in the constructor, telling the class to create the image with an alpha channel (alpha channel basically means that fancy transparency you cant get with GIF's). Also, when we create the Icon, we also specify another Img as the second argument, which specifies a shadow. Thats pretty much all you have to do to get pretty PNG icons.

Using Second Life region names (NOT IMPLEMENTED)

I know you've been wondering, what if I don't know which XY coordinate corresponds to which region name? Well, with this feature you can now use region names to define locations on the map instead of XY coordinates. If you'd like, skip to the example.

SLPoint('ahern',128,128); // use this instead of XYPoint(997,1002)

The above code simply creates an SLPoint located at the Welcome Area. Instead of having to figure out the XY coodinates, we were just able to use the region name. With this SLPoint now we can do whatever we want with it, like recenter the map here, put a window here, or put a marker here.

Note - The region name is case insensitive, so to specificy "Da Boom" region, you could use:

SLPoint("da boom") // OR
SLPoint("dA bOOm")