新作品:可以自由编辑的Google地图,700行javascript+70行php
以前在龙骑士城堡提过一种想法,就是用GOOGLE MAPS来做桌面游戏玩家的主题地图。当时推荐的是EEMAP的服务,然则这个网站的注册一直需要邀请码,很不方便,而且界面难看,速度也很慢……
当时就想过自己来做一个GOOGLE MAPS API的应用,但一直没时间看API文档。这几天总算有空闲(辞职就是好哑),把想象中的东西基本上做出来了,我把它叫作Free Map Folio v1.0(取自DND设定集的名字),可以像维基百科那样自由编辑,前端是静态的HTML,数据库用xml,方便部署,而交互操作的程序完全用Javascirpt来写,只需要打开一个HTML页面,然后整个使用过程都不需要刷新页面,也不需要从外部获取数据(只用AJAX提交数据)。
演示:桌面游戏玩家主题地图(乱加东西要记得删掉)——
以前在龙骑士城堡提过一种想法,就是用GOOGLE MAPS来做桌面游戏玩家的主题地图。当时推荐的是EEMAP的服务,然则这个网站的注册一直需要邀请码,很不方便,而且界面难看,速度也很慢……
当时就想过自己来做一个GOOGLE MAPS API的应用,但一直没时间看API文档。这几天总算有空闲(辞职就是好哑),把想象中的东西基本上做出来了,我把它叫作Free Map Folio v1.0(取自DND设定集的名字),可以像维基百科那样自由编辑,前端是静态的HTML,数据库用xml,方便部署,而交互操作的程序完全用Javascirpt来写,只需要打开一个HTML页面,然后整个使用过程都不需要刷新页面,也不需要从外部获取数据(只用AJAX提交数据)。
演示:桌面游戏玩家主题地图(乱加东西要记得删掉)——http://www.ntrpg.org/yy/maps/
Javascirpt的主要代码有700行,都写在一个对象里(yymap),我本来想把每个单独的功能都封装起来,避免重复代码(DRY原则?),不过后来页面右侧栏加入了“地点列表”之后,程序就改复杂了……………以后有空要做一下重构……
用户只需要访问一个静态的HTML页面,唯一一次从外部获取数据是在地图加载的时候,用了API提供的XmlHttpRequest对象,非常方便,比如GXml.parse可以把responseText获得的文本转换成XML DOM。不过用GXmlHttp和GDownloadUrl的时候,IE7都会遇到一个缓存问题(IE6没试过):刷新页面后,不会重新下载XML文件,因此页面上的数据不会更新。解决方法是在xml文件的地址后面加随机参数(感谢tinyfool的帮助):
var ramnum = parseInt(100000*Math.random());
var request = GXmlHttp.create();
request.open("GET", "db.xml?x="+ramnum, true);
标记(Marker)的样式可以自定义,所以我做了一个选择图标的功能,先建立所有图标的基本属性(yymap.baseIcon),包括阴影图片和各种尺寸,然后在创建新标记时,根据用户选择的图标,把地址传给icon.image就行了。其实还可以做一个自定义图片的功能,允许用户在编辑器里上传自己的图片(比如照片)当作图标,只是必须把图片处理成固定大小的32位PNG……
点击标记弹出的信息窗口是最麻烦的东西,因为页面里同时只能存在一个信息窗口,而信息窗口里的内容也不能保存在标记的对象里,所以要修改某个标记对应的信息窗内容,就只能修改它的点击事件:
GEvent.addListener(marker, "click", function()
{
yymap.whenClickMarker(marker,info,point,icon.image);
});
我在点击事件里传了4个参数:点击的标记对象 , 信息窗的内容, 标记的经纬度, 标记使用的图标, 除了用来显示信息窗,也是为了把它们传给全局变量(因为编辑这个标记的时候会用到)。
为了让右侧栏列表与地图上的图标一一对应,我在列表的每个链接上设了跟标记对应的ID,每次做添加、编辑或删除的操作时,除了修改标记本身的点击事件,还要用ID找到列表上对应的链接,修改链接的点击事件…………总之,感觉这个侧栏列表很添乱……却又是必要的功能……
在我写这篇文章时,还有一个搜索地名的功能没做好。本来API提供了地理译码的功能,可以把符合格式的地名转换成JSON数据(用JS对象来传递数据的格式),但这么方便的东西我却享受不了——地理译码还没有支持中国的地名…………在地图上就能很明显的看到:周围日本、印度,都有详细的城市名字,放大后还有交通信息,而中国是一片空白…………
因此对于不熟悉地理的用户来说,要在这样的中国地图上找到某个城市可能太难了,搜索地名是必须的功能。由于没有地理译码,目前使用GOOGLE MAPS API的网站,比如EEMAP,都是自己建立地名和经纬度对应的数据库。我找到了一个很全的“乡镇级中国行政区划地标”,是GOOGLE EARTH用的KMZ文件,但其实就是压缩过的XML,用WINRAR打开就能看到一个KML文件,可以直接拿来当搜索数据库。我考虑过两种实现方法:把用户输入的中文地名用AJAX发给PHP,让PHP搜索这个XML文件里匹配的标签,然后返回相应的经纬度;或者直接用GXmlHttp下载XML,然后用JS的DOM方法来搜索相应的标签,第二种方法很合我的胃口,不需要借道PHP,遗憾的是…………这意味着搜索时要用AJAX获得19M的XML数据……更新:地名搜索已经完成了,模糊搜索范围包括省会、地级市、县城、村镇……足行匹配,搜索对象在KML文件里排名越靠后,搜索时间越长,不过最多应该不超过5秒……
我刚才测试了一下,搜索不到结果时4.36s,搜索最后一个地名“番阳”需要4.02s,搜索北京1.16s,搜索克拉玛依只需要华丽的328ms
php是由以前的同事Skylin帮忙写的,由于PHP只负责根据AJAX提交的数据,修改XML文件,所以内容很少……然则Skylin不肯用PHP5自带的XML类,而是自己写正则……最后代码只有几十行……果然是高手风范……
比如,这是remove.php:<?php
include "./globals.php";
$file_content = join('',file("../db.xml"));
if(preg_match("/<marker>\r\n<id>".intval($_POST['id'])."<\/id>.*<\/marker>\r\n\r\n/isU",$file_content,$array))
{
$file_content = str_replace($array[0],'',$file_content);
}
$fp = fopen("../db.xml","w+");
flock($fp,LOCK_EX);
fputs($fp,$file_content);
flock($fp,LOCK_UN);
fclose($fp);
?>
不过正则也容易出现问题,例如:在我最初做的XML数据库里面,标签的前面都有缩进,大概因为有的缩进是TAB,有的是空格,导致正则一直出错,只好把XML里的缩进全部删掉了……
目前已经全部完工,可能还有一些小BUG需要修改,比如:在简介里输入全角字符(比如·和——),会导致后面的字符都无法保存。P.S. 单引号、双引号和"&"容易引起JS错误,我把它们都屏蔽了-_____-b
作者: Dexter.Yy 发表于 3/13/2007 04:10:00 下午
10 条评论:
沙发/沙发。。。。
你好 YY君是意淫的意思么不好意思我猜测-__-!!
看你BLOG很长时间首次沙发,给你去过信不过没回。。
为什么辞职呢???薪金太少或是上办D&D被抓了??疑问中
我去过一个叫龙骑士堡的网站很好不知道你去过没
沙发完毕
……老爷,这篇文章首行里就有“龙骑士城堡”这个词……
辞职嘛,通常不是因为对过去不满,而是为了新的希望。
流汗!流汗!果真
被google'大字吸引没有注意也
编辑了一下~~~盘龙城@_@
恩,又编辑了毁灭之神的右眼~~~好玩,有时间继续编辑~~
口下!不要加太多无关内容,这不是画板或棋盘……
继续赞美YY大婶~~
ps:为什么最近到处都看到辞职的消息呢……
老哥,你什么时候去找工作啊???
你的blogger超级漂亮!如果现在没有用google blogger的朋友看到你的blogger,我相信他们都会惊讶:blogger竟然可以做得这么漂亮!然后就转投blogger门下。
yy君你好
我如果想学一门语言做为业余爱好
在爱好的学习同时,最后能达到做一个简单的人员管理加收费的数据库的目的,不怕耗时间长,就想通过这个目的督促学习。不学vf那种,至少学完后,还能写点其他奇怪的用的着的东东。你推荐学什么,给个书目如何。
发表评论