RkkiiiiClickable Map Icons
------------> Chat here, or Forums for help: http://p2pu.org/webcraft/node/12927/forums
A : Set up your map
Make sure you know how to set up an OpenLayers map on http://jsFiddle.net
- You could also start with our map at http://jsfiddle.net/UAxun/46/ On the top menu, click "Run" to test your new code, and "Update" to get a new URL to share with the group
B: Add your first Point
- Before you can create an icon, you have to create a Point object
Fortunately, this part isn't any more difficult than it was to create a LonLat object:
long = 78.042068;
lat = 27.173768;
myPoint = new OpenLayers.Geometry.Point(long,lat).transform( map.displayProjection, map.projection);
- As described in the OpenLayers WalkThrough, you're transforming the degrees of latitu
- de and longitude into the measurement system used by the map. Without this transform, you would need to calculate the position in meters instead of degrees.
- When we stack, mix, and match different sources on top of the map, we call them layers. Your Point object is going to be added using a new type called a Vector layer. The OSM layer is made up of many tiles, but this vector layer is made up of points.
layerStyle = OpenLayers.Util.extend( { }, OpenLayers.Feature.Vector.style['default']);
pointLayer = new OpenLayers.Layer.Vector("Layer Name", {style: layerStyle});
map.addLayer(pointLayer);
- Some maps libraries let you add a point very quickly, but OpenLayers is precise about things. You want to customize myPoint before adding it to pointLayer.
sampleStyle = OpenLayers.Util.extend( { }, layerStyle);
sampleStyle.fillColor = "blue"; // the main color of the shape
sampleStyle.graphicName = "square"; // other good shapes are "star", "circle"
sampleStyle.pointRadius = 10; // controls the size of the marker
sampleStyle.strokeColor = "blue"; // the border color of the shape
sampleStyle.strokeWidth = 3; // border width
sampleStyle.fillOpacity = 1; // from 0 (transparent) to 1 (opaque)
sampleStyle.graphicOpacity = 1; // from 0 (transparent) to 1 (opaque)
pointLayer.addFeatures( [ new OpenLayers.Feature.Vector(myPoint,null,sampleStyle) ] );
- Tah-dah! Let's see what that looks like (if you don't see anything, make sure the place where you are adding the point is visible on your map!) http://jsfiddle.net/UAxun/68/
- Adding a second, different-looking point is much easier. You can copy sampleStyle and make a small adjustment to make rotatedStyle, like this:
rotatedStyle = OpenLayers.Util.extend( { }, sampleStyle);
rotatedStyle.rotation = 45; // 0 to 360 degrees... this doesn't work as well for circles
// create a new point called rotatedPoint
pointLayer.addFeatures( [ new OpenLayers.Feature.Vector(rotatedPoint,null,rotatedStyle) ] );
I played around with some style options to get http://jsfiddle.net/UAxun/70/
C: Add your first icon
- An icon is no different from any other style option. Go back to when you created sampleStyle and add this line to the end:
sampleStyle.externalGraphic ="http://google-maps-icons.googlecode.com/files/palace.png";
- My icon looked small. Just like with the original point object, increase the pointRadius to change the size
sampleSize.pointRadius = 24;
Notice that when you change sampleSize, it also affects all styles you copied from it, so the rotatedStyle points also have this icon: http://jsfiddle.net/UAxun/71/
D: Multiple icons
- Use the libraries listed above to find more icons for your map
- Create one standardStyle with the size, transparency, and other things that you want
- Copy standardStyle for each different icon, using the code
dolphinIconStyle= OpenLayers.Util.extend( { }, standardStyle);
dolphinIconStyle.externalGraphic = "http://google-maps-icons.googlecode.com/files/dolphins.png";
E: Attributes
For awhile, we've been using this line to add a point:
pointLayer.addFeatures( [ new OpenLayers.Feature.Vector(rotatedPoint,null,rotatedStyle) ] );
- Let's break this down to two lines:
// create myPoint and myStyle before this line
myPointFeature = new OpenLayers.Feature.Vector(myPoint,null,myStyle)
pointLayer.addFeatures( [ myPointFeature ] );
- If you're not familiar with JavaScript, here's a quick explainer. Curly brackets create an object, which are essentially a list of properties. Place a comma after each item in the list, except for the last. For example:
osm = { fullName: "OpenStreetMap", isOpen: true, homepage:"http://openstreetmap.org" } ;
bng = { fullName: "Bing Maps", isOpen: false, homepage:"http://maps.bing.com" } ;
Now we can check these properties. For example, osm.isOpen = true, and window.location=bng.homepage will send your browser to maps.bing.com
- Go back to your maps code, and add some custom properties to myPointFeature.
myPointFeature = new OpenLayers.Feature.Vector(myPoint,null,myStyle)
myPointFeature.attributes = {
name: "Taj Mahal",
description: "One of India's most famous buildings",
wikiPage: "http://simple.wikipedia.org/wiki/Taj_Mahal "
};
pointLayer.addFeatures( [ myPointFeature ] );
- Now each of your points is a lot smarter. It knows what its name is, can describe itself, and can give you a link to a page on Wikipedia. Now we just need a way to know if the user is asking for this information, by clicking on that icon.
F: Clicks and good popups make an interactive map
- Okay. A couple more leaps of faith and you have an interactive map.
- I assume your layer is still called pointLayer. Always double-check when you use someone else's variable names.
- A SelectFeature control handles the difficult part of finding when someone is clicking on an icon, and what that icon is. Then you set up responses.
// create a Control that watches for clicking on a feature, then add the control to the map
selectControl = new OpenLayers.Control.SelectFeature( pointLayer );
map.addControl(selectControl);
selectControl.activate();
/* the control calls events (featureselected and featureunselected) and we connect those events to functions */
pointLayer.events.on({
'featureselected': onFeatureSelect,
'featureunselected': onFeatureUnselect
});
- onFeatureSelect and onFeatureUnselect are functions. Instead of running our code from top to bottom, these functions will not run until something (our clicks on the map) call them.
- We're going to make the map create a popup window and show the name of a place. Remember you added a name in the last section about Attributes
- I modified this code from an OpenLayers example and Ushahidi's open source map code. You can learn more about what it does later, and change some values to see how it affects things, or see the library at http://dev.openlayers.org/releases/OpenLayers-2.6/doc/apidocs/files/OpenLayers/Popup/FramedCloud-js.html
function onFeatureSelect(clickInfo) {
clickedFeature = clickInfo.feature;
popup = new OpenLayers.Popup.FramedCloud(
"featurePopup", // an ID for this popup
clickedFeature.geometry.getBounds().getCenterLonLat(), // anchor to the icon
new OpenLayers.Size(120,250), // set height and width of the window
clickedFeature.attributes.name, // HTML displayed inside the window
null, // used for other applications
true, // have an [x] to close the Popup
onPopupClose // call another function when the Popup is closed
);
// let feature and popup 'know' about each other
clickedFeature.popup = popup;
popup.feature = clickedFeature;
// add the popup to the map
map.addPopup(popup);
}
function onFeatureUnselect(clickInfo) {
feature = clickInfo.feature;
if (feature.popup) {
// if an icon with a popup window is un-selected, that popup is removed
popup.feature = null;
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
}
function onPopupClose(closeInfo) {
// closing the Popup un-selects the icon
selectControl.unselect(this.feature);
}
- This is a lot of code to take on faith, but most of the difficult parts of understanding clicks and designing the window is done for you.
- I'm going to focus on just one clickable icon for now. I went back to my example and removed the other icons, to get this: http://jsfiddle.net/UAxun/72/
------------> Go to the forums for help: http://p2pu.org/webcraft/node/12927/forums
Once you have that working...
- The line after setting the Popup's size is the line setting what appears inside:
clickedFeature.attributes.name,
- This can be any HTML. Take this line and do something cool with it. For example, let's have the name be a bold red section - <h3></h3> - and then write the description.
"<h3 style='font-weight:bold;color:red;'>" + clickedFeature.attributes.name + "</h3>" + clickedFeature.attributes.description,
Make sure that the line still ends with a comma.
If things go wrong, use your browser's built-in debugger to see if you used the wrong variable name or punctuation.
http://jsfiddle.net/UAxun/73/
<a href="http://example.com?TheLinkURL" target="_blank">Link Text</a>
- Can anyone make it show an image? What about images for two separate markers? The HTML for adding an image is:
<img src="http://example.com/ImageURL.jpg"/>