房产地图google map的初步应用点滴.1)
房产地图google map的初步应用点滴.2)
房产地图google map的初步应用点滴.3)

本来是想将房产地图google map的应用记录一个系列,但继1)记录完之后总找不到时间继续记录下去,1)中主要解决了Google Maps JavaScript API V3 与 Google Local Search API两者由于版本问题带来的一系列麻烦,思路是使用一个iframe作为兼容的跳板,子页面应用Local Search API获得查询的result后返回给父页面,下面再记录一些地图坐标的定位和一些UI的组成。

效果可参考 http://xf.house.163.com/gz/map/00Xa.html

1.坐标定位

打开一个楼盘的地图,首先需要将此楼盘定位为此地图的中心点

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=GBK"/>
<title></title>
<style type="text/css"> 
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
      var map;
      var lat = 23.1257424;
      var lng = 113.37404225;
      function init() {
        var mapDiv = document.getElementById('map-canvas');
          map = new google.maps.Map(mapDiv, {
            center: new google.maps.LatLng(lat,lng),
            zoom: 15,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });
      }
      google.maps.event.addDomListener(window, 'load', init);
    </script>
</head>
<body style="">
<div id="map-canvas" style="width: 600px; height: 500px"></div>
</body>
</html>

这里要注意的是我们引进了http://maps.google.com/maps/api/js?sensor=false,这是google MAP API V3版本的连接点
创建了一个div <div id="map-canvas" style="width: 600px; height: 500px"></div>作为地图的容器,然后对地图基本类Map进行创建

google.maps.Map 是google map的容器实现,在指定的 HTML 容器中创建新的地图,该容器通常是一个DIV元素
在初始化地图,还要创建一个地图的初始化变量,这些变量包括了上面的center,zoom,mapTypeId等等

google.maps.LatLng 是一个以纬度和经度表示的地理坐标点,在上面我们使用一个定义好的LatLng类确定了整个地图的中心点,其中lat 和 lng 分别为我们楼盘的经纬度值 
zoom 为地图展开的级别
google.maps.MapTypeId.ROADMAP 是地图显示的类型,通常有ROADMAP,SATELLITE,TERRAIN等等,这里选择的ROADMAP类型是显示为普通的街道地图

2.为定位的楼盘添加图标

在上面完成了将楼盘显示到整个地图的中心处,下面为该楼盘添加图标,给楼盘坐标的位置添加图标,实际上也就是在地图上添加一个叠加层,在google MAP API中拥有大量的实现类,如Marker,为我们上面的程序加多个Marker实现,楼盘的图标就可以显示出来

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=GBK"/>
<title></title>
<style type="text/css"> 
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
      var map;
      var lat = 23.1257424;
      var lng = 113.37404225;
      function initialize() {
        var mapDiv = document.getElementById('map-canvas');
          map = new google.maps.Map(mapDiv, {
            center: new google.maps.LatLng(lat,lng),
            zoom: 15,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(lat,lng), 
            map: map
        });
      }
      google.maps.event.addDomListener(window, 'load', initialize);
    </script>
</head>
<body style="">
<div id="map-canvas" style="width: 600px; height: 500px"></div>
</body>
</html>

但是呢,这个图标并不是我们想要的,我们想要的是在此楼盘经纬度处放入自己的图片,设置是一段html的显示代码来组成自定义的叠加层,并且这个叠加层可以监听各种事件,可以对拖动地图的DOM元素中指定的地理位置像素坐标进行计算

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=GBK"/>
<title></title>
<style type="text/css"> 
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
      var map;
      var lat = 23.1257424;
      var lng = 113.37404225;
      function initialize() {
        var mapDiv = document.getElementById('map-canvas');
          map = new google.maps.Map(mapDiv, {
            center: new google.maps.LatLng(lat,lng),
            zoom: 15,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });
        new CustomMarker(map.getCenter(), map);
      }

function CustomMarker(latlng,map) {
         this.latlng_ = latlng;
         this.setMap(map);
      }
    //扩展自OverlayView;OverlayView扩展自MVCObject,实际上也扩展自MVCObject
    CustomMarker.prototype = new google.maps.OverlayView();

CustomMarker.prototype.draw = function() {
    var me = this;
    var div = this.div_;
    if (!div) {
        div = this.div_ = document.createElement('DIV');
        div.style.position = "absolute";
        div.innerHTML = "<span><img src='http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/examples/images/house.png'/></span>";
        //这个div的对象需要Listener事件,必须先用trigger(me)先进行侦听
        google.maps.event.addDomListener(div, "click", function(event) {
            google.maps.event.trigger(me, "click");
        });
        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    }
    CustomMarker.prototype.remove = function() {
        if (this.div_) {
            this.div_.parentNode.removeChild(this.div_);
            this.div_ = null;
        }
    };
    //获取Position
    CustomMarker.prototype.getPosition = function() {
        return this.latlng_;
    };
}
      google.maps.event.addDomListener(window, 'load', initialize);
    </script>
</head>
<body style="">
<div id="map-canvas" style="width: 500px; height: 400px"></div>
</body>
</html>

实现效果如下

我们创建一个CustomMarker类,扩展自OverlayView;OverlayView扩展自MVCObject,实际上也扩展自MVCObject
这里需要详细说说OverlayView,我们继承了此类,方法是将叠加层的 prototype 设置为 new OverlayView.prototype。必须实现三个方法,即 onAdd()、draw() 和 onRemove()。在 add() 方法中,您应当创建 DOM 对象,并将其作为窗格的子对象附加。在 draw() 方法中,应放置这些元素。在 onRemove() 方法中,应将对象从 DOM 中删除。您必须调用包含有效地图对象的 setMap(),以触发对 onAdd() 方法和 setMap(null) 的调用,这样才能触发 onRemove() 方法。可以在构建叠加层时调用 setMap() 方法,也可以在需要重新显示已删除叠加层的任何时候调用该方法。每当地图属性更改时都会调用 draw() 方法,该方法可以更改元素的位置,如缩放、中心或地图类型。

把叠加层的绘图放在draw()方法中,我们再此方法中创建了一个DIV,并且使用innerHTML属性将要显示的html代码写回div中,并且如果需要对此属性加添加Listener事件时,则必须先使用trigger(me)先进行侦听,这样才能对外部的event事件进行反应,在构建完div后还需要获得panes窗口,panes包含渲染叠加层的 DOM 元素,作为显示此 OverlayView 的窗格,记住它是必须在draw 方法调用后才能实用。
onRemove() 实现此方法可将您的元素从 DOM 删除。调用 setMap(null) 之后立即调用此方法。
getProjection() 返回与相应 OverlayView 相关联的 MapCanvasProjection 对象。仅在调用 draw 函数后才可用

3.点击楼盘图标填出楼盘信息盒子
下面再需要实现的效果是点击刚才创建的楼盘图标,则弹出一个楼盘信息盒子
先上代码,再上效果图

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=GBK"/>
<title></title>
<style type="text/css"> 
@import url("http://img1.cache.netease.com/cnews/css07/style.css");
@import url("http://img1.cache.netease.com/cnews/img09/channel_nav.css");
@import url("http://xf.house.163.com/product/css/ydmap.css");
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
      var map;
      var lat = 23.1257424;
      var lng = 113.37404225;
      function initialize() {
        var mapDiv = document.getElementById('map-canvas');
          map = new google.maps.Map(mapDiv, {
            center: new google.maps.LatLng(lat,lng),
            zoom: 15,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        });
        var marker = new CustomMarker(map.getCenter(), map);
        google.maps.event.addListener(marker, "click", function(e) {
            var infoBox = new InfoBox({
                latlng : marker.getPosition(),
                map : map
            });
            });
      }

function CustomMarker(latlng,map) {
         this.latlng_ = latlng;
         this.setMap(map);
      }
    //扩展自OverlayView;OverlayView扩展自MVCObject,实际上也扩展自MVCObject
    CustomMarker.prototype = new google.maps.OverlayView();

CustomMarker.prototype.draw = function() {
    var me = this;
    var div = this.div_;
    if (!div) {
        div = this.div_ = document.createElement('DIV');
        div.style.position = "absolute";
        div.innerHTML = "<span><img src='http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/examples/images/house.png'/></span>";
        //这个div的对象需要Listener事件,必须先用trigger(me)先进行侦听
        google.maps.event.addDomListener(div, "click", function(event) {
            google.maps.event.trigger(me, "click");
        });
        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    }
    //计算存放可拖动地图的 DOM 元素中指定地理位置的像素坐标
    var point = this.getProjection().fromLatLngToDivPixel(this.latlng_);
    //div的像素坐标
    if (point) {
        div.style.left = point.x + 'px';
        div.style.top = point.y + 'px';
    }
    };

CustomMarker.prototype.remove = function() {
        if (this.div_) {
            this.div_.parentNode.removeChild(this.div_);
            this.div_ = null;
        }
    };
    //获取Position
    CustomMarker.prototype.getPosition = function() {
        return this.latlng_;
    };

/*********************************************************************************************************************************************************
 * InfoBox==楼盘icon点击后弹出的box窗口,继承OverlayView,
 */

function InfoBox(opts) {
    google.maps.OverlayView.call(this);
    this.latlng_ = opts.latlng;
    this.map_ = opts.map;
    this.offsetVertical_ = -260;
    this.offsetHorizontal_ = -450;
    //div偏移的像素
    this.height_ = 260;
    this.width_ = 460;
    var me = this;
    //监听bounds
    this.boundsChangedListener_ = google.maps.event.addListener(this.map_,
            "bounds_changed", function() {
                return me.panMap.apply(me);
            });
    this.setMap(this.map_);
}
InfoBox.prototype = new google.maps.OverlayView();
//移除div
InfoBox.prototype.remove = function() {
    if (this.div_) {
        this.div_.parentNode.removeChild(this.div_);
        this.div_ = null;
    }
};
InfoBox.prototype.draw = function() {
    // 创建element
    this.createElement();
    if (!this.div_)
        return;
    var pixPosition = this.getProjection().fromLatLngToDivPixel(this.latlng_);
    if (!pixPosition)
        return;
    // top,left减去width,height达到右下角对齐的效果
    this.div_.style.width = this.width_ + "px";
    this.div_.style.left = (pixPosition.x + this.offsetHorizontal_ )+ "px";
    this.div_.style.height = this.height_ + "px";
    this.div_.style.top = (pixPosition.y + this.offsetVertical_ )+ "px";
    this.div_.style.display = 'block';
};
InfoBox.prototype.createElement = function() {
    //返回可在其中显示此 OverlayView 的窗格。仅在调用 draw 函数后才可用。
    var panes = this.getPanes();
    var div = this.div_;
    if (!div) {
        div = this.div_ = document.createElement("div");
        var content = document.getElementById("houseInfoBox_template").value;
        div.style.border = "0px none";
        div.style.position = "absolute";
        div.innerHTML = content;
        panes.floatPane.appendChild(div);
        this.panMap();
    } else if (div.parentNode != panes.floatPane) {
        // 如果panes发生变化,移除此div
        div.parentNode.removeChild(div);
        panes.floatPane.appendChild(div);
    } else {
    }
}
/*
 * 对InfoBox的pan进行调整,调整到居中值减去偏移值,控制infobox的位置
 */
InfoBox.prototype.panMap = function() {
    var map = this.map_;
    //返回当前视口的纬度/经度范围。如果还未启动地图(即 mapType 仍为 Null),或者没有设置中心和缩放,则结果为 Null。
    var bounds = map.getBounds();
    if (!bounds)
        return;
    // InfoBox的位置
    var position = this.latlng_;
    // InfoBox的尺寸
    var iwWidth = this.width_;
    var iwHeight = this.height_;
    // infobox位置和尺寸的抵消
    var iwOffsetX = this.offsetHorizontal_;
    var iwOffsetY = this.offsetVertical_;
    var padX = 40;
    var padY = 40;
    // 像素的计算
    var mapDiv = map.getDiv();
    var mapWidth = mapDiv.offsetWidth;
    var mapHeight = mapDiv.offsetHeight;
    var boundsSpan = bounds.toSpan();////将指定的地图范围转换为纬度/经度跨度。
    var longSpan = boundsSpan.lng();//
    var latSpan = boundsSpan.lat();//纬度的地图跨度
    var degPixelX = longSpan / mapWidth;
    var degPixelY = latSpan / mapHeight;
    // 地图界面跳动的定位
    var mapWestLng = bounds.getSouthWest().lng();
    var mapEastLng = bounds.getNorthEast().lng();
    var mapNorthLat = bounds.getNorthEast().lat();
    var mapSouthLat = bounds.getSouthWest().lat();
    // infowindow的bounds
      var iwWestLng = position.lng() + (iwOffsetX - padX) * degPixelX;
      var iwEastLng = position.lng() + (iwOffsetX + iwWidth + padX) * degPixelX;
      var iwNorthLat = position.lat() - (iwOffsetY  - padY) * degPixelY;
      var iwSouthLat = position.lat() - (iwOffsetY + iwHeight + padY) * degPixelY;
    // 向居中的偏移计算
     var shiftLng = (iwWestLng < mapWestLng ? mapWestLng - iwWestLng : 0) ;
     var shiftLat = (iwNorthLat > mapNorthLat ? mapNorthLat - iwNorthLat : 0) ;
    // 居中值
    var center = map.getCenter();
    // 居中值减去偏移值,得到infobox的位置
    var centerX = center.lng() - shiftLng;
    var centerY = center.lat() - shiftLat;
    //***********************************************************
    // 重新确定并显示楼盘为地图的中心点 ps:此处取消重新定位
    map.setCenter(new google.maps.LatLng(centerY, centerX));
    //***********************************************************
    // 移除上面bounds监听值“this.boundsChangedListener_”
    google.maps.event.removeListener(this.boundsChangedListener_);
    this.boundsChangedListener_ = null;    
    };
      google.maps.event.addDomListener(window, 'load', initialize);
    </script>
</head>
<body style="">
<div id="map-canvas" style="width: 600px; height: 400px"></div>
<textarea name="houseInfoBox_template" id="houseInfoBox_template">
<div class="houseInfoBox" style="width:460px;height:200px;">
<div class="boxc2"></div>
<div class="boxc1"></div>
<div class="boxc3"></div>
<div class="boxc5">
<div class="boxc4"></div>
<div class="houseDataMap">
<h2 class="title">房产地图</h2>
<div class="tabTilHouse">
<ul>
<li class="on">楼盘信息</li>
</ul>
</div>
<div class="datas">
<div class="infos">
<span class="equal">本月均价:<strong class="cDRed">¥1000</strong></span>
<span class="blank3"></span>
地址:广州广州广州广州广州广州广州<br />
电话:123123123123
<p class="about">简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介简介 <span class="cDRed"><a href="">&raquo;查看详情</a></span></p>
</div>
<div class="prePic"><a href=""><img src="http://img2.cache.netease.com/photo/0087/2009-07-13/1247479037333.jpg" width="160" height="120" /></a></div>
</div>
</div>
<div class="boxc6"></div>
</div>
<div class="boxc7"></div>
<div class="boxc8"></div>
<div class="boxc9" ></div>
<span class="close" id="infohouse_close"></span>
</div>
</textarea>
</body>
</html>

下面是效果图

看似有点恐怖增加了很多代码,其实只是增加了一个InfoBox类,也是扩展自OverlayView,基本上实现的道理跟上面的CustomMarker一样,不过里面多了很多细节,最重要一点是div的偏移计算,因为这个box对应的方位是右下角,而div在定义时候与像素的对应点是在左上角,所以这里涉及到一个对InfoBox的pan进行调整,调整到居中值减去偏移值,控制infobox的位置,可见代码 InfoBox.prototype.panMap = function() {},当然啦,偏移值是跟你的div实际情况有关的,记住要将偏移像素值换算成地图的经纬度值,这部分计算的细节很多,要安装实际情况进行转换。

        var marker = new CustomMarker(map.getCenter(), map);
        google.maps.event.addListener(marker, "click", function(e) {
            var infoBox = new InfoBox({
                latlng : marker.getPosition(),
                map : map
        });
        });

为楼盘图标添加一个addListener click事件,只要触动click就会相应new InfoBox,其实google的event非常多

房产地图google map的初步应用点滴.2)(转)的更多相关文章

  1. 房产地图google map的初步应用点滴.4)(转)

    房产地图google map的初步应用点滴.1) 房产地图google map的初步应用点滴.2) 房产地图google map的初步应用点滴.3) 房产地图google map的初步应用点滴.4) ...

  2. 房产地图google map的初步应用点滴.3)(转)

    房产地图google map的初步应用点滴.1)房产地图google map的初步应用点滴.2)房产地图google map的初步应用点滴.3) 房产地图google map的初步应用点滴.4) go ...

  3. 房产地图google map的初步应用点滴.1)(转)

    房产地图google map的初步应用点滴.1)房产地图google map的初步应用点滴.2)房产地图google map的初步应用点滴.3) 房产地图google map的初步应用点滴.4) 以前 ...

  4. 谷歌地图实现车辆轨迹移动播放(google map api)

    开发技术:jquery,js baidu map api,json,ajax QQ1310651206 谷歌地图(google map api)实现车辆轨迹移动播放(google map api)

  5. Android Google Map API使用的八个步骤

    本系列教程将分为两部分,第一部分是指导用户使用Mapview控件进行编程,其中包括了如何获得Google Map API,如何使用该API进行简单的开发,如何获得用户当前所在的位置.第二部分则包括如何 ...

  6. Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解

    在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...

  7. Google Map API v2 (三)----- 地图上添加标记(Marker),标记info窗口,即指定经纬度获取地址字符串

    接上篇 http://www.cnblogs.com/inkheart0124/p/3536322.html 1,在地图上打个标记 private MarkerOptions mMarkOption; ...

  8. Google Map API v2 步步为营(一) ----- 初见地图

    官方文档:https://developers.google.com/maps/documentation/android/start?hl=zh-CN 先谷歌后百度.使用google的api基本上按 ...

  9. arcgis api for silverlight使用google map等多个在线地图

    原文 http://blog.csdn.net/leesmn/article/details/6820245 无可否认,google map实在是很漂亮.可惜对于使用arcgis api for si ...

随机推荐

  1. Git 学习(五)远程仓库

    Git 学习(五)远程仓库 之前的章节所说的是本地Git仓库的操作,版本管理的优越性显然不会仅仅在本地.远程仓库也就是服务器或是网络端的仓库操作也是必须的. 本文具体说明 Git 的远程仓库操作,示例 ...

  2. python中的归并排序

    本来在博客上看到用python写的归并排序的程序,然后自己跟着他写了一下,结果发现是错的,不得不自己操作.而自己对python不是非常了解所以就变百度边写,最终在花了半个小时之后就写好了. def m ...

  3. [开发工具]_[VS2010]_[vs2010的一个bug-使用stringstream时出现]

    1. 注冊Microsfot之后想提交bug, 发现有这个提示, 所以提交不了bug, 有能提交的提交下吧. You are not authorized to submit the feedback ...

  4. 深入理解Java中的组合和继承

    Java是一个面向对象的语言.每一个学习过Java的人都知道,封装.继承.多态是面向对象的三个特征.每个人在刚刚学习继承的时候都会或多或少的有这样一个印象:继承可以帮助我实现类的复用.所以,很多开发人 ...

  5. OBjective-C:文件管理类NSFileManager

    文件管理类NSFileManager类:对文件进行创建.复制.重命名.删除等,一般不对文件内容进行操作. NSData类和NSMutableData类:相当于数据缓冲区  NSFileManager是 ...

  6. 解决:HTTP 错误 404.2 - Not Found. 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面

    错误重现: 在发布网站的过程中,虽然不是第一次发布了,但是还是遇到了很多的问题.为了以后可以轻松解决此类问题还是积累下来比较好. 问题:HTTP 错误 404.2 - Not Found. 由于 We ...

  7. WF4.0(3)----变量与参数

    已经写了两篇关于WF4.0的博客,算是基础博客,如果是WF比较熟悉就直接跳过吧,如果你对工作流不是很熟悉,或者想了解一下基础的东西,本文还是比较适合你的.工作流中变量,参数,表达式属于数据模型中概念, ...

  8. 【Dagger2】 案例大全

    只有Inject是不可以的,必须有Component public class Test { @Inject Person person; private void test() { System.o ...

  9. Java基础(六):继承

    1.继承的概念: 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类.继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具 ...

  10. MySQL bin-log与主从服务器

    试验环境                                                                                       Ubuntu    ...