[算法设计] google map如何计算两地间最短行车路线的距离

[复制链接]
周梓敏 2013-11-10 23:51:39
最近在用google map做这样一件事情:0 G+ z) y8 f: P9 z- X* y
数据库中有一个USER表,记录了人名及其所在地和最远的出行距离,需要将表中这样的用户查询出来:
+ {# X* w6 ~- I0 o5 p8 Z# ~4 L, ]他距离广东佛山不超过他的最远出行距离。(注:这里的距离是两地间最短行车路线的距离,并非直线距离)
- ~/ G- H6 W6 h( g" N计算两地间最短行车路线的距离可以通过google map的GDirections类做到,方法如下:


复制代码

  • <body onunload="GUnload()">
  • </body>
复制代码这里很容易犯一个错误,很多人会这样写:

  • var directions;
  • function initialize() {
  • directions = new GDirections();
  • directions.load("from: 江西省南昌市 to: 江西省新建县");
  • alert(directions.getDistance().meters);}
复制代码然后会提示directions.getDistance().meters没有定义。这是因为GDirections的load方法是异步的,alert(directions.getDistance().meters)的时候距离还没有计算出来。正确的方法是给load方法增加一个监听器,等它完成之后,就可以取得你想要的值了。
/ s) N$ M+ x7 F% b m知道如何计算距离了,现在该如何实现本文开始的那个需求呢?
# r$ G! K# X3 I一边是从数据库中读取数据,一边是google map计算结果。我先说下一开始时我的一个傻帽想法:用php先读取出用户,得到一个数组,再遍历数组,取得他们的地址一一向google map发送请求,取得结果后再输出到模板。然后我就想如果用php向google map发送请求,google map只提供了javascript的api,并没有php的api,而javascript是在浏览器执行。想到这我自己都傻了,我居然试图在服务器端执行客户端浏览器的代码。
0 B+ @& `, J; W, h2 |$ s( f纠正思路:
% M$ Y6 m1 c1 d8 |+ n+ ^用php先读取出用户,得到一个数组,输出到模板。(剩下的事情交给浏览器)

  • <?php
  • $people = array(
  • 0 => array(
  • 'name' => '刘德华',
  • 'address' => '南昌',
  • 'maxdistance' => '900',
  • ),
  • 1 => array(
  • 'name' => '金城武',
  • 'address' => '日本',
  • 'maxdistance' => '1500',
  • ),
  • 2 => array(
  • 'name' => '刘若英',
  • 'address' => '浙江',
  • 'maxdistance' => '1300',
  • ),
  • 3 => array(
  • 'name' => '成龙',
  • 'address' => '宜春',
  • 'maxdistance' => '800',
  • ),
  • 4 => array(
  • 'name' => '李连杰',
  • 'address' => '北京',
  • 'maxdistance' => '700',
  • ),
  • 5 => array(
  • 'name' => '黄晓明',
  • 'address' => '上海',
  • 'maxdistance' => '1400',
  • ),
  • 6 => array(
  • 'name' => '陆毅',
  • 'address' => '北京',
  • 'maxdistance' => '1300',
  • ),
  • 7 => array(
  • 'name' => '古天乐',
  • 'address' => '南京',
  • 'maxdistance' => '1200',
  • ),
  • 8 => array(
  • 'name' => '孙红雷',
  • 'address' => '青岛',
  • 'maxdistance' => '1800',
  • ),
  • 9 => array(
  • 'name' => '聂远',
  • 'address' => '杭州',
  • 'maxdistance' => '1500',
  • )
  • );
  • $people = json_encode($people);
  • $jobaddress = '广东佛山';?>
复制代码浏览器中对得到的数组遍历,再一一向google map发送请求,得到距离。

复制代码这段代码似乎没什么问题,但是运行之后却让人大失所望,它将数组的最后一个元素输出了10遍。
2 F1 o6 c0 k2 d$ W1 k但是一想,这问题也出得理所当然,原因还在于”异步”,load方法向google map请求数据是不少时间的,但是循环却是瞬间完成的,所以在load的监听函数中输出currentPerson.name时循环早已结束,所以输出的总是数组的最后一个元素。7 ^- I% N' y1 l8 G
于是将代码改成这样:

  • function initialize() {
  • var people = eval('('+'<?php echo $people;?>'+')');
  • var directions = new GDirections();
  • for(i = 0, max = people.length; i < max; i++){
  • var currentPerson = people;
  • var onDirectionLoad = function(currentPerson){
  • return function(){
  • if(directions.getStatus().code == G_GEO_SUCCESS)
  • {
  • var distance = directions.getDistance().meters;
  • var listDiv = document.getElementById('userlist');
  • var maxdistance = currentPerson.maxdistance * 1000;
  • alert(distance+','+maxdistance);
  • if(distance * 1 <= maxdistance){
  • document.write(currentPerson.name+'
    ');
  • }
  • }
  • }
  • }
  • GEvent.addListener(directions, "load", onDirectionLoad(currentPerson));
  • directions.load("from: "+"<?php echo $jobaddress;?>"+" to: "+currentPerson.address);
  • }}
复制代码这里将load的监听函数封装成了一个闭包,关于闭包我是这两天才了解了下概念,在这里就不累赘了,怕讲不好,自己google吧。总之,闭包在这里的作用就是让currentPerson这个变量在每一次请求中不会因为循环影响。% Q& v) ]2 ?. g: ^7 u
原以为这样可以搞定了,没想到currentPerson随我意了,directions却没有,就是说在监听函数中得到的directions.getDistance().meters总是数组最后一个元素的距离。
8 ^- u. w) F. X0 s: g, + @因此将directions也封装到闭包中:

  • function initialize() {
  • var people = <?php echo $people;?>;
  • for(i = 0, max = people.length; i < max; i++){
  • var currentPerson = people;
  • function createDirection(currentPerson){
  • var directions = new GDirections();
  • var onDirectionLoad = function(currentPerson){
  • return function(){
  • if(directions.getStatus().code == G_GEO_SUCCESS)
  • {
  • var distance = directions.getDistance().meters;
  • var listDiv = document.getElementById('userlist');
  • var max_distance = currentPerson.maxdistance * 1000;
  • if(distance * 1 <= max_distance){
  • listDiv.innerHTML += currentPerson.name+','+currentPerson.address+','+distance+','+max_distance+',YES
    ';
  • }else{
  • listDiv.innerHTML += currentPerson.name+','+currentPerson.address+','+distance+','+max_distance+',NO
    ';
  • }
  • }
  • }
  • }
  • GEvent.addListener(directions, "load", onDirectionLoad(currentPerson));
  • directions.load("from: 广东佛山 to: "+currentPerson.address);
  • return directions;
  • }
  • createDirection(currentPerson);
  • }}
复制代码OK,搞定了!: p( m- y# # 6 G$ F
演示:演示1
/ W/ L3 u6 I4 w: O; F, J" o" E后来看见有人用串联的方法做,于是我也试了试:

  • var people = <?php echo $people;?>;
  • var i = 0;
  • var max = people.length;
  • function go() {
  • var directions = new GDirections();
  • var currentPerson = people;
  • var onDirectionLoad = function(currentPerson){
  • return function(){
  • if(directions.getStatus().code == G_GEO_SUCCESS)
  • {
  • var distance = directions.getDistance().meters;
  • var listDiv = document.getElementById('userlist');
  • var max_distance = currentPerson.maxdistance * 1000;
  • if(distance * 1 <= max_distance){
  • listDiv.innerHTML +=currentPerson.name+','+currentPerson.address+','+distance+','+max_distance+',YES
    ';
  • }else{
  • listDiv.innerHTML +=currentPerson.name+','+currentPerson.address+','+distance+','+max_distance+',NO
    ';
  • }
  • i++;
  • if(i < max){
  • go();
  • }
  • }
  • }
  • }
  • GEvent.addListener(directions, "load", onDirectionLoad(currentPerson));
  • directions.load("from: <?php echo $jobaddress;?> to: "+currentPerson.address);}
复制代码一样可以达到要求。
7 F) }% R2 z u+ m5 @不过呢,串联的形式是在完成了一个请求之后再发送下一个请求的,速度自然会慢一些。! u# P$ z( o o# o1 ~6 w/ V* [: t
演示:演示2
袁淳雅 2013-11-11 01:16:31
围观 围观 沙发在哪里!!!
回复

使用道具 举报

秋咸英 2013-11-11 01:39:51
LZ敢整点更有创意的不?兄弟们等着围观捏~
回复

使用道具 举报

有丝娜 2013-11-11 03:58:09
路过 帮顶 嘿嘿
回复

使用道具 举报

郑会 2013-11-11 04:46:25
围观 围观 沙发在哪里!!!
回复

使用道具 举报

况雪毓 2013-11-11 06:17:25
专业抢沙发的!哈哈
回复

使用道具 举报

殳贞 2013-11-11 10:29:43
为毛老子总也抢不到沙发?!!
回复

使用道具 举报

林竹 2013-11-11 12:19:37
支持,赞一个
回复

使用道具 举报

瞿海花 2013-11-11 14:13:45
支持,赞一个
回复

使用道具 举报

穆野雪 2014-3-18 10:30:26
支持支持再支持
回复

使用道具 举报

颛孙雪羽 2014-3-20 12:47:45
报告!别开枪,我就是路过来看看的。。。
回复

使用道具 举报

陶金枝 2024-9-23 17:14:50
看帖要回,回帖才健康,在踩踩,楼主辛苦了!
回复

使用道具 举报

卫梦云 2024-11-10 11:40:16 来自手机
支持你哈...................................
回复

使用道具 举报

刘吉帆 2025-2-2 22:51:07
广告位,,坐下看看
回复

使用道具 举报

亢昭懿 2025-2-23 11:20:34
是爷们的娘们的都帮顶!大力支持
回复

使用道具 举报

田美华 2025-3-21 07:20:41 来自手机
占坑编辑ing
回复

使用道具 举报

梁飞雪 2025-5-4 10:09:02
鼎力支持!!
回复

使用道具 举报

梁飞雪 2025-5-6 07:43:58
前排支持下
回复

使用道具 举报

祁紫杉 2025-5-20 18:24:48
发发呆,回回帖,工作结束~
回复

使用道具 举报

手机版

GMT+8, 2025-5-30 11:07

Copyright © 2012 技术派 | 技术支持:技术派设计

Powered by Discuz! X3.4