最近做了一个PC端列表页和地图找酒店页,两个页面需要用到Google Map API V3地图件。
其中花了比较多的时间的有两个地方,包括自定义图标和自定义信息框,这里将我的经验分享一下。因为是第一次用,所以写的有问题的地方请指出。
下面介绍了两种方法:
方法一是采用Google Map API V3中的markerImage对象来来生成自定义的图像;
方法二是利用Google Map API V3中的overLayView层来生成自定义的图标,相比于markerImage,overLayer的功能更强大。
最终结果的展示:主要功能是在列表页加载完成后获取列表中所有酒店的经纬度等信息,在地图上展示出来。并且对所有的图标marker进行点击事件绑定,还需要将在列表中的某一个酒店滑到屏幕中央时在地图上将该marker改为激活状态,如图中1号。
此处只说如何实现marker的自定义样式。如图,该自定义的marker图标有如下需求:
(1)、marker是动态的图片,展示含有数字1-30的小图片
(2)、在激活状态颜色变成黄颜色。
当时在处理这个问题的时候因为对API不了解,所以最先找到的是这个笨办法。就是利用API中的
MarkerImage对象生成自定义图标。下面是我的一张图片资源,使用MarkerImage对象就可以用这张图片根据需求生成带有不同颜色和标号的图标了。
/*
* 生成自定义标记图片
* @param i 列表中的第几个
* @param col 是否激活
* */
markerImage:function(i,col){
var imageUrl = 'http://img3.tuniucdn.com/img/201603151117/globalHotel/maplist_icon.png';
var markerImage = new google.maps.MarkerImage(
imageUrl,
new google.maps.Size(20, 25),
new google.maps.Point(i*20,col*25)
//'undefined',
//new google.maps.Size(40, 50)
//new google.maps.scaledSize(20, 25)
);
return markerImage;
}
当我们需要标号为1的激活(黄颜色)的图标时,就调用markerImage(0,0),对应的获取了图片中标记出来的区域,和CSS里面的背景图片一样,如图:
这样我们就可以获取这张大图上的各个图标了。
在实际项目中,通过dom加载完成后,获取整个列表的数据,循环该数据对象,将所有maker全部生成存放如一个数组中。
createMarkerList:function(data){
var map = map_box.map;
var markerList = [];
for(var i in data){
var LatLng = new google.maps.LatLng(data[i].lat,data[i].lng);
var image = {};
var marker = {};
image = map_box.markerImage(i,1);//未选中,第二列
marker = new google.maps.Marker({
position: LatLng, //经纬度位置 lat,lng
map:map,
icon:image,
title:i,
zIndex: parseInt(i)
});
markerList.push(marker);
}
map_box.markerList = markerList;
}
这样后面我们仅需要通过传递过来 i(当前需激活的图标index) 就可以操作该图标了。当需要是某一个图标激活时,我们先生成新的图片,再使用marker.setIcon()将图片替换掉。
/*
* 给marker添加样式
* addOrRemove ture add
* */
addOrRemoveMarkerCss:function(marker,i,addOrRemove){
if(addOrRemove){
image = map_box.markerImage(i,0);//选中,第一列
marker.setIcon(image);
marker.setZIndex(9999);
}else{
image = map_box.markerImage(i,1);//未选中,第二列
/*
* 此处ie8和以下版本不兼容Google API 的(setIcon setZIndex)
* 重置方法,会报错,影响更随浮动的点击事件
* */
if( !(($.browser.msie) && (parseFloat($.browser.version) <= 8.0)) ){
marker.setIcon(image);
marker.setZIndex(parseInt(i));
}
}
}
利用OverlayView对象。具体代码如下:
<html>
<head>
<title>Google Maps JavaScript API v3: Custom Marker Demotitle>
<script type="text/javascript" src="http://ditu.google.cn/maps/api/js?sensor=false&language=zh-CN">script>
<script>
function CustomMarker(latlng, map) {
this.latlng_ = latlng;
// Once the LatLng and text are set, add the overlay to the map. This will
// trigger a call to panes_changed which should in turn call draw.
this.setMap(map);
}
CustomMarker.prototype = new google.maps.OverlayView();
CustomMarker.prototype.draw = function() {
var me = this;
// Check if the div has been created.
var div = this.div_;
if (!div) {
// Create a overlay text DIV
div = this.div_ = document.createElement('DIV');
// Create the DIV representing our CustomMarker
div.style.border = "none";
div.style.position = "absolute";
div.style.paddingLeft = "0px";
div.style.cursor = 'pointer';
div.style.width = '30px';
div.style.height = '30px';
div.style.lineHeight = '30px';
div.style.textAlign = 'center';
div.style.backgroundColor = "greenyellow";
// var img = document.createElement("img");
// img.src = "http://gmaps-samples.googlecode.com/svn/trunk/markers/circular/bluecirclemarker.png";
var span = document.createElement("span");
span.innerHTML = "ME!";
div.appendChild(span);
google.maps.event.addDomListener(div, "click", function(event) {
console.log(1111);
google.maps.event.trigger(me, "click");
});
// Then add the overlay to the DOM
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
}
// Position the overlay
var point = this.getProjection().fromLatLngToDivPixel(this.latlng_);
if (point) {
div.style.left = point.x + 'px';
div.style.top = point.y + 'px';
}
};
CustomMarker.prototype.remove = function() {
// Check if the overlay was on the map and needs to be removed.
if (this.div_) {
this.div_.parentNode.removeChild(this.div_);
this.div_ = null;
}
};
CustomMarker.prototype.getPosition = function() {
return this.latlng_;
};
var map;
var overlay;
function initialize() {
var opts = {
zoom: 9,
center: new google.maps.LatLng(-34.397, 150.644),
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map"), opts);
overlay = new CustomMarker(map.getCenter(), map);
var iw = new google.maps.InfoWindow({content: "Hello!", pixelOffset: new google.maps.Size(5,0)});
iw.open(map, overlay);
google.maps.event.addListener(overlay, "click", function() {
iw.open(map, overlay);
});
}
function addOverlay() {
overlay.setMap(map);
}
function removeOverlay() {
overlay.setMap(null);
}
script>
head>
<body onload="initialize()">
<div id="map" style="width: 320px; height: 480px;">map divdiv>
<div>
<input type="button" value="Add Marker" onclick="addOverlay()">
<input type="button" value="Remove Marker" onclick="removeOverlay()">
div>
body>
html>
markImage要比overLayView更方便快捷,采用如果展示信息比较单一,仅用一张图片就可以替代,使用起来很方便,也很快捷(上面讲的第一种实现方法,后来也被我用overLayView进行了改写);overLayView方法更强大,可以实现多种需求,但组织起来较复杂。文档中对两个对象和方法都有明确定义。
MarkerImage(url:string,size?:Size,origin?:Point,anchor?:Point,scaledSize?:Size)
定义一张用作标记图标或者阴影的图像。“origin”和“size”用于选择拼合图像的图块,“anchor”重写锚点默认所处的底部中间位置。图像的锚点是系统在跟踪图像位置时引用的像素。默认情况下,锚点设置为图像的底部中间位置 (坐标宽度/2, 高度)。因此,当标记放置在指定的LatLng上时,定义为锚点的像素就定位于指定的LatLng上。要缩放图像,无论该图像是否为拼合图像,都请将scaledSize 的值设置为整个图像的大小,并用换算值设置大小、原点和锚点。MarkerImage 在构造完成后就无法更改。OverlayView 类:如果想在地图上显示自定义类型的叠加层对象,则可以使用此类。此类扩展
了 MVCObject。
构造函数:OverlayView()
action | returnValue | explain |
---|---|---|
draw() | None | 实现此方法可绘制或更新叠加层。在实现onAdd()以后,并且projection.fromLatLngToPixel() 的位置返回指定 LatLng 的新值时,调用此方法。缩放、中心或地图类型发生更改时将会调用此方法。拖动或重新设定大小时无需调用该方法。 |
getMap() | Map | |
getPanes() | MapPanes | 返回可在其中显示此OverlayView 的窗格。仅在调用 draw 函数后才可用。 |
getProjection() | MapCanvasProjection | 返回与相应 OverlayView相关联MapCanvasProjection对象。仅在调用 draw 函数后才可用。 |
onAdd() | None | 实现此方法可初始化叠加层 DOM 元素。对有效地图调用 setMap() 之后,调用该方法一次。此时将会初始化窗格和投影。 |
onRemove() | None | 实现此方法可将您的元素从 DOM 删除。调用setMap(null) 之后立即调用此方法。 |
setMap(map:Map(or)StreetViewPanorama) | None | 将叠加层添加到地图或全景图。 |