前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南

前言

最近刚忙完一个新项目,是基于WebGIS开发技术采用离线瓦片地图进行交互,由于之前做过类似的项目,也花了一些时间做研究,所以接手这个"So Easy"。主要技术栈是Vue+OpenLayers+地图,下面会分享一些我用WebGIS开发的大致路线和入门知识,以及项目实战经验,如有不妥之处,还请批评纠正,也欢迎大家一起探讨学习。

首先来认识一下WebGIS是什么东东,如下图所示:

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第1张图片

百度百科: WebGIS(网络地理信息系统)是指工作在Web网上的GIS,是传统的GIS在网络上的延伸和发展,具有传统GIS的特点,可以实现空间数据的检索、查询、制图输出、编辑等GIS基本功能,同时也是 Internet 上地理信息发布、共享和交流协作的基础。

https://baike.baidu.com/item/webgis/761986?fr=aladdin

WebGIS 介绍

Web + GIS 就是,在Web网页上的GIS系统,我们可以在网页(浏览器)上进行GIS数据处理操作、可视化展示等。

WebGIS 三层架构主要为展示层、地图服务层、数据层,通过UML图形进行理解,如下图所示:

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第2张图片

3D WebGIS是近期未来的方向,因为大数据可视化,最佳配合展示方式是3D地图。

地图要素展示(建筑、路线信息),空间分析(最短路径、最快路径),数据分析可视化(交通实时情况),POI兴趣点(附近景点、商家、美食等)。

Web服务器一般指网站服务器,简单的可以理解为,电脑上的文件资源,可以通过Web服务器部署后,让通过因特网的人都能访问预览。

目前行业上比较流行的地图JS库,主要有:ArcGIS API for JavaScript、OpenLayers、Leaflet、Mapbox、maptalks.js

详细介绍请移步:「开源项目」8款最受欢迎的地图API和javascript库

技术要求

  • JavaScript、CSS / HTML 熟练掌握
  • Vue 基础知识
  • GIS 基本知识:地图投影、坐标系相关
  • Web 端常用 GIS 数据存储格式:wkt、geojson、esriJSON
  • OGC(OGC、WMS、WFS、TMS、WMTS)规范
  • 掌握 ArcGIS Server 或者 GeoServer 发布地图服务并展示
  • 懂得 Java、C# 等后端语言(不强制)
  • Geotools(Java GIS 工具包)

学习路线

二维

  • web 基础知识
  • Vue 基础知识
  • gis 基础知识
  • arcgis/ Qgis/ mapgis
  • arcgis server / Geoserve / igserver
  • openlayers / leaflet / mapboxgl / arcgis api for js

三维

  • web 基础知识
  • Vue 基础知识
  • gis 基础知识
  • 计算机图形学
  • 3dMax / Maya / SketchUp / Blender / Pro-E(三维建模)
  • skyline / arcgis(gis 平台)
  • cesium / threeJS / webGL

新手看到上面的学习路线,心里就会嘀咕着想打退堂鼓,别灰心,继续跟着我的节奏往下走,已准备好一个快速上手开发的操作步骤。只要有前端基础,信手拈来。

如何快速上手

  • 选择地图下载器(使用在线地图此条忽略)
  • 下载离线切片图源(使用在线地图此条忽略)
  • 开发准备工作
  • Vue 脚手架搭建框架
  • 引入开源JS库 OpenLayers(自行查看官网文档API及DEMO示例)
  • 离线瓦片数据源存放到public目录作为静态资源(使用在线地图此条忽略)
  • 万事俱备只欠动手(文末附 OpenLayers 快速上手教程链接)

选择地图下载器

小编推荐两个免费地图下载器工具,如需下载工具及源码请关注公众号:[懒人码农],回复关键词“地图”即可下载使用。

  • 全能电子地图下载器

  • 个人版地图下载器

免安装打开即用

支持地图种类繁多:几乎包含所有主流在线地图,包括不仅限于谷歌、百度、高德、四维、微软、诺基亚、天地图、腾讯、ArcGIS、雅虎等地图,每种地图各有千秋。

下载离线瓦片地图数据源(可以根据自己需求下载地图级别数据源,等级越大数据量越大,下载时间越久)

全能电子地图下载器的操作方法:

  • 菜单栏选择“地图” —— 目前提供多种地图:百度地图、MapABC地图、谷歌普通地图、谷歌卫星图、谷歌混合图、谷歌地形图、腾讯普通地图,腾讯卫星图,腾讯混合图、雅虎中国地图。

  • 左侧栏勾选“地图等级” —— 谷歌地图等级为0-19级,其他地图是3-18级,地形图0-14级,建议下载区域遵循以下原则即可:世界1-4级,中国4-7级,城市8-17级。

  • 选择“下载区域” —— 点击地图左上角选择工具,选择感兴趣的区域, 支持按矩形、不规则多边形、圆形区域,还可以按省/市区域下载。

  • 左侧栏选择“当前视野”或“显示范围”,地图上会框选被选区域。

  • 左侧栏点击“开始”按钮即可下载地图,也可以选择省份下载。

准备工作

  • windows 10 操作系统
  • 下载安装 nodejs v14+ https://nodejs.org/zh-cn/
  • 代码编辑器工具 VS Code

搭建部署开发

Vue 脚手架搭建框架

1) 打开命令行窗口,输入 node -v 查看,出现版本号说明已安装成功,如下图:

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第3张图片

2) 使用以下命令安装Vue

npm install -g @vue/cli
// 安装指定版本
npm install -g @vue/cli@4.5.13
// OR
yarn global add @vue/cli

3)安装完成,检查vue版本,如下图:

vue -V

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第4张图片

4) vue-cli4 创建项目及运行

vue create mapdemo
cd mapDemo
npm run serve

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第5张图片

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第6张图片

在浏览器地址栏输入:http://localhost:8080/

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第7张图片

引入开源的JavaScript类库包 OpenLayers

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第8张图片

  • npm 安装 OpenLayers v6.5.0
npm install ol
  • CDN 引入

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第9张图片

功能设计和代码实现

按照上面的步骤已完成脚手架构建,并把需要的 Openlayers 依赖库引入和安装配置好,准备上刺刀开干。

先来个简单的在线地图实例(参照官方DEMO)

https://openlayers.org/en/latest/doc/quickstart.html

在 main.js 文件中挂载,代码如下:

// 将全局的ol对象挂载到Vue的原型对象上
// 在别的组件中使用 this.$ol
Vue.prototype.$ol = window.ol

在 components 文件夹新建组件demo1.vue文件,代码如下:

<template>
  <div class="page-map">
    <div id="map" class="map"></div>
  </div>
</template>

<script>
export default {
  name: "Demo1",
  data() {
    return {
      map: null
    }
  },
  mounted() {
    this.initMap()
  },
  methods: {
    // 初始化地图
    initMap() {
      this.map = new this.$ol.Map({
        target: 'map',
        layers: [
          new this.$ol.layer.Tile({
            source: new this.$ol.source.OSM()
          })
          // new this.$ol.layer.Tile({
          //  source: new this.$ol.source.XYZ({
          //    // 在线加载 Mapbox 卫星影像底图
          //    url: 'https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.jpg?access_token=pk.eyJ1Ijoid2FuZ2hhaGExIiwiYSI6ImNqeHUycXF5ZDEweDQzYnBiOTcwZGoxMHAifQ.eCGuiA6erHJ7ew-Fkc7dRA'
          //  })
          // }),
          // new this.$ol.layer.Tile({
          //   source: new this.$ol.source.XYZ({
          //     // 在线加载谷歌卫星底图(需)
          //     url: 'http://mt2.google.com/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}'
          //   })
          // })
        ],
        view: new this.$ol.View({
          center: this.$ol.proj.fromLonLat([121.3431, 25.067]),
          zoom: 4
        })
      });
    }
  }
};
</script>

<style scoped>
.map {
  width: 100%;
  height: 100vh;
}
</style>

效果图如下所示:

  • OpenStreetMap 地图

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第10张图片

  • 必应卫星影像底图

  • MapBox 卫星影像底图

  • 谷歌卫星影像底图

  • 高德卫星影像底图(与天地图、百度地图效果一样)

离线瓦片地图实例

  • MapHelper对象封装(模块化)

在utils文件夹中新建gisHelper.js文件,JS模块化代码实现如下:

// 创建initMap方法,初始化地图
initMap(targetName) {
    // let googleMapLayer = []
    // googleMapLayer = [
    //     this.layers.googleScreenAgeMapLayer
    // ]
    // 实例化Map对象,用于加载地图
    this.map = new ol.Map({
        // 地图容器div的id
        target: targetName,
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            })
        ],
        view: new ol.View({
            center: ol.proj.fromLonLat([121.3431, 25.067]),
            zoom: 8,
            minZoom: 4,
            maxZoom: 12,
            extent: this.extents.World
        }),
        // 地图控件
        controls: ol.control.defaults({
            attribution: false,
            zoom: false,
            rotate: false
        }).extend([])
    })
}
  • 在components文件夹创建demo2.vue组件并导入模块MapHelper,如下图所示:

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第11张图片

  • 在APP.vue组件中引入demo2.vue子组件,如下图所示:

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第12张图片

常用实例详解

  • 鼠标移入要素,箭头变成手型
// 鼠标响应手形变化
this.map.on('pointermove', (e) => {
    let pixel = this.map.getEventPixel(e.originalEvent)
    if (this.map.hasFeatureAtPixel(pixel)) {
        this.map.getTargetElement().style.cursor = 'pointer'
    } else {
        this.map.getTargetElement().style.cursor = ''
    }
})
  • 点击地图任意区域获取经纬度
// 点击地图获取经纬度,或点击要素
this.map.on('click', (e) => {
    console.log(e.pixel)
    let feature = this.map.forEachFeatureAtPixel(e.pixel, (ft) => {
        // 鼠标点击某一个要素后,获取这个要素,执行业务逻辑
        return ft
    })
    console.log(feature);
    if (feature) {
        // this.addUnitDetailPopUp(feature.get('extraData'))
    }
})
  • 设置初始化视角
// 设置视角(中心点)
setView(lngLat) {
    this.map.getView().animate({
        center: ol.proj.fromLonLat(lngLat)
    })
}
  • 设置地图缩放等级
// 设置地图缩放
setZoom(zoomLevel) {
    this.map.getView().animate({
        zoom: zoomLevel
    });
}
  • 点击获取经纬度或选中要素
// 点击地图获取经纬度
this.map.on('click', (e) => {
    let lngLat = ol.proj.toLonLat(e.coordinate), // 点击获取经纬度
    feature = this.map.forEachFeatureAtPixel(e.pixel, (ft) => {
        // forEachFeatureAtPixel()方法获取选中要素
        return ft;
    })
})
  • 指定经纬度显示要素标记点
// 地图上显示要素标记点
addFeatureMarker(arr) {
    let features = [];
    arr.forEach((e) => {
        let feature = new ol.Feature({
            geometry: new ol.geom.Point(ol.proj.fromLonLat([e.longitudeX, e.latitudeY])),
        })

        feature.setStyle(new ol.style.Style({
            image: new ol.style.Icon({
                src: e.imgPath,
                anchorXUnits: 'fraction',
                anchorYUnits: 'pixels',
                anchorOrigin: 'top-right',
                offsetOrigin: 'top-right',
                anchor: [0.5, 60]

            }),
            text: new ol.style.Text({
                text: e.name,
                textAlign: 'center',
                textBaseline: 'middle',
                font: "normal 13px sans-serif",
                padding: [3, 8, 3, 8],
                backgroundFill: new ol.style.Fill({
                    color: 'rgba(218, 77, 81, .2)',
                }),
                fill: new ol.style.Fill({
                    color: '#fff',
                })
            }),
        }))
        feature.set("extraData", e);
        features.push(feature);
    })
    this.featureSource.addFeatures(features);
}
  • 点击要素显示气泡弹框
// 显示气泡弹框PopUp
addDialogPopUp(item) {
    let lngLat = [item.longitudeX, item.latitudeY];
    this.removeOverlayPopUp();
    this.dialogOverlay = new ol.Overlay({
        element: this.createDialogDom(item),
        position: ol.proj.fromLonLat(lngLat),
        autoPan: true,
        positioning: 'bottom-left',
        offset: [50, -50]
    })
    this.map.addOverlay(this.dialogOverlay);
}

前端切图仔如何玩转webgis开发酷炫界面实战项目经验指南_第13张图片

  • 绘制圆形大小及样式
setCircle(location, size) {
    let circle = new ol.geom.Circle(ol.proj.transform(location, 'EPSG:4326', 'EPSG:3857'), size);
    this.circleFeature = new ol.Feature(circle);
    this.circleFeature.setStyle(
        new ol.style.Style({
            fill: new ol.style.Fill({
                color: 'rgba(255, 255, 255, .2)'
            }),
            stroke: new ol.style.Stroke({
                color: '#ffcc33',
                width: 1
            })
        })
    );
    this.circleSource.addFeature(this.circleFeature);
}
  • 绘制线条带箭头
// 设置线条带箭头
setLineString(location) {
    let line = new ol.geom.LineString([ol.proj.fromLonLat(this.posCenter), location]);
    this.lineFeature = new ol.Feature(line);
    let geometry = this.lineFeature.getGeometry(),
    sta = geometry.flatCoordinates.slice(-4),
    dx = sta[2] - sta[0],
    dy = sta[3] - sta[1],
    rotation = Math.atan2(dy, dx), // 获取线段的角度(弧度)
    arrowLonLat = [sta[2], sta[3]];
    this.lineFeature.setStyle([
        new ol.style.Style({
            fill: new ol.style.Fill({
                color: 'rgba(255, 255, 255, .2)'
            }),
            stroke: new ol.style.Stroke({
                color: '#ffcc33',
                lineDash: [1, 2, 3, 4, 5, 6],
                width: 3
            })
        }),
        new ol.style.Style({
            geometry: new ol.geom.Point(arrowLonLat),
            image: new ol.style.Icon({
                src: require('../assets/arrow.png'),
                anchor: [0.75, 0.5], // 图标锚点
                rotateWithView: true, // 与地图视图一起旋转
                rotation: -rotation // 因为角度以顺时针旋转为正值,所以前面添加负号
            })
        })

    ]);
    this.lineSource.addFeature(this.lineFeature);
}

写在最后

这次分享的内容写得比较仓促,涉及知识面不是很广,毕竟小编词库有限。看到这里相信小伙伴们,对WebGIS开发都有所了解,赶快动手操作一波吧。

如果这篇文章对你有一丝帮助,可以点赞、评论、转发分享,也是对我的一种支持,万分感谢。如需获取更多实战项目经验或源码资源,请关注公众号:「懒人码农」,回复关键词“地图”即可下载本资源,也可以加我微信【lazycode520】,一起学习一起进步。

学习资料

  • OpenLayers 快速上手教程
  • Openlayers 加载XYZ示例
  • epsg世界坐标系统
  • GEOJSON标准格式学习
  • EsriJSON
  • OGC规范
  • 计算机图形学
  • GeoServer
  • ArcGIS Server
  • 坐标系相关介绍
  • 地理坐标系、大地坐标系与地图投影与重投影

你可能感兴趣的:(前端开发,项目实战,javascript,javascript,vue.js,es6,css3,html5)