当前位置:首页 » 网页前端 » web室内地图开源
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

web室内地图开源

发布时间: 2022-12-09 16:49:16

❶ supermap iclient3d for webgl是开源的吗

是基于Cesium进行的扩展开发,目前超图没有开源,Cesium是开源的

❷ 什么是开源的webgis平台

简单的说就是基于网络的WebGIS分布式系统
使用者可以在单一的环境和单一的工作系统中使用分布于网络上的任何地理数据和地理信息,其目的是建立一个无边界、分布式、基于构件的地理数据互操作环境。
希望有用!

❸ 如何自己搭建openlayers地图服务器

OpenLayers只是WebGIS前端。搭建地图服务器需要使用
MapServer,
GeoServer
(开源WebGIS),
或者商业的
ArcGIS
Server,然后用
OpenLayers
在前端调用。

❹ 如何构建REST风格的WEB地图服务

让我们构建一个简单的EmployeeManager Web服务,我们将使用它来演示与MongoDB连接的HATEOAS。为了引导我们的应用程序,我们将使用Spring Initializr。我们将使用Spring HATEOAS和Spring Data MongoDB作为依赖项。你应该看到类似下图2所示的内容。图2 :引导应用程序配置完成后,下载zip并将其作为Maven项目导入你喜欢的IDE中。首先,让我们配置application.properties。

spring.data.mongodb.host=//Mongoserverhost

spring.data.mongodb.port=//Mongoserverport
spring.data.mongodb.username=//Loginuser
spring.data.mongodb.password=//Password
spring.data.mongodb.database=//Databasename

一般来说,如果所有内容都是全新安装的,并且你没有更改或修改任何Mongo属性,则只需提供一个数据库名称(已经通过GUI创建了一个数据库名称)。

spring.data.mongodb.database=EmployeeManager


另外,为了启动Mongo实例,作者创建了一个.bat,它指向安装文件夹和数据文件夹。它是这样的:"C:ProgramFilesMongoDBServer3.6inmongod"--dbpathD:-datadb
现在,我们来快速创建模型。这里有两个模型,员工模型和部门模型。检查它们,确保有没有参数、getter、setter、equals方法和hashCode生成的构造函数。(不用担心,所有代码都在GitHub上,你可以稍后查看它:https://github.com/theFaustus/EmployeeManager。)

publicclassEmployee{
privateStringemployeeId;
privateStringfirstName;
privateStringlastName;
privateintage;
}
publicclassDepartment{
privateStringdepartment;
privateStringname;
privateStringdescription;
privateList<Employee>employees;
}

现在我们已经完成了模型的制作,让我们来创建存储库,以便来测试持久性。存储库如下所示:


extendsMongoRepository<Employee,String>{
}

extendsMongoRepository<Department,String>{
}

如上所示,这里没有方法,因为大家都知道Spring Data中的中心接口被命名为Repository,在其之上是CrudRepository,它提供了处理模型的基本操作。在CrudRepository之上,我们有PagingAndSortingRepository,它为我们提供了一些扩展功能,来简化分页和排序访问。在我们的案例中,最重要的是MongoRepository,它用于严格处理我们的Mongo实例。因此,对于我们的案例来说,除了那些现成的方法外,我们不需要任何其他方法,但是仅出于学习目的,作者在这里要提到的是你可以添加其他查询方法的两种方法:

  • “惰性”(查询创建):此策略将尝试通过分析查询方法的名称并推断关键字(例如findByLastnameAndFirstname)来构建查询。
  • 编写查询:这里没有什么特别的。例如,只用@Query注释你的方法,然后自己编写查询。你也可以在MongoDB中编写查询。下面是基于JSON的查询方法的示例:
  • @Query("{'firstname':?0}")
    List<Employee>findByTheEmployeesFirstname(Stringfirstname);

  • 至此,我们已经可以测试我们持久性如何工作。我们只需要对模型进行一些调整即可。通过调整,作者的意思是我们需要注释一些东西。Spring Data MongoDB使用MappingMongoConverter将对象映射到文档,下面是我们将要使用的一些注释:
  • @Id :字段级别注释,指出你的哪个字段是身份标识。
  • @Document :类级别的注释,用于表示该类将被持久化到数据库中。
  • @DBRef :描述参考性的字段级别注释。
  • 注释完成后,我们可以使用CommandLineRunner获取数据库中的一些数据,CommandLineRunner是一个接口,用于在应用程序完全启动时(即在run()方法之前)运行代码段。
  • 我们已经创建了一些模型,并对它们进行了持久化。现在,我们需要一种与他们交互的方式。如上所说,所有代码都可以在GitHub上找到,因此作者在这里将仅向我们展示一个域服务(接口和实现)。
  • 接口的实现如下:
  • @{
    @Autowired
    ;
    @Override
    publicEmployeesaveEmployee(Employeee){
    returnemployeeRepository.save(e);
    }
    @Override
    (StringemployeeId){
    returnemployeeRepository.findOne(employeeId);
    }
    @Override
    publicvoiddeleteByEmployeeId(StringemployeeId){
    employeeRepository.delete(employeeId);
    }
    @Override
    publicvoipdateEmployee(Employeee){
    employeeRepository.save(e);
    }
    @Override
    publicbooleanemployeeExists(Employeee){
    returnemployeeRepository.exists(Example.of(e));
    }
    @Override
    publicList<Employee>findAll(){
    returnemployeeRepository.findAll();
    }
    @Override
    publicvoiddeleteAll(){
    employeeRepository.deleteAll();
    }
    }

  • 这里没有什么特别的要注意的,下面我们将继续讨论最后一个难题——控制器!
  • 因此,对于上面实现的所有方法,我们将自己定位在Richardson成熟度模型的第二级,因为我们使用了HTTP动词并实现了CRUD操作。现在,我们有了与数据进行交互的方法,并且可以使用Postman,我们可以如下图3所示检索资源,或者可以如下图4所示添加新资源。
  • 图3 :检索JSON中的部门列表
  • 图4:JSON中添加新员工

❺ 蜂鸟视图的室内三维地图引擎是如何实现跨平台的展现的

【蜂鸟视图】FENGMAP室内三维地图引擎底层使用C++技术,保证引擎的高效、稳定性。基于OpenGL及相应的WebGL、OpenGL ES 技术进行定制裁剪。应用层使用C#、Java、JavaScript语言对于不同系统平台进行封装,最大程度上保证外部接口的统一性,并使其可运行在电脑端、网页端、手机端、以及HTML5的公众号内。所采用的GLTF三维数据格式是国际最新标准格式。已满足VR及室内定位技术的对接展现。

❻ 有哪些开源的地图引擎

图形处理器开发环境 CUDA,C++视觉库 VXL,Google三维API O3D,三维图形渲染引擎 OGRE,SoftArt,beostudy-imagelib,计算机图形渲染库 Voreen,C语言的JPEG操作库 OpenJPEG,2D,Magick++,Equalizer,Python图像处理 Mahotas,GLFW
人脸识别 faceservice.cgi,libpng,绘图引擎 RRDtool,计算机视觉库 OpenCV,图像处理类库 CImg,2D图形库 AGG,Google 图形处理引擎 skia,JPEG 图像压缩库 LibJPEG,图像处理库 GD,C++图像处理库 ExactImage,太多了,开源图形库 FreeImage,C++向量图生成库 CreEPS,医学影像转换工具 XMedCon,3移动设备上的OpenGL OpenGL ES,Apache图像处理模块 mod_gfx,LibRaw,OpenGL图形接口 glew,OpenGL的C++封装 D;Enfent Engine
NVIDIA Scene Graph,C语言的EXIF库 libexif,Exiv2,Symbian绘图库 Cairo for Symbian OS,数据可视化库 Tulip,高质量图形图表库 MathGL,图像识别类库 Tesseract OCR,开源图形API OpenGL,开源图形库 CxImage,C++ PNG类库 PNGwriter,图形布局引擎 GLE,OpenCSG,图像处理和分析 Leptonica,QTeXEngine……;3D 图形开发库 Visualization Library,BMP图像处理库 bmplib,向量图形库 Picasso,摄像头图像捕捉 QuickCapture,2D 图形引擎 Quad-Ren,Symbian图像处理扩展库 NokiaCV,
libQGLViewer,OpenGL工具包 Freeglut,大图像处理工具 VIPS,OCR识别 OCRopus,C 图像操作库 Jhead,图形处理包 DevIL,OpenGL应用工具包 GLUT多了去了

❼ Egret Wing

Egret Wing是一款开源免费的HTML5游戏开发工具,Egret Wing支持目前市面主流的开发语言和技术,作为一款可视化编辑器,它可以帮你提高开发效率。这款工具还支持 Node.js 开发扩展插件,可以让你更好的定制化自有内容。

渲染模式:dom,cavase,webGL

不同的地图、不同的元素,好玩的道具(充值付费获得道具、融合形成新的道具)

创建项目->资源(json/png)resDepot->模块game

地图、步数、道具、消除

1.地图:元素按照地图排列

最大宽高格子数为8

形状可配置

包含自己的背景图

不同关卡背景图不同

无论地图形状如何改变,尺寸不变

2.步数:

不同关卡步数不同

步数为0时,游戏结束

3.道具

一共五种道具,道具功能不同,使用道具时候不消耗步数,来源于游戏奖励

4.消除:

三个及以上相同元素可消除

元素随机出现

初局开始时,不可有消除元素

没有可消除元素时,自动乱序

数据:地图数据、基础数据、关卡数据、道具数据

视图:元素、背景、关卡、道具

逻辑:主逻辑控制器、数据解析器、地图数据控制器、算法控制器、视图控制器

mapData:

一维数组:数据整理方便,下标

二维数组:空间表示方便,获取位置方便

index = row * 8 + column

json数据描述

地图配置信息如何描述

{"map": [0,1,8,9,6,7,14,15]} 一维数组记录不展示以及不可放置元素的方格

游戏元素数据设计

元素:type、ID(唯一)、location

eg:

mapData[3][6] = element.ID  

elements[mapData[3][6]] 元素对象池 访问想要的数据

ID:45

location:30

public static unmapnum: number = 0;//空白地图块数量

public static mapData: number[][]; //游戏地图,-1表示块地图不能使用,-2表示,此地图没有元素

public static stepNum: number = 0;//玩家剩余步数

public static levelStepNum: number = 0;//当前关卡步数

public static elementTypes: number[];//当前关卡出现的元素类型

public static unusedElements: number[];//游戏中未使用得元素,仅记录元素ID

public static levelBackgroundImageName = ""; //当前关卡背景图资源名

public static MaxRow: number = 8;//最大的行

public static MaxColumn: number = 8;//最大的列

public static currentElementNum: number = 0;//当前关卡游戏中地图可用元素数量

public static levelReq: LevelRequire;//当前关卡过关条件

public static elements: GameElement[];//游戏中出现得元素数据池,最多为64个,因为8*8

//舞台宽高,此封装为了方便调用

public static stageW: number = 0;

public static stageH: number = 0;

DisplayObjectContainer

public constructor() {

        super();

        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this);

    }

Sprite 类是基本显示列表构造块:一个可包含所有子项的显示列表节点

Sprite() 实例化一个容器

1.背景

var gbg:GameBackGround = new GameBackGround();

this._gameStage.addChild(gbg);

gbg.changeBackground();

2.地图

this.mapc = new MapControl();

this.mapc.createElementAllMap();

3.过关条件

let lec:egret.Sprite = new egret.Sprite();

this._gameStage.addChild(lec);

this.levm = new LevelReqViewManage(lec);

this.levm.createCurrentLevelReq();

4.元素

let cc:egret.Sprite = new egret.Sprite();

this._gameStage.addChild(cc);

this.evm = new ElementViewManage(cc);

this.evm.showAllElements();

1.寻找可消除元素

2.预检索可消除元素算法设计与实现

3.是否可以互相交换

交换后是否可以消除

❽ 如何在网页中嵌入自己制作的小区域矢量地图

如果想实现一个完整的web地图,具备基础的地图功能,那么需要一个前端地图js框架与后端地图引擎,我不建议使用ArcGIS等商业组件,商业组件一般都包装得比较严实,不利于学习。推荐使用各种开源组件自己搭建独立地图服务,容易学习到本质的技术。
1、前端框架有openlayers,google map js离线版本等,近两年流行leaflet,支持HTML 5前端矢量渲染,支持TileJson。
2、后端地图引擎主要实现地图渲染、空间检索、投影算法,也就是许多商业软件的GeoServer类产品。但是,如果想实现自有地图,可使用开源的Postgresql+postgis构建空间数据库,它可导入shapefile文件,支持常见的空间几何算法,也可使用mysql+空间扩展;在地图渲染方面,建议尝试自己编写瓦片渲染算法,可以体会一下几何图形与标注的压盖算法;投影方面,可参考proj4;另外,GeoTools也有很多用处。

❾ 做室内地图导航有什么开源的平台可以使用

网络地图、腾讯地图可以导航。 网络地图是网络提供的一项网络地图搜索服务,覆盖了国内近400个城市、数千个区县。在网络地图里,用户可以查询街道、商尝楼盘的地理位置,也可以找到离您最近的所有餐馆、学校、银行、公园等等。

❿ 从零打造一个Web地图引擎

说到地图,大家一定很熟悉,平时应该都使用过网络地图、高德地图、腾讯地图等,如果涉及到地图相关的开发需求,也有很多选择,比如前面的几个地图都会提供一套 js API ,此外也有一些开源地图框架可以使用,比如 OpenLayers 、 Leaflet 等。

那么大家有没有想过这些地图是怎么渲染出来的呢,为什么根据一个经纬度就能显示对应的地图呢,不知道没关系,本文会带各位从零实现一个简单的地图引擎,来帮助大家了解 GIS 基础知识及 Web 地图的实现原理。

首先我们去高德地图上选个经纬度,作为我们后期的地图中心点,打开 高德坐标拾取 工具,随便选择一个点:

笔者选择了杭州的雷峰塔,经纬度为: [120.148732,30.231006] 。

地图瓦片我们使用高德的在线瓦片,地址如下:

目前各大地图厂商的瓦片服务遵循的规则是有不同的:

谷歌和 TMS 的瓦片区别可以通过该地址可视化的查看: 地图瓦片 。

虽然规范不同,但原理基本是一致的,都是把地球投影成一个巨大的正方形世界平面图,然后按照四叉树进行分层切割,比如第一层,只有一张瓦片,显示整个世界的信息,所以基本只能看到洲和海的名称和边界线,第二层,切割成四张瓦片,显示信息稍微多了一点,以此类推,就像一个金字塔一样,底层分辨率最高,显示的细节最多,瓦片数也最多,顶层分辨率最低,显示的信息很少,瓦片数量相对也最少:

每一层的瓦片数量计算公式:

十八层就需要 68719476736 张瓦片,所以一套地图瓦片整体数量是非常庞大的。

瓦片切好以后,通过行列号和缩放层级来保存,所以可以看到瓦片地址中有三个变量: x 、 y 、 z

通过这三个变量就可以定位到一张瓦片,比如下面这个地址,行号为 109280 ,列号为 53979 ,缩放层级为 17 :

对应的瓦片为:

关于瓦片的更多信息可以阅读 瓦片地图原理 。

高德地图使用的是 GCJ-02坐标系 ,也称火星坐标系,由中国国家测绘局在02年发布,是在GPS坐标( WGS-84 坐标系)基础上经加密后而来,也就是增加了非线性的偏移,让你摸不准真实位置,为了国家安全,国内地图服务商都需要使用 GCJ-02坐标系 。

WGS-84 坐标系是国际通用的标准, EPSG 编号为 EPSG:4326 ,通常GPS设备获取到的原始经纬度和国外的地图厂商使用的都是 WGS-84 坐标系。

这两种坐标系都是地理坐标系,球面坐标,单位为 度 ,这种坐标方便在地球上定位,但是不方便展示和进行面积距离计算,我们印象中的地图都是平面的,所以就有了另外一种平面坐标系,平面坐标系是通过投影的方式从地理坐标系中转换过来,所以也称为投影坐标系,通常单位为 米 ,投影坐标系根据投影方式的不同存在多种,在 Web 开发的场景里通常使用的是 Web墨卡托投影 ,编号为 EPSG:3857 ,它基于 墨卡托投影 ,把 WGS-84 坐标系投影成正方形:

这是通过舍弃了南北 85.051129纬度 以上的地区实现的,因为它是正方形,所以一个大的正方形可以很方便的被分割为更小的正方形。

坐标系更详细的信息可参考 GIS之坐标系统 , EPSG:3857 的详细信息可参考 EPSG:3857 。

上一节里我们简单介绍了一下坐标系,按照 Web 地图的标准,我们的地图引擎也选择支持 EPSG:3857 投影,但是我们通过高德工具获取到的是火星坐标系的经纬度坐标,所以第一步要把经纬度坐标转换为 Web墨卡托 投影坐标,这里为了简单,先直接把火星坐标当做 WGS-84 坐标,后面再来看这个问题。

转换方法网上一搜就有:

3857 坐标有了,它的单位是 米 ,那么怎么转换成瓦片的行列号呢,这就涉及到 分辨率 的概念了,即地图上一像素代表实际多少米,分辨率如果能从地图厂商的文档里获取是最好的,如果找不到,也可以简单计算一下(如果使用计算出来的也不行,那就只能求助搜索引擎了),我们知道地球半径是 6378137 米, 3857 坐标系把地球当做正圆球体来处理,所以可以算出地球周长,投影是贴着地球赤道的:

所以投影成正方形的世界平面图后的边长代表的就是地球的周长,前面我们也知道了每一层级的瓦片数量的计算方式,而一张瓦片的大小一般是 256*256 像素,所以用地球周长除以展开后的世界平面图的边长就知道了地图上每像素代表实际多少米:

地球周长算出来是 40075016.68557849 ,可以看到 OpenLayers 就是这么计算的:

3857 坐标的单位是 米 ,那么把坐标除以分辨率就可以得到对应的像素坐标,再除以 256 ,就可以得到瓦片的行列号:

函数如下:

接下来我们把层级固定为 17 ,那么分辨率 resolution 就是 1.194328566955879 ,雷峰塔的经纬度转成 3857 的坐标为: [13374895.665697495, 3533278.205310311] ,使用上面的函数计算出来行列号为: [43744, 11556] ,我们把这几个数据代入瓦片的地址里进行访问:

一片空白,这是为啥呢,其实是因为原点不一样, 4326 和 3857 坐标系的原点在赤道和本初子午线相交点,非洲边上的海里,而瓦片的原点在左上角:

再来看下图会更容易理解:

3857 坐标系的原点相当于在世界平面图的中间,向右为 x 轴正方向,向上为 y 轴正方向,而瓦片地图的原点在左上角,所以我们需要根据图上【绿色虚线】的距离计算出【橙色实线】的距离,这也很简单,水平坐标就是水平绿色虚线的长度加上世界平面图的一半,垂直坐标就是世界平面图的一半减去垂直绿色虚线的长度,世界平面图的一半也就是地球周长的一半,修改 getTileRowAndCol 函数:

这次计算出来的瓦片行列号为 [109280, 53979] ,代入瓦片地址:

结果如下:

可以看到雷峰塔出来了。

我们现在能根据一个经纬度找到对应的瓦片,但是这还不够,我们的目标是要能在浏览器上显示出来,这就需要解决两个问题,一个是加载多少块瓦片,二是计算每一块瓦片的显示位置。

渲染瓦片我们使用 canvas 画布,模板如下:

地图画布容器 map 的大小我们很容易获取:

地图中心点我们设在画布中间,另外中心点的经纬度 center 和缩放层级 zoom 因为都是我们自己设定的,所以也是已知的,那么我们可以计算出中心坐标对应的瓦片:

缩放层级还是设为 17 ,中心点还是使用雷峰塔的经纬度,那么对应的瓦片行列号前面我们已经计算过了,为 [109280, 53979] 。

中心坐标对应的瓦片行列号知道了,那么该瓦片左上角在世界平面图中的像素位置我们也就知道了:

计算出来为 [27975680, 13818624] 。这个坐标怎么转换到屏幕上呢,请看下图:

中心经纬度的瓦片我们计算出来了,瓦片左上角的像素坐标也知道了,然后我们再计算出中心经纬度本身对应的像素坐标,那么和瓦片左上角的差值就可以计算出来,最后我们把画布的原点移动到画布中间(画布默认原点为左上角,x轴正方向向右,y轴正方向向下),也就是把中心经纬度作为坐标原点,那么中心瓦片的显示位置就是这个差值。

补充一下将经纬度转换成像素的方法:

计算中心经纬度对应的像素坐标:

计算差值:

最后通过 canvas 来把中心瓦片渲染出来:

这里先来看看 getTileUrl 方法的实现:

这里随机了四个子域: webrd01 、 webrd02 、 webrd03 、 webrd04 ,这是因为浏览器对于同一域名同时请求的资源是有数量限制的,而当地图层级变大后需要加载的瓦片数量会比较多,那么均匀分散到各个子域下去请求可以更快的渲染出所有瓦片,减少排队等待时间,基本所有地图厂商的瓦片服务地址都支持多个子域。

为了方便看到中心点的位置,我们再额外渲染两条中心辅助线,效果如下:

可以看到中心点确实是雷峰塔,当然这只是渲染了中心瓦片,我们要的是瓦片铺满整个画布,对于其他瓦片我们都可以根据中心瓦片计算出来,比如中心瓦片左边的一块,它的计算如下:

所以我们只要计算出中心瓦片四个方向各需要几块瓦片,然后用一个双重循环即可计算出画布需要的所有瓦片,计算需要的瓦片数量很简单,请看下图:

画布宽高的一半减去中心瓦片占据的空间即可得到该方向剩余的空间,然后除以瓦片的尺寸就知道需要几块瓦片了:

我们把中心瓦片作为原点,坐标为 [0, 0] ,来个双重循环扫描一遍即可渲染出所有瓦片:

效果如下:

很完美。

拖动可以这么考虑,前面已经实现了渲染指定经纬度的瓦片,当我们按住进行拖动时,可以知道鼠标滑动的距离,然后把该距离,也就是像素转换成经纬度的数值,最后我们再更新当前中心点的经纬度,并清空画布,调用之前的方法重新渲染,不停重绘造成是在移动的视觉假象。

监听鼠标相关事件:

在 onMousemove 方法里计算拖动后的中心经纬度及重新渲染画布:

movementX 和 movementY 属性能获取本次和上一次鼠标事件中的移动值,兼容性不是很好,不过自己计算该值也很简单,详细请移步 MDN 。乘以当前分辨率把 像素 换算成 米 ,然后把当前中心点经纬度也转成 3857 的 米 坐标,偏移本次移动的距离,最后再转回 4326 的经纬度坐标作为更新后的中心点即可。

为什么 x 是减, y 是加呢,很简单,我们鼠标向右和向下移动时距离是正的,相应的地图会向右或向下移动, 4326 坐标系向右和向上为正方向,那么地图向右移动时,中心点显然是相对来说是向左移了,因为向右为正方向,所以中心点经度方向就是减少了,所以是减去移动的距离,而地图向下移动,中心点相对来说是向上移了,因为向上为正方向,所以中心点纬度方向就是增加了,所以加上移动的距离。

更新完中心经纬度,然后清空画布重新绘制:

效果如下:

可以看到已经凌乱了,这是为啥呢,其实是因为图片加载是一个异步的过程,我们鼠标移动过程中,会不断的计算出要加载的瓦片进行加载,但是可能上一批瓦片还没加载完成,鼠标已经移动到新的位置了,又计算出一批新的瓦片进行加载,此时上一批瓦片可能加载完成并渲染出来了,但是这些瓦片有些可能已经被移除画布,不需要显示,有些可能还在画布内,但是使用的还是之前的位置,渲染出来也是不对的,同时新的一批瓦片可能也加载完成并渲染出来,自然导致了最终显示的错乱。

知道原因就简单了,首先我们加个缓存对象,因为在拖动过程中,很多瓦片只是位置变了,不需要重新加载,同一个瓦片加载一次,后续只更新它的位置即可;另外再设置一个对象来记录当前画布上应该显示的瓦片,防止不应该出现的瓦片渲染出来:

因为需要记录瓦片的位置、加载状态等信息,我们创建一个瓦片类:

然后修改之前的双重循环渲染瓦片的逻辑:

效果如下:

可以看到,拖动已经正常了,当然,上述实现还是很粗糙的,需要优化的地方很多,比如:

1.一般会先排个序,优先加载中心瓦片

2.缓存的瓦片越来越多肯定也会影响性能,所以还需要一些清除策略

这些问题有兴趣的可以自行思考。

拖动是实时更新中心点经纬度,那么缩放自然更新缩放层级就行了:

效果如下:

功能是有了,不过效果很一般,因为我们平常使用的地图缩放都是有一个放大或缩小的过渡动画,而这个是直接空白然后重新渲染,不仔细看都不知道是放大还是缩小。

所以我们不妨加个过渡效果,当我们鼠标滚动后,先将画布放大或缩小,动画结束后再根据最终的缩放值来渲染需要的瓦片。

画布默认缩放值为 1 ,放大则在此基础上乘以 2 倍,缩小则除以 2 ,然后动画到目标值,动画期间设置画布的缩放值及清空画布,重新绘制画布上的已有瓦片,达到放大或缩小的视觉效果,动画结束后再调用 renderTiles 重新渲染最终缩放值需要的瓦片。

效果如下:

虽然效果还是一般,不过至少能看出来是在放大还是缩小。

前面还遗留了一个小问题,即我们把高德工具上选出的经纬度直接当做 4326 经纬度,前面也讲过,它们之间是存在偏移的,比如手机 GPS 获取到的经纬度一般都是 84 坐标,直接在高德地图显示,会发现和你实际位置不一样,所以就需要进行一个转换,有一些工具可以帮你做些事情,比如 Gcoord 、 coordtransform 等。

上述效果看着比较一般,其实只要在上面的基础上稍微加一点瓦片的淡出动画,效果就会好很多,目前一般都是使用 canvas 来渲染 2D 地图,如果自己实现动画不太方便,也有一些强大的 canvas 库可以选择,笔者最后使用 Konva.js 库重做了一版,加入了瓦片淡出动画,最终效果如下:

另外只要搞清楚各个地图的瓦片规则,就能稍加修改支持更多的地图瓦片:

具体实现限于篇幅不再展开,有兴趣的可以阅读本文源码。

本文详细的介绍了一个简单的 web 地图开发过程,上述实现原理仅是笔者的个人思路,不代表 openlayers 等框架的原理,因为笔者也是 GIS 的初学者,所以难免会有问题,或更好的实现,欢迎指出。

在线 demo : https://wanglin2.github.io/web_map_demo/

完整源码: https://github.com/wanglin2/web_map_demo