社交地图开发全流程:从基础交互到个性化定制
在社交地图项目中,我们致力于为 Twitter 搜索结果增添更多细节,打造一个功能丰富、交互性强且视觉效果出色的社交地图。以下将详细介绍从构建高级交互标记到添加多推文显示,再到自定义标记外观的整个开发过程。
构建高级交互标记
为了让社交地图更加生动,我们需要在 Twitter 搜索结果出现时自动打开信息面板。这一过程涉及创建 Google Marker 的子类,并为其添加新的 InfoWindow,以便将实时 HTML 数据集成到地图中。
操作步骤
:
1.
替换标记
:在
showTweet
函数中,将新标记替换为
TwitterMarker
标记。
function showTweet(obj,latLng){
if(!obj) obj = {text:'No tweet found in this area for this topic'};
console.log(obj);
var marker = new TwitterMarker({
map: map,
position: latLng,
tweet: obj,
title:obj.text
});
}
-
创建自定义标记
:定义
TwitterMarker构造函数。
function TwitterMarker(opt){
var strTweet = this.buildTwitterHTML(opt.tweet);
this.infoWindow = new google.maps.InfoWindow({
maxWidth:300,
content:strTweet
});
this.setValues(opt);
this.infoWindow.open(this.map,this);
google.maps.event.addListener(this, 'click', this.onMarkerClick);
}
-
继承标记功能
:让
TwitterMarker继承google.maps.Marker的所有特性。
TwitterMarker.prototype = new google.maps.Marker();
- 添加切换按钮 :在标记事件监听器中创建切换按钮,控制 InfoWindow 的打开和关闭。
TwitterMarker.prototype.onMarkerClick=function(evt){
this.isOpen=!this.isOpen;
if(this.isOpen)
this.infoWindow.close();
else
this.infoWindow.open(this.map,this);
}
-
生成 Twitter 消息 HTML
:实现
buildTwitterHTML方法,根据 Twitter 对象生成 HTML 字符串。
TwitterMarker.prototype.buildTwitterHTML = function(twt){
var str;
if(twt.from_user_name){
str =
"<span><img style='float: left' src='"+twt.profile_image_url+"' />"+
"<b>" +twt.from_user_name + "</b><br/><a href ='http://twitter.com/"
+ twt.from_user + "'>@"+twt.from_user+"</a><br/> "
+ twt.location + "</span>"
+ "<p>"+twt.text+"</p>";
}else{
str="The 50 Kilometer radius around this point did not message this value";
}
return str;
}
工作原理
:
通过 JavaScript 的继承机制,我们可以在不影响原始对象的情况下扩展其功能。
TwitterMarker
继承了
google.maps.Marker
的所有特性,并添加了自定义行为。
buildTwitterHTML
方法将 Twitter 对象的数据转换为 HTML,用于在 InfoWindow 中显示。切换按钮的逻辑基于
isOpen
变量,通过点击标记来切换其状态,从而控制 InfoWindow 的打开和关闭。
添加多推文到 InfoWindow
为了在 InfoWindow 中显示多条推文,我们需要添加分页系统。
操作步骤
:
1.
修改搜索链接
:将 Twitter 搜索设置为每次返回最多 100 个结果。
var searchLink = 'http://search.twitter.com/search.json?q='+ searchKeyWord+ '&geocode=' + geocode +"&result_type=recent&rpp=100";
-
更新事件监听器
:将完整的推文数组传递给
TwitterMarker构造函数。
google.maps.event.addListener(map, 'click', function(e) {
var searchKeyWord = 'html5';
var geocode=e.latLng.lat() + "," + e.latLng.lng()+",50km";
var searchLink = 'http://search.twitter.com/search.json?q='+ searchKeyWord+ '&geocode=' + geocode +"&result_type=recent&rpp=100";
$.getJSON(searchLink, function(data) {
showTweet(data.results,e.latLng);
});
});
function showTweet(a,latLng){
if(!a) a = [{text:'No tweet found in this area for this topic'}];
var marker = new TwitterMarker({
map: map,
position: latLng,
tweet: a,
title:a[0].text
});
}
-
更新构造函数
:在
TwitterMarker构造函数中添加推文数量和当前推文索引的信息,并为每个标记分配唯一的 ID。
function TwitterMarker(opt){
this.count = opt.tweet.length;
this.crnt = 0;
this.id = TwitterMarker.aMarkers.push(this);
this.aTweets = opt.tweet;
var strTweet = this.buildTwitterHTML(opt.tweet[0])
this.infoWindow = new google.maps.InfoWindow({
maxWidth:300,
content:strTweet
});
this.setValues(opt);
this.infoWindow.open(this.map,this);
google.maps.event.addListener(this, 'click', this.onMarkerClick);
}
-
存储标记
:创建一个静态数组
TwitterMarker.aMarkers来存储所有标记。
TwitterMarker.prototype = new google.maps.Marker();
TwitterMarker.aMarkers= [];
-
添加导航链接
:在
buildTwitterHTML方法中添加前后导航链接。
TwitterMarker.prototype.buildTwitterHTML = function(twt){
var str;
if(twt.from_user_name){
str =
"<span><img style='float: left' src='"+twt.profile_image_url+"' />"+
"<b>" +twt.from_user_name + "</b><br/><a href ='http://twitter.com/"
+ twt.from_user + "'>@"+twt.from_user+"</a><br/> "
+ twt.location + "</span>"
+ "<p>"+twt.text+"</p>";
if(this.count>1){
str+="<span style='absolute; bottom: 0; right: 0px; width:80px'>";
if(this.crnt!=0) str+="<a href='javascript:TwitterMarker.aMarkers["+(this.id-1)+"].prev();'><</a> ";
str+= (this.crnt+1) + " of " + this.count;
if(this.crnt<(this.count-1)) str+= "<a href='javascript:TwitterMarker.aMarkers["+(this.id-1)+"].next();'>></a> ";
str+= "</span>"
}
}else{
str="The 50 Kilometer radius around this point did not message this value";
}
return str;
}
-
实现前后切换方法
:添加
next和prev方法,用于切换推文。
TwitterMarker.prototype.next =function(){
this.infoWindow.close();
this.infoWindow.content = this.buildTwitterHTML(this.aTweets[++this.crnt]);
this.infoWindow.open(this.map,this);
return false;
}
TwitterMarker.prototype.prev =function(){
this.infoWindow.close();
this.infoWindow.content = this.buildTwitterHTML(this.aTweets[--this.crnt]);
this.infoWindow.open(this.map,this);
return false;
}
工作原理
:
首先,我们修改了 Twitter 搜索 API 的返回结果数量,以获取更多推文。然后,将完整的推文数组传递给
TwitterMarker
构造函数。通过创建静态数组
TwitterMarker.aMarkers
,我们可以在 InfoWindow 中引用标记并实现前后导航功能。在
buildTwitterHTML
方法中,根据推文数量和当前索引添加导航链接,点击链接时调用
next
和
prev
方法来切换推文。
以下是添加多推文到 InfoWindow 的流程图:
graph TD;
A[修改搜索链接] --> B[更新事件监听器];
B --> C[更新构造函数];
C --> D[存储标记];
D --> E[添加导航链接];
E --> F[实现前后切换方法];
通过以上步骤,我们可以在社交地图的 InfoWindow 中显示多条推文,并实现分页导航功能,为用户提供更好的交互体验。
社交地图开发全流程:从基础交互到个性化定制(续)
自定义标记的外观和感觉
接下来,我们将对标记本身进行改造,使其更具特色。我们会把标记更新为类似 Twitter 鸟的样式,并且添加一个图形层来为 Twitter 标记添加阴影,阴影的不透明度将根据推文数量(最多 100 条推文)从 0 到完全不透明变化。
操作步骤
:
1.
更新
showTweet
函数
:
function showTweet(a,latLng){
if(!a) a = [{text:'No tweet found in this area for this topic'}];
var marker = new TwitterMarker({
map: map,
position: latLng,
tweet: a,
title:a[0].text,
icon:"img/bird.png"
});
}
-
在
TweeterMarker构造函数中创建MarkerCounter对象实例 :
function TwitterMarker(opt){
this.count = opt.tweet.length;
this.mc = new MarkerCounter(opt);
this.crnt = 0;
// 其他代码...
}
-
创建
MarkerCounter构造函数 :
function MarkerCounter(opt) {
this.radius = 15;
this.opacity = (opt.tweet.length) /100;
this.opt = opt;
this.setMap(opt.map);
}
-
创建
MarkerCounter作为google.maps.OverlayView对象的子类 :
MarkerCounter.prototype = new google.maps.OverlayView();
-
创建
onAdd方法 :当元素添加到地图时,该方法会自动调用,用于完成绘制的准备工作。
MarkerCounter.prototype.onAdd = function() {
var div = document.createElement('div');
div.style.border = "none";
div.style.borderWidth = "0px";
div.style.position = "absolute";
this.canvas = document.createElement("CANVAS");
this.canvas.width = this.radius*2;
this.canvas.height = this.radius*2;
this.context = this.canvas.getContext("2d");
div.appendChild(this.canvas);
this.div_ = div;
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
}
-
重写
draw方法 :在新创建的 canvas 元素中进行绘制,并定位 div 元素。
MarkerCounter.prototype.draw = function() {
var radius = this.radius;
var context = this.context;
context.clearRect(0,0,radius*2,radius*2);
context.fillStyle = "rgba(73,154,219,"+this.opacity+")";
context.beginPath();
context.arc(radius,radius, radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
var projection = this.getProjection();
var point = projection.fromLatLngToDivPixel(this.opt.position);
this.div_.style.left = (point.x - radius) + 'px';
this.div_.style.top = (point.y - radius) + 'px';
};
工作原理
:
首先,我们通过在
showTweet
函数中传递
icon
参数,将标记的默认图形替换为 Twitter 鸟的图形。由于我们扩展了常规标记,所以可以使用其默认功能来交换图标。然后,我们创建了
MarkerCounter
类作为
google.maps.OverlayView
的子类,用于添加阴影层。在
onAdd
方法中,我们创建了一个 div 元素和一个 canvas 元素,并将 canvas 元素添加到 div 中,最后将 div 添加到地图的覆盖层。在
draw
方法中,我们根据推文数量设置阴影的不透明度,并使用 canvas 绘制圆形阴影。通过
getProjection
方法将经纬度转换为像素坐标,从而正确定位阴影层。
以下是自定义标记外观的操作步骤表格:
| 步骤 | 操作 |
| ---- | ---- |
| 1 | 更新
showTweet
函数,设置图标 |
| 2 | 在
TweeterMarker
构造函数中创建
MarkerCounter
实例 |
| 3 | 创建
MarkerCounter
构造函数 |
| 4 | 创建
MarkerCounter
作为
google.maps.OverlayView
的子类 |
| 5 | 创建
onAdd
方法,完成绘制准备 |
| 6 | 重写
draw
方法,进行绘制和定位 |
处理无结果情况
目前,我们假设世界上某个地方总是有推文,但实际情况并非如此。因此,我们需要重写行为,在没有结果时提供替代标记,并跳过所有自定义操作。
操作步骤
:
1.
更新
showTweet
函数
:
function showTweet(a,latLng){
var marker = new TwitterMarker({
map: map,
position: latLng,
tweet: a,
title:a.length? a[0].text : 'No tweet found in this area for this topic',
icon:"img/bird.png"
});
}
-
重写
TwitterMarker构造函数 :
function TwitterMarker(opt){
if(!opt.tweet || !opt.tweet.length){
opt.icon = "img/x.png";
}else{
this.count = opt.tweet.length;
this.mc = new MarkerCounter(opt);
this.crnt = 0;
this.id = TwitterMarker.aMarkers.push(this);
this.aTweets = opt.tweet;
var strTweet = this.buildTwitterHTML(opt.tweet[0])
this.infoWindow = new google.maps.InfoWindow({
maxWidth:300,
content:strTweet
});
this.infoWindow.open(this.map,this);
google.maps.event.addListener(this, 'click', this.onMarkerClick);
}
this.setValues(opt);
}
工作原理
:
在
showTweet
函数中,我们使用三元运算符根据推文数组的长度更新标记的标题。在
TwitterMarker
构造函数中,我们首先检查是否有推文,如果没有,则将图标更新为
img/x.png
;如果有推文,则继续执行正常的初始化操作。最后,无论是否有推文,都调用
setValues
方法来设置标记的属性。
以下是处理无结果情况的流程图:
graph TD;
A[更新 `showTweet` 函数] --> B[重写 `TwitterMarker` 构造函数];
B --> C{是否有推文};
C -- 是 --> D[正常初始化];
C -- 否 --> E[更新图标为 `img/x.png`];
D --> F[调用 `setValues` 方法];
E --> F;
通过以上步骤,我们完成了社交地图的开发,包括构建高级交互标记、添加多推文显示和自定义标记外观,并处理了无结果的情况。这个社交地图可以让用户更方便地查看特定区域的 Twitter 推文,并且提供了良好的交互体验。你还可以进一步扩展这个项目,例如更容易地更改搜索词,或者比较两个搜索结果等。
超级会员免费看
1474

被折叠的 条评论
为什么被折叠?



