2

分享一下如何制作专业的手绘电子地图 - 轻轻的烟雾

 1 year ago
source link: https://www.cnblogs.com/whatmiss/p/16438563.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

分享一下如何制作专业的手绘电子地图

分享一下如何制作专业的手绘电子地图。

一、智慧导览系统介绍

手绘电子地图,就是把手绘地图覆盖到地图上,游客或者普通用户,可以在手机上通过地图的链接(或者现在流行的小程序)打开使用。是一种使用非常方便,集“视、听、路径规划、实时导航”等诸多功能于一体的智慧导览系统。也是现在很多景区为游客提供的增加便捷性和游玩体验的一项功能。

最重要的两点,我认为是:

1.手绘图本身

手绘图的美观度、清晰度、完整度、准确度,决定了图的档次格调的高低,也是手绘设计师的技术水平、设计能力、规划能力、沟通能力等综合性体现。

2.实时导航功能

如果说手绘图本身是面子,让人对地图有第一印象和直观感受,那么实时导航功能则是地图的灵魂和里子。没有实时定位和动态路径规划导航功能的地图,只是一个可观而不可用的花瓶,没有使用价值。没有准确的而高效的实时导航算法,就不能把地图价值在游客手里发挥到最大。

因为多年的从业经验,我从一个纯技术的角度来分享一下如何实现这样的“智慧导览系统”。

二、智慧导览系统功能

先看一个参考示例图(根据实际情况,只添加了必要的功能):

​ 

435509-20220702210537173-2118421142.png

参考示例图

1.基础功能

地图功能的设计,包括需要哪些功能,需要怎么展示,地图点位的图标等细节,不一而足。每个需求方可能要的也不一样。但总体来说,可能包含如下:

景点介绍:这是智慧导览系统最基础的功能之一。在系统后台可以在地图上添加景点标注,并完善相应的介绍信息,包括图片、文字、图文、语音、视频等内容。

服务设施:在地图上添加区域内的服务设施,如厕所、游客中心、停车场等内容。

商家信息:在地图上添加区域内的商家,如酒店、餐饮、特产等商家。用户可查看商家介绍、商家产品,并可支付下单购买。

景区公告:在后台添加景区最新公告,如闭园通知、开园通知、最新活动等信息。

线路推荐:在后台设置推荐的线路及景点,游客在地图上可点击查看,并在地图上直观的规划出推荐的路径,模拟导览游览。非常直观明了。

咨询电话:可在后台设置景区的咨询、客服的联系方式,如电话、微信、微博等。

景区720:可拍摄制作景区的720全景,并在地图上标注展示,更直观的向游客展示景点的实景。

2.增强功能

智慧导览系统还应该具备如下增强功能,才能更好的增强客户的服务能力、满足用户的使用需求。这也是当前电子手绘地图系统的重点和难点。

实时定位:基于客户端的位置获取接口(如上文,可能大部分是微信环境里,或者浏览器环境),实时获取用户当前的位置信息。当然,位置的精度可能会受到诸多方面因素的影响,如天气、建筑物遮挡、设备本身的性能或GPS模块的精度、网络状况等。在理想的情况下,精度甚至可达到10到20米左右的偏差。这种精度,在民用已经算是极致了。为什么不给出更精确的精度,可能一方面是设备、技术等因素限制,另一方面,从安全角度来看,可能这也超出民用的范畴。当然,话说回来,从我们的实际使用场景来看,这样的精度其实已经远远的满足我们的需求了。这里说个题外话,为什么我们在手机上使用地图APP导航的时候,不管是驾车还是步行,看上去都能做到精准无误呢?(如驾车,在路口转向时,基本上达到米级的精度)关于这一点,我是这样思考的:地图APP是基于设备的定位,然后再结合当前使用者的导航方式、路径规划、设备朝向、速度等多方面综合的因素,用强大的后台算法为用户的当前位置做了智能的“纠偏”。那为什么我们智慧导览系统不做这样的纠偏呢。从实际出发,这一方面是我们的数据量远远不够丰富完善,另一方面是“性价比”不高。在园区内的导航,不需要这样的“纠偏”已经可以满足需求,而要做这样的“锦上添花”的功能,则需要付出指数级甚至更高的成本和代价。

动态路线规划:基于前端设备“实时定位”的能力,智慧导览系统实时计算用户当前位置和指定目的地的路径。指定的目的地,可以是地图上标注的任意一个点位,如景点、服务设施、商家等。这一点,和地图APP的导航功能非常类似。园区内很多情况下,没有地图APP平台采集路线,所以需要我们人工在智慧导览系统后台标注和实际情况一致的路线,或者通过智慧导览系统提供的路线采集工具,安排人员现场采集。其实,地图平台的路线采集也是这样做的。各大地图平台,都有国家发放的专业牌照,然后通过路线采集人员驾车或步行,采集、更新每个城市的道路(仔细想想,这是一个多大的工作量和成本,我们每个人都可以免费的使用这些服务,感谢他们的付出成本和辛苦)。

自动触发:基于“实时定位”和“动态路线规划”能力,用户达到系统设置的点位附近时,可以自动触发后台配置的各种功能,如自动播放景点的语音讲解、展示图文内容,或推送商家的优惠券等。为用户提供便利、人性化的智慧服务。

多语言:多语言是智慧导览系统满足国际化需求的一个增强功能。系统具备基本的汉语、英语选择,还具备很便捷的扩展其他语种的设计和功能。

3.地图个性化

智慧导览系统不应该是一个单纯的功能性的系统,还应该有更多丰富的、多元化的功能,为用户提供更多个性化、趣味化的服务。

个人中心:系统具备用户个人中心的功能。用户可以对地图上的景点进行点赞、评论等操作,然后可在个人中心查看。

营销、广告:后台可在地图上添加固定的营销、广告等信息,增强能力和满足运营需求。

优惠券:后台可设置地图上的商家发送优惠券,吸引、导流游客进店,带动消费。

寻宝游戏等活动:后台可在地图上添加寻宝指引点位,引导游客到指定地点扫码积星对话奖品。

标注图标动效:所有标注点的图标,可设置一些动效,增加地图的趣味性和个性化。

三、技术栈的选择

从这里开始后面的内容,有一定的行业背景或经验的人,能更好的理解。我尽量说得通俗易懂一些。如果你觉得一些专业名词不明白是什么意思,可以直接跳过。

现在绝大部分业务系统的开发,都是基于一个成熟的技术栈来实现。这样可以极大的节约基础设施的成本,而且效率得到极大的提高。甚至某些系统或行业的应用及系统,不基于一些成熟的技术栈,想要完全自主开发,几乎是不可实现的。

智慧导览系统,建议基于这样的一个技术栈:

1.服务器

使用成熟的云平台,国内成熟好用的几家,业内人都知道。

2.前端平台

如今最大的前端平台是微信小程序,还有就是浏览器直接通过链接打开。不过就智慧导览系统来说,大部分情况下,微信小程序也是基于Webview控件来调用,本质上和浏览器的直接打开没什么区别,就是HTML5+JavaScript+CSS3来实现。但是微信的生态内,会有一些微信开放的额外的一些接口和功能,比如说:可以使用微信提供的位置获取接口,来为游客获取更精准的定位。

3.地图平台

智慧导览系统只能基于地图的开放平台来实现。目前国内几家大而成熟的地图平台:高德地图、百度地图、腾讯地图。建议首选高德地图,次选百度地图。为什么呢?

地图有个“层级(Zoom)”的概念,就是用户打开地图,放大缩小,就是显示的不同的层级。现在地图平台开放的层级,高德地图最大为19级,百度地图为18级,而同级别的情况下,高德地图也更大一些。因此,建议选择高德地图,可以做更精细化的地图。腾讯地图多不做介绍。

另外,如果涉及国外的景区或地点,那谷歌地图是不二的选择。国内的地图在国外没有完整的内容,而且访问速度也很随缘。

四、开发介绍

具体开发内容,这里主要介绍涉及地图核心的部分。其他比如数据库设计、后台管理系统等不做过多介绍。

1.开发语言选择

后端开发:目前流行的开发语言如Java、PHP、Python等都是不错的选择,每个语言都有自己的特色。就个人而言,我比较喜欢Java和PHP,Java纯面向对象,适合大型项目,运行速度较快;PHP灵活简单,开发效率很高,现在利用有Swoole这样的扩展,也可以做到运行速度很快。

前端开发:前端开发老生常谈,JavaScript+HTML5+CSS3,千年不变的三板斧。但是可选择的框架或者库现在比较多,JavaScript有之前非常流行的JQuery库,也有现在很火的Vue等框架。总之,做为开发者,你最擅长的可能就是最适合的选择。当然,你也可以选择学习新的知识和技术代替曾经最擅长的。

2.地图基础知识

这一点,是核心,基础中的基础,原理也比较复杂。因为地球是一个球体,是立体的,并不是天圆地方的一个平面,所以,首先,需要引入一个叫“坐标系统”的概念。

当前常见的坐标系主要有三种:

地球坐标系:WGS84,常见于GPS设备,Gooogle地图(非中国区域)等国际标准的坐标体系 。

火星坐标系:GCJ-02,中国国内使用的被强制加密后的坐标系,如高德地图、腾讯地图、谷歌地图(中国区域)的坐标就属于此类坐标系。

百度坐标系:BD-09,百度地图所特有的坐标体系,它在火星坐标系的基础上又进行了一次加密处理。

但是我们使用地图的时候,却又只能看到平面的地图,因此,又有了另外一个概念:墨卡托投影。

墨卡托投影的主要功能,就是让三维立体的地图坐标能在二维平面上显示。有点类似于《三体》里的二向箔的功能,把三维系统二维化。

二维化之后的平面,会被分割为一片一片的小图,或者换句话说,由一片一片的小图拼成了二维的地图。而这个小图,叫“瓦片图”。这又是一个重要的概念。后文会继续细说。

而瓦片图的开始点(最左上角,或最左下角)在地球的什么地方呢,因为坐标系的不同,每个地图可能也不一样。所以,同一个经纬度,在不同的地图平台上,对应的瓦片图的序号可能都是不一样的。其中详细的原理和规则算法,这篇文章说得比较详细:

国内主要地图瓦片坐标系定义及计算原理

3.地图平台介绍

高德、百度、腾讯、谷歌地图开放平台介绍。

首先祭出开放平台文档,这是基于平台开发的基础:

高德地图:https://lbs.amap.com/api/javascript-api/summary

百度地图:https://lbsyun.baidu.com/index.php?title=jspopular3.0

腾讯地图:https://lbs.qq.com/webApi/javascriptGL/glGuide/glBasic

谷歌地图:https://developers.google.com/maps/documentation/javascript

每个地图的API,大同小异。从细节来说,腾讯地图的接口和高德地图差别最小。

值得一提的是,在地图上画线(主要是导航的线路规划标识),谷歌地图没有直接给出绘制虚线的接口,而国内的地图平台都有。这一点也体现了国内和国外的一种思维的差异。

另外还有一个细节,标注图标旋转(比如导航时,箭头图标跟随人的方向旋转)接口,高德地图的旋转的中心点不是图标中心,而是图标外层父元素的点位,因此转向时,给人的感觉是自身的位置也在画一个圆圈,而百度地图没有这个问题。当然这个问题也不是无法解决,我们可以通过自己编写转向的CSS,利用JavaScript来控制图标以中心点来转向。

435509-20220702210743472-366018484.png

  图标围绕父元素边点转向

435509-20220702210831152-2079604622.png

  图标围绕中心点正常转向

每个地图平台在手机端的表现和体验也有些差异。我个人觉得高德地图最流畅顺滑,百度地图次之。

还有另外一点细节,就是关于瓦片图(后文细说),一样的图,在腾讯地图上会有非常细微的差别(腾讯地图允许级别Zoom为小数,在两个级别之间,还可以有多个过度值,而其他地图只能是整数,这是一个更人性化的设计,但却导致了瓦片图变得模糊了一点)。

4.瓦片图覆盖到地图上

瓦片图是尺寸为256px*256px的正方形图片。这样的图片,像瓦片盖房一样,覆盖为整个地图,所以称为“瓦片图”。

瓦片图的设计是一个非常精妙的设计,解决了地图图片太大的根本性问题,节约了服务器、客户端设备的内存,按视觉范围内加载图片,也节约了网络流量。

这是一种前端的“懒加载”思想的体现,也是和前端的“雪碧图”刚好相反的设计(关于“懒加载”和“雪碧图”,这里不做过多介绍)。

因此我们可以发现,不管什么解决方案,都有相应的使用场景,也有相反的局限性。不可脱离场景,一概而论。

瓦片图覆盖到地图,这是整个手绘电子地图最核心、最基础的设施和功能。因为此,我们自己绘制的精美地图,才能够覆盖到地图平台上,做成我们个性化需求的地图。具体的实现,并没有想象的那么复杂。当然,经验丰富的程序员,可以设计出更科学的算法和加载逻辑。这里抛砖引玉,做一个示例(高德地图):

 1 var fileHost = 'https://yourfilehost.com/';
 2 var tileLayer = new AMap.TileLayer.Flexible({
 3     createTile: function (x, y, zoom, success, fail) {
 4         var imagePath = fileHost + '/tilefile/' + zoom + '/x + '_' + y + '.png';
 5           
 6         var div = document.createElement('div'); 
 7         var img = document.createElement('img');
 8         img.onload = function () {
 9             div.appendChild(img);
10         }; 
11         img.crossOrigin = "anonymous";
12         img.onerror = function () {
13             fail()
14         };
15         img.src = imagePath;
16 
17         success(div);
18          
19     }
20 });
21 tileLayer.setMap(map);

这里AMap.TileLayer.Flexible方法是核心,这是高德地图提供的使用瓦片图的一个接口。他提供了一个div层(className为“amap-layer amap-flexible”)覆盖在底图之上,然后允许此方法返回仁义的元素,填充在256*256的瓦片图的方格里。因此,这里其实也可以更简单的直接返回一个img元素而不用div:

 1 var fileHost = 'https://yourfilehost.com/';
 2 var tileLayer = new AMap.TileLayer.Flexible({
 3     createTile: function (x, y, zoom, success, fail) {
 4         var imagePath = fileHost + '/tilefile/' + zoom + '/x + '_' + y + '.png'; 
 5         var img = document.createElement('img');
 6         img.onload = function () {
 7             success(img);
 8         }; 
 9         img.crossOrigin = "anonymous";
10         img.onerror = function () {
11             fail()
12         };
13         img.src = imagePath; 
14     }
15 });
16 tileLayer.setMap(map);

以上为高德地图的示例,其他地图原理相差不大,因此不再赘述。当然,这里只给了最基础的加载瓦片图的逻辑。事实上,根据实际情况,这里面还会做很多必要的其他业务逻辑的判断,比如,系统应当存储当前地图的瓦片图范围,超出范围的,就不要加载图片,或者加载一张透明的小图等。

这里列一下地图平台瓦片图的接口名,便于有需要的搜索使用:

AMap.TileLayer.Flexible // 高德地图

BMap.TileLayer // 百度地图

TMap.ImageTileLayer // 腾讯地图

google.maps.ImageMapType // 谷歌地图

  //需要注意的是,一些地图的接口允许传入参数:瓦片图的尺寸。不过建议默认为256较好,毕竟这是通用的默认尺寸。

5.瓦片图的制作

既然瓦片图是基础,那么我们如何从一张完整的手绘图制作成为256*256的多张瓦片图呢?可能设计师都能想到,直接用Photoshop切图即可,很简单。是的,常理来说是这样,但这有2个问题:

(1)我们设计的图,往往不是刚好为256px的倍数,那么第一张切图,从什么地方开始?(即便是刚好为256的倍数,也不能从0像素开始切,后文细说)

(2)我们切图出来之后,结合前文的地图基础知识,通过上面示例代码可见,最关键的是每个图的文件名,要和地图的级别Zoom、X轴的数值x、Y轴的数值y相对应。否则切出来的图,没有任何意义。

这两个问题,是制作有用的瓦片图的根本问题。

其实,在我们绘制手绘图片文件之前,就已经清晰的知道,我们绘制的内容到底是处于地图的什么区域。然后应当记录这个区域的起始点的经纬度。

前面说了瓦片图可能从地图的最左下角或左上角开始。具体情况是这样的:高德、谷歌、腾讯地图是从左下角,高德地图是从左上角开始。

然后通过经纬度、抹卡托、可见区域像素三者的转换算法,计算出当前手绘图分别在X轴和Y轴的第二张瓦片图的偏移像素,然后从此像素位置开始切图,并把计算得到的层级(Zoom)、X坐标(x)、Y坐标(y)的值作为对应的文件名保存切图。因此,说到这里,我们便都知道,这切图工作没办法由设计师来人工执行,只能由设计的专门算法的系统执行。

这里因为一些商业保密和其他的原因,我不能对这个切图算法做更仔细的讲解,非常抱歉。

瓦片图切好之后,放到专门的文件服务器,然后前端代码便可调用,实现瓦片图覆盖于地图底图上展示。个性又漂亮的手绘地图便基本成型了(如上图“参考示例图”)。

6.动态规划路径的实现

漂亮个性的手绘电子地图完成之后,这还只是一个纯纯的地图展示,谈不上功能性的使用,更别说“智慧”。因此,我们还需要增加各项智慧能力的功能。这其中,最基础的又应当是“实时定位”及“动态路径规划”了。

其实这两项功能,就是地图APP的基础的导航功能。但是因为大部分我们的园区内根本没有地图的路线,或者不全面,因此需要我们自己来实现这个功能。

具体如何实现,原理很简单。前端通过定位接口获取到用户当前的位置(需要注意的是,为了支持更全面的使用场景,可以考虑兼容微信及HTML5原生接口),然后系统计算当前位置与指定的点位之间的路线。

因此,这就需要我们根据实际情况,事先在系统里标注园区内的点位和路线,路线越详细越好。而通过这些点位和路线,要计算得到最短路径,关键则在于最短路径的“寻路算法”。算法可以自己设计,而目前很多伟大的科学家公开的很多最短路径算法则更为推荐。因为自己设计的算法难免可能会出现一些不可预料的BUG,而这些公开的算法经过严密的证明和大量使用的验证,使得计算效率以及可靠性都有很好的保证。

这也是我的个人经验,曾经我们自己设计的一个算法,在大部分情况下都能计算出正确的最短路径结果,但在某些情况下,却得到意外的结果,或发生计算消耗较多时间,效率低下的情况。

我推荐“迪杰斯特拉”算法,或“佛洛依德”算法。

 1 //C语言版本的迪杰斯特拉算法
 2 int a[1000][1000];
 3 int d[1000];//d表示源节点到该节点的最小距离
 4 int p[1000];//p标记访问过的节点
 5 int i, j, k;
 6 int m;//m代表边数
 7 int n;//n代表点数
 8 int main()
 9 {
10     scanf("%d%d",&n,&m);
11     int    min1;
12     int    x,y,z;
13     for(i=1;i<=m;i++)
14     {
15         scanf("%d%d%d",&x,&y,&z);
16         a[x][y]=z;
17         a[y][x]=z;
18     }
19     for( i=1; i<=n; i++)
20         d[i]=max1;
21     d[1]=0;
22     for(i=1;i<=n;i++)
23     {
24         min1 = max1; 
25         for(j=1;j<=n;j++)
26             if(!p[j]&&d[j]<min1)
27             {
28                 min1=d[j];
29                 k=j;
30             } 
31         p[k] = 1;  
32         for(j=1;j<=n;j++)
33             if(a[k][j]!=0&&!p[j]&&d[j]>d[k]+a[k][j])
34                 d[j]=d[k]+a[k][j];
35     } 
36     for(i=1;i<n;i++)
37         printf("%d->",d[i]);
38     printf("%d\n",d[n]); 
39     return 0;
40 }

当然这些公开算法,都是最基本的核心和原理,要能让我们可在地图上做最短路径寻找,还需要我们自己根据实际业务和逻辑,做相应的变种。

根据对当前用户的实时定位,通过最短路径算法,便能实现动态路径的规划。这便使得我们的手绘电子地图具备了最基础、最重要的导航功能。

7.自动触发的实现

通过实时定位获取到用户当前位置,系统判断位置是否和后台设定的点位接近。当距离已小于设置值的时候,电子地图系统便自动展示当前点位的介绍信息、语音讲解,或者商家推送的优惠券等。因此,我们的电子地图系统便越来越智能了。

而在此基础之上,我们可以相当的所有功能,都可以加载到电子地图系统上。由此我们的系统便优化成为真正的“智慧导览系统”。其他的更多的功能的实现,我便不再赘述,只对下列三个比较特别的功能再做一些简述。

8.多语言的实现

多语言是一个老生常谈的需求,也是一个系统国际化所必备的功能。对于智慧导览系统而言,我觉得有两个值得注意的点:

(1)地图本身的文案,包括提示信息、按钮文字等。这可以在代码层面做多语言的配置。

(2)地图标注点位相关的内容,包括图文介绍、语音讲解等内容,这里需要在后台系统设计可添加多语言内容的管理。

9.实现国内国外可同时访问地图

这一点需求,是根据实际情况来提的。因为国内和国外的地图基本上不能互通,因此我们的智慧导览系统应当解决这一痛点。

10.地图路线的采集和标注

系统的“动态路径规划”功能需要园区的路线数据为基础,因此系统应当提供路线采集和标注的配套工具,方便工作人员从现场采集路线的经纬度等信息。

五、结尾

本文是我个人基于“智慧导览系统”开发经验的一个大致的概括。整体来讲,写得比较粗陋和简略。很难作为一个方案或者教程,只当是我个人做一个总结罢了。如有不当之处,欢迎指正。也欢迎有兴趣的一起讨论。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK