现在,许多应用都提供地理位置定位的功能,只要用户开放他们的位置信息就可以实现定位了,今天我们将创建一个基于Google 地图的微博用户地图,这里我们将通过Weibo API获取微博用户的地理信息,然后使用Google地理位置服务将用户的地理信息转换为相应的地理坐标,最后,根据地理坐标加载到Google地图中显示。
首先,我们定义程序的Index页面,它用于加载显示Google地图,具体实现如下:
<!-- Weibo user map --> <div id="map"></div> <div class="weibo"> <div class="inside"></div> </div> <div class="posts"></div> <div class="get"> <input type="hidden" value="优等生杜小明" /> <input type="hidden" value="杨幂" /> <input type="hidden" value="思想汇聚人生" /> <input type="hidden" value="KevinOriste" /> <input type="hidden" value="韩寒" /> <input type="hidden" value="复古老照片" /> <input type="hidden" value="独立检察官2011" /> <input type="hidden" value="顾扯淡" /> <input type="hidden" value="李开复"/> </div>
上面,第一个div(map)用来加载显示Google 地图,第二个div(weibo)用来显示微博用户的头像、描述、用户名和个人信息,第三个div(posts)用来加载显示相应用户最近发的微博信息,最后,一个div(get)用来存放微博用户名,我们的程序将根据这些用户名来获取相应的微博数据。
接下来,我们通过jQuery插件方式实现微博用户地图插件,我们定义了三个方法别是:weiboMap(),weiboMap.size()和weiboMap.init(),具体定义如下:
// Weibo user map plugin. (function($) { $.fn.weiboMap = function(options) { // Your code here. }; $.fn.weiboMap.size = function() { // Your code here. }; $.fn.weiboMap.init = function() { // Your code here. }; })(jQuery);
weiboMap()方法通过调用微博API获取微博数据,然后将返回数据加载显到Index页面中;weiboMap.size()获取当前窗口的大小,用来设置Google地图的初始大小;weiboMap.init()初始化Google地图,设置地图的zoom,地图中心位置(这里以北京为中心),地图大小和地图类型。
上面,我们只给出了三个方法的定义,但还没有给出具体的实现,接下来让我们实现上面的方法吧!
// Gets the size of window . $.fn.weiboMap.size = function() { var w = $(window).width(), h = $(window).height(); return { width: w, height: h }; }
上面,我们实现了weiboMap.size()方法,它获取当前窗口的大小,然后返回一个包含长和宽属性的对象。
// Initalizes the google map $.fn.weiboMap.init = function() { // Sets the size of map. var size = $.fn.weiboMap.size(); $('#map').css({ width: size.width, height: size.height }); // Creates a google map instance. map = new google.maps.Map(document.getElementById('map'), $.fn.weiboMap.defaults.data); // Creates a geo coder instance. geocoder = new google.maps.Geocoder(); }
图1 Google地图
我们通过方法weiboMap.init()初始化Google地图,首先,我们设置了map div的长和宽,然后创建了Google地图和地理编码对象。
在创建新的地图实例时,我们需要在网页中指定一个 div 元素作为地图的容器;这里我们通过getElementById ()方法获取map元素。
构造函数:Map(mapDiv:Node, opts?:MapOptions)
说明:第一个参数设置地图的HTLM容器,第二参数可选,用于设置Google地图的zoom,显示位置,地图大小和地图类型等(具体请参考这里)。
上面,我们实现了方法weiboMap.size()和weiboMap.init(),接下来我们继续实现方法weiboMap()。
由于weiboMap()负责调用微博API获取微博数据,然后加载显示到Google地图上面,所以这里就涉及到两个功能的实现:调用微博API和Google地图地理定位。
首先,我们定义方法getUsers()获取在Index.html页面中设置的微博用户名,然后根据这些用户名获取相应的用户信息和微博信息。
// Gets the list of weibo screen name // from the .get div. function getUsers() { var arr = new Array(); $('.get').find('input').each(function(i) { var $element = $(this); arr[i] = $element.val(); }); return arr; }
上面,我们通过find()方法获取get元素中的用户名,然后储存在数组中并且返回该数组,接下来,我们实现show()方法,它根据微博用户名调用微博API获取用户的基本信息和微博信息,由于用户的基本信息包含了地理信息,我们通过Google的地理编码服务将用户的地理信息转换为地理坐标,例如:根据北京转换为相应的经纬度北纬39.90,东经116.41,具体实现如下:
// Get weibo user show and binding data // with google map. function show() { // Gets the weibo user screen name. var users = getUsers(); for (var i = users.length - 1; i >= 0; i--) { // Invokes the weibo api to get data. $.getJSONP({ url: opts.url, timeout: 30000, data: { source: opts.appKey, access_token: opts.accessToken, screen_name: users[i] }, error: function(xhr, status, e) { console.log(e); }, complete: function() { }, success: function(json) { if (json.data.error) { // log the error. return; } var arr = new Array(), img = json.data.profile_image_url, screen_name = json.data.screen_name; // Initalizes the geo coder instance. geocoder.geocode({ address: json.data.location }, function(response, status) { if (status == google.maps.GeocoderStatus.OK) { // Sets latitude and longitude by location name. var x = response[0].geometry.location.lat(), y = response[0].geometry.location.lng(), blogUrl, marker = new google.maps.Marker({ icon: img, map: map, title: screen_name, animation: google.maps.Animation.DROP, position: new google.maps.LatLng(x, y) }); // Creates user information. blogUrl = json.data.url !== '' ? json.data.url : 'http://www.weibo.com/u/' + json.data.id; arr.push('<div class="item">'); arr.push('<p class="img"><a href="#" class="open" rel="' + screen_name + '"><img src="' + img + '" alt="" /></a></p>'); arr.push('<div class="entry">'); arr.push('<a href="#" class="open title" rel="' + screen_name + '">' + json.data.name + '</a>'); arr.push('<p class="description">' + json.data.description + '</p>'); arr.push('<p class="url"><a href="' + blogUrl + '" target="_blank">' + blogUrl + '</a></p>'); arr.push('<p class="count">粉丝: ' + json.data.followers_count + ', 关注: ' + json.data.friends_count + '</p>'); arr.push('</div>'); arr.push('</div>'); var html = arr.join(''); arr = []; $('.weibo').find('.inside').append(html); // Clicks the user image showing relative user's weibo. google.maps.event.addListener(marker, 'click', function() { open(this.title); }); } }); } }); }; }
上面,我们通过getJSONP()方法调用微博API获取微博用户数据,如名称,描述,地理位置和头像路径等,然后,我们使用Google的地理编码服务将用户地理位置信息转换为具体的地理坐标,最后,我们将微博用户的头像加载到地图的相应坐标上并且添加用户的名称和描述信息。
接着,我们打开Chrome的开发者工具,在Network中,查看到getJSONP()方法通过向微博的users/show接口发送请求来获取微博数据。
图2 Ajax请求
当请求成功微博将返回JSON格式的数据,数据的结构如下:
图3 微博JSON数据
前面,我们取得了微博数据,我们根据用户的location值获取相应的地理坐标值,这里我们使用Google的地理编码服务可以将用户地理位置信息(location)转换为具体的地理坐标,具体实现如下:
// Sets latitude and longitude by location name. var x = response[0].geometry.location.lat(), y = response[0].geometry.location.lng(), blogUrl, marker = new google.maps.Marker({ icon: img, map: map, title: screen_name, animation: google.maps.Animation.DROP, position: new google.maps.LatLng(x, y) });
我们根据用户的微博头像,名称和地理坐标创建marker实例,它用于在地图上显示对应的微博用户的位置,然后,我们把用户的名称,描述,粉丝和关注数量加载到weibo div中。
图4 微博用户地图
上面,我们实现了根据微博用户的位置信息进行地理定位,这样我们可以在地图上查看到每个微博用户的地理位置了,在地图的下方,我们给出了微博用户的描述信息。
现在,我们已经实现了微博用户地图的功能了,随着,我们查询用户增加,但我们显示用户信息的空间是有限,难道我们要用整个窗口来显示用户的信息吗?
其实,我们可以通过滚动方式来查看微博用户的信息,具体实现如下:
// Gets mouse Y coordinate. function getYCoordinate(e) { var y = e.pageY; return y; } // Checks move size. function checkYCoordinate(y) { var all = $('.weibo').height(), inside = $('.weibo').find('.inside').height(); // The max move size |all - inside|. if (y < (all - inside)) { y = all - inside; } else if (y > 0) { y = 0; } return y; } // Updates inside top css. function update(e) { var y = getYCoordinate(e), movey = y - my, // Changes Y coordinate. top = ey + movey, check = checkYCoordinate(top); console.log(top, check); $('.weibo').find('.inside').css({ top: check + 'px' }); } init(); function init() { $('.weibo').find('.inside').bind({ mousedown: function(e) { e.preventDefault(); mouseDown = true; var mouseY = getYCoordinate(e), // Gets element coordinate. element = $(this).position(); // Gets Y coordinate move. my = mouseY; ey = element.top; update(e); }, mousemove: function(e) { if (mouseDown) update(e); return false; }, mouseup: function() { if (mouseDown) mouseDown = false; return false; }, mouseleave: function() { if (mouseDown) mouseDown = false; return false; } }); }
用户通过垂直拖拉weibo div来实现上下查看微博用户信息,首先init()方法绑定了mousedown,mousemove,mouseup和mouseleave事件,当用户点击weibo div区域时,调用getYCoordinate()方法获取鼠标当前的Y坐标,当用户拖动鼠标时,调用update()方法更新inside div的top属性。
现在,我们可以通过垂直拖拉查看微博用户的信息,接下来,我们添加CSS效果调整一下界面布局,具体实现如下:
@import url("reset.css"); /* ------ layout -----------------------------------------------*/ html, body { margin:0; padding:0; } body { font-family:Arial, Helvetica, sans-serif; font-size:12px; color:#333; line-height:18px; } #map { float:left; } .weibo { position:fixed; left:0; bottom:0; background:#000; background:rgba(0, 0, 0, .7); width:100%; height:180px; color:#fff; overflow:hidden; } .weibo .inside { position:absolute; top:0; left:0; cursor:n-resize; } .weibo .item { float:left; width:280px; padding:20px; } .weibo .item .img { float:left; width:48px; } .weibo .img img { -moz-box-shadow:0 0 5px #000; -webkit-box-shadow:0 0 5px #000; box-shadow:0 0 5px #000; } .weibo .item .entry { float:right; width:215px; height:140px; color:#eee; font-size:11px; position:relative; } .weibo .item .count { position:absolute; left:0; bottom:-10px; font-size:10px; text-transform:uppercase; } .weibo .item .title { font-size:13px; font-weight:bold; color:#fff; } .weibo .item .url a { text-decoration:underline; } .weibo .item p { margin-bottom:5px; } .posts { display:none; position:absolute; left:50%; margin-left:-310px; width:580px; bottom:180px; background:#fff; color:#fff; background:#000; background:rgba(0, 0, 0, .7); padding:20px; } .posts .post { float:left; clear:both; width:100%; margin-bottom:20px; font-size:12px; font-weight:bold; } /* ------ anchors -----------------------------------------------*/ a { text-decoration:none; color:#fff; }
图5 微博用户地图
上面,实现了微博用户地图,我们可以在Google地图上查看到微博用户对应的地图位置,在下面给出了每个用户的描述信息。
我们实现了微博用户地图程序,首先将Google地图加载程序当中,然后,我们通过ajax请求调用微博API,获取微博用户的基本信息,当成功返回JSON数据时,从中获取用户的地址信息,然后通过Google的地理编码服务将地址信息转换为地理坐标,这样我们就可以定位每个微博用户的地理位置了,最后,通过marker把每个用户的定位到Google地图上显示出来。