Vue与常用GIS框架集成

3 篇文章 0 订阅
2 篇文章 1 订阅

1 Cesium

1.1 安装Cesium

# 安装Cesium
pnpm install cesium --save

# 安装指定版本的Cesium
pnpm install cesium@1.106

# 卸载
pnpm uninstall cesium

1.2 安装Cesium自动导入插件

pnpm i vite-plugin-cesium vite -D

# 安装Cesium类型以来 1.106版本之后不需要
pnpm i @types/cesium -D

1.2.1 在vite.config.js配置Cesium插件

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import cesium from 'vite-plugin-cesium'
 
 
export default defineConfig({
  plugins: [vue(), cesium()]
});

1.3 Cesium初始化示例

<script setup lang="ts">
import { ref, watch, nextTick, onMounted } from 'vue'
import {
    Viewer,
    Camera,
    Rectangle,
    // GeographicTilingScheme,
    // Ellipsoid,
    UrlTemplateImageryProvider,
    JulianDate
} from 'cesium'
// Cesium组件参数类型
import type { CesiumViewerProps } from '@/components/cesiumViewer/CesiumViewerProps'

// 定义组件参数
const props = defineProps<CesiumViewerProps>()
const cesiumViewerRef = ref()
// Cesium的Viewer对象
let viewer: Viewer | undefined

// 初始化Cesium场景
const initCesiumViewer = () => {
    // 设置Cesium的默认初始化视角
    Camera.DEFAULT_VIEW_RECTANGLE = Rectangle.fromDegrees(75, 0, 140.0, 60)
    /**
     * 初始化Cesium的Viewer
     */
    viewer = new Viewer(mapContainer.value, {
        // 选中相机框:不显示相机框
        selectionIndicator: false,
        // 信息框
        infoBox: false,
        // 地图导航罗盘
        navigation: false,
        // 右上角位置搜索按钮
        geocoder: false,
        // 底图图层选择器
        baseLayerPicker: false,
        // 回到主视图按钮
        homeButton: false,
        // 视图选择按钮:2D、2.5D、3D
        sceneModePicker: false,
        // 仅仅是3D视图
        scene3DOnly: true,
        // 帮助按钮
        navigationHelpButton: false,
        // 当前时间动画器件
        animation: false,
        // 全屏按钮
        fullscreenButton: false,
        // 底部时间轴控件
        timeline: false,
        // 设置基础底图
        baseLayer: new Cesium.ImageryLayer(
            new Cesium.UrlTemplateImageryProvider({
                // 天地图
                url: "http://t{s}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=1d109683f4d84198e37a38c442d68311", // 影像
                subdomains: "01234567",
                maximumLevel: 18,
            })
        ),
        // // 设置基础地图
        // imageryProvider: new UrlTemplateImageryProvider({
        //     // 使用Cesium自带的瓦片
        //     url: '../lib/Cesium/Assets/Textures/NaturalEarthII/{z}/{x}/{reverseY}.jpg',
        //     maximumLevel: 2,
        //     tilingScheme: new Cesium.GeographicTilingScheme({
        //         ellipsoid: Cesium.Ellipsoid.WGS84,
        //         // numberOfLevelZeroTilesX: 2,
        //         // numberOfLevelZeroTilesY: 1
        //     })
        // })
    })
    
    // 移除logo
    // viewer.cesiumWidget.creditContainer.style.display = "none"; // 隐藏logo
    viewer.cesiumWidget.creditContainer.remove(); // 删除logo
    // 关闭太阳光照
    viewer.scene.globe.enableLighting = false
    // 设置当前时间,防止晚上进入系统,看到的是黑的
    viewer.clock.currentTime = JulianDate.fromIso8601('2023-09-18T07:00:33.013999999995576218Z') // 北京时间下午15点
}

// 销毁Cesium场景
const destroyCesiumViewer = () => {
    viewer && viewer.destroy()
    viewer = undefined
}

watch([() => props.visible], () => {
    if (props.visible) {
        nextTick(() => {
            initCesiumViewer()
        })
    } else {
        destroyCesiumViewer()
    }
})

onMounted(() => {
    if (props.visible) {
        // 初始化三维场景
        initCesiumViewer()
    }
})
</script>

<template>
    <div ref="cesiumViewerRef" v-if="visible" class="cesium-viewer"></div>
</template>

<style scoped lang="scss">
.cesium-viewer {
    width: 100%;
    height: 100%;
}
</style>

2 Leaflet

2.1 安装Leaflet

# 安装Leaflet依赖
pnpm install --save leaflet

# 安装ts类型定义
pnpm install @types/leaflet --save-dev

2.2 基础示例

<template>
    <div v-if="visible" v-show="show" ref="mapContainer" class="leaflet-map"></div>
</template>

<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue'
import { MapComponentProps } from '../MapComponent'
import * as L from 'leaflet'
import type { Map } from 'leaflet'
import 'leaflet/dist/leaflet.css'

// Leaflet组件参数
const props = defineProps({
    visible: {
        type: Boolean,
        default: true,
    },
    show: {
        type: Boolean,
        default: true,
    },
})

const mapContainer = ref()
let map: Map | undefined

// 组件初始化完成,初始化地图
onMounted(() => {
    // 动态设置Leaflet地图容器的id
    ;(<HTMLElement>mapContainer.value).id = 'map' + Date.now() + Math.round(Math.random() * 1000)
    if (props.visible && props.show) {
        initMap()
    }
})

// 当组件可见时初始化地图
watch([() => props.visible, () => props.show], () => {
    // 组件是否可见
    if (props.visible && props.show && !map) {
        initMap()
    } else if (!props.visible) {
        destroyMap()
    }
})

/**
 * 初始地图
 */
const initMap = () => {
    nextTick(() => {
        _initMap()
    })
}

/**
 * 销毁地图
 */
const destroyMap = () => {
    console.log('销毁地图')
    map && map.remove && map.remove()
    map = undefined
}

/**
 * 初始地图
 */
const _initMap = () => {
    map = L.map(mapContainer.value.id, {
        minZoom: 0, // 设置地图的最小层级
        maxZoom: 18, // 设置地图的最大层级
        center: L.latLng(30.560407944979296, 115.97852713758685), // 设置地图的中心点
        zoom: 4, // 设置地图初始化的层级
        zoomControl: false, // 缩放控件是否可见
        attributionControl: false, // 属性控件是否可见
    })
    // 加载图层
    L.tileLayer('https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s,m&gl=CN&x={x}&y={y}&z={z}').addTo(map)
}
</script>

<style lang="scss" scoped>
.leaflet-map {
    width: 100%;
    height: 100%;
}
</style>

3 OpenLayers

3.1 安装依赖

pnpm install --save ol

3.2 基础示例

<template>
    <div v-if="visible" v-show="show" class="openlayers-map" ref="mapContainer"></div>
</template>

<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue'
import 'ol/ol.css'
import { Map, View } from 'ol'
import TileLayer from 'ol/layer/Tile'
import XYZ from 'ol/source/XYZ'
import { fromLonLat, transform } from 'ol/proj'
import { MapComponentProps } from '../MapComponent.ts'

const props = defineProps({
    // 地图是否可见
    visible: {
        type: Boolean,
        default: true,
    },
    // 地图是否显示
    show: {
        type: Boolean,
        default: true,
    },
})

const mapContainer = ref('')
let map: Map | undefined

// 当组件可见时初始化地图
onMounted(() => {
    if (props.visible && props.show) {
        initMap()
    }
})

// 当组件可见时初始化地图
watch([() => props.visible, () => props.show], () => {
    // 组件是否可见
    if (props.visible && props.show && !map) {
        initMap()
    } else if (!props.visible) {
        destroyMap()
    }
})

const initMap = () => {
    nextTick(() => {
        _initMap()
    })
}

/**
 * 销毁地图
 */
const destroyMap = () => {
    console.log('销毁地图')
    map && map.dispose && map.dispose()
    map = undefined
}

/**
 * 真正初始化地图
 */
const _initMap = () => {
    if (map) {
        return
    }
    // 初始化OpenLayer视图
    const view = new View({
        center: fromLonLat([115.97852713758685, 30.560407944979296], 'EPSG:3857'),
        // center: [104.912777, 34.730746], // 地图中心点
        zoom: 4,
        // projection: 'EPSG:4326',// 设置地图的投影
    })

    const layer = new TileLayer({
        source: new XYZ({
            // url: 'http://t{0-7}.tianditu.com/DataServer?T=vec_w&tk=b9031f80391e6b65bd1dd80dcde1b097&x={x}&y={y}&l={z}',
            url: 'https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}',
        }),
    })

    // 初始化地图
    map = new Map({
        target: mapContainer.value,
        layers: [layer],
        view: view,
    })
}


</script>

<style scoped lang="scss">
.openlayers-map {
    width: 100%;
    height: 100%;
}
</style>

4 MapBoxGL

4.1 安装依赖

# 安装依赖
pnpm install --save mapbox-gl

# 安装ts类型定义
pnpm install @types/mapbox-gl -D

4.2 初始化样例

<template>
    <div v-if="visible" v-show="show" ref="mapContainer" class="mapbox-map"></div>
</template>

<script setup lang="ts">
import { onMounted, ref, watch, nextTick } from 'vue'
import { MapComponentProps } from '../MapComponent'
import 'mapbox-gl/dist/mapbox-gl.css'
import { Map } from 'mapbox-gl'
import type { Control } from 'mapbox-gl'

const props = defineProps(MapComponentProps)

const mapContainer = ref() // 承载地图的容器
let map: Map | undefined // MapBox地图对象

// 组件挂载完成并且地图可见,初始化地图
onMounted(() => {
    if (props.visible && props.show) {
        initMap()
    }
})

// 当组件可见时初始化地图
watch([() => props.visible, () => props.show], () => {
    // 组件是否可见,不可见则销毁地图
    if (props.visible && props.show && !map) {
        initMap()
    } else if (!props.visible) {
        destroyMap()
    }
})

// 初始化地图
const initMap = () => {
    nextTick(() => {
        _initMap()
    })
}

/**
 * 销毁地图
 */
const destroyMap = () => {
    console.log('销毁地图')
    map && map.remove && map.remove()
    map = undefined
}

const _initMap = () => {
    // 初始化MapBox地图
    map = new Map({
        container: mapContainer.value,
        // style: "mapbox://styles/mapbox/streets-v12",
        // 必须要设置style、sources、layers,如果有字体,必须要设置glyphs属性
        style: {
            version: 8,
            sources: {},
            layers: [],
        },
        center: [115.97852713758685, 30.560407944979296],
        zoom: 3,
        attributionControl: false,
    })
    // @ts-ignore
    const controls = map?._controls
    controls.forEach((control: Control) => {
            // 移除MapBox logo控件
            if ('_updateLogo' in control) {
                map && map.removeControl(control)
            }
        },
    )

    // 移除MapBox的权限校验
    // @ts-ignore
    map._authenticate = () => {
    }

    map.on('load', () => {
        // 加载图层
        map && map.addLayer({
            id: 'GoogleImageLayer',
            type: 'raster',
            source: {
                'type': 'raster',
                'tiles': ['https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}'],
                'tileSize': 256,
            },
        })
    })
}
</script>

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

4.3 功能定制

4.3.1 修改源码方式

MapBox在内网使用时,accesstoken不能使用,导致局域网内地图服务不能使用,只需修改mapbox-gl.js文件中this._requestManager._customAccessToken,(e=>{if(e&&(false)),框架就不会验证token,可内网部署。

// 改之前:this._requestManager._customAccessToken,(t=>{if(t&&(t.message===e.AUTH_ERR_MSG||401===t.status))
// 改制后:this._requestManager._customAccessToken,(t=>{if(t&&(false))

4.3.2 非修改源码方式,TS依赖检查报错(需要忽略报错)

// <div ref="mapRef" id="map"></div>

// const mapRef = ref()
// container: mapRef.value, // 地图容器

// 初始化地图
const map = new mapboxgl.Map({
    container: 'map',
    // style: "mapbox://styles/mapbox/streets-v12",
    // 必须要设置style、sources、layers,如果有字体,必须要设置glyphs属性
    style: {
        version: 8,
        sources: {},
        layers: []
    },
    center: [130, 50],
    zoom: 0
});
console.log("初始化地图完成:", map);

// 添加导航控件
map.addControl(new mapboxgl.NavigationControl(), 'top-left');

// 移除Token校验
// @ts-ignore
map._authenticate = () => {
    console.log("移除Token校验");
}

map.on('load', function () {
    console.log('Map Load')

    // 初始化后加载栅格类型的地图
    map.addLayer({
        id: "GoogleImageLayer",
        type: "raster",
        source: {
            "type": "raster",
            "tiles": ["https://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}"],
            "tileSize": 256
        }
    });
})

4.3.3 移除默认控件

// ͨ通过设置css样式移除
// map._controls[0]._container.style.display = 'none'

let controls = map._controls;
controls.forEach(control => {
    console.log("'_updateLogo' in control", '_updateLogo' in control)
    // 移除logo控件
    if('_updateLogo' in control){
        map.removeControl(control)
    }

    // 移除地图属性控件
    if('_attribHTML' in control){
        map.removeControl(control)
    }
})

5 Maplibre

maplibre是基于MapBox 1.x分支出来的,在使用上与Mapbox类似,但是移除了Mapbox的校验,默认添加了字体支持(未验证默认字体对中文的字体的支持情况)。

5.1 安装依赖

参考:https://visgl.github.io/react-map-gl/docs/get-started

# 安装依赖
pnpm install maplibre-gl

# maplibre款式规范
@maplibre/maplibre-gl-style-spec

6 ArcGIS for JavaScript

依赖下载:https://developers.arcgis.com/javascript/latest/downloads/

7 GeoScene

7.1 安装依赖

# 创建vue项目
pnpm create vite my-vue-app --template vue

# 安装GeoScene
pnpm install @geoscene/core
# 安装指定版本
pnpm install @geoscene/core@4.23.14

pnpm view @geoscene/core versions

7.2 本地化配置

7.2.1 本地化资源依赖配置(内网)
// 导入GeoScene全局配置
import geosceneConfig from '@geoscene/core/config'

// 导入GeoScene的静态资源加载路径(如GeoScene微件的配置)
geosceneConfig.assetsPath = 'https://ynyth.jcdiq.cn/geoscene/assets'

// 设置字体库的访问路径,内网环境需要设置,不然地图绘制标签时找不到字体,显示不出标签文本。
geosceneConfig.fontsUrl = 'https://ynyth.jcdiq.cn/geoscene/fonts'
7.2.2 导入GeoScene地图样式

方法一:使用js语法

<script setup lang="ts">
// 亮色 
import '@geoscene/core/assets/geoscene/themes/light/main.css'
    
// 暗色
// import '@geoscene/core/assets/geoscene/themes/dark/main.css'
</script>

方法二:使用CSS样式导入语法(全局导入)

<!--导入GeoScene地图组件的默认样式-->
<style lang="scss">
// 使用scss的@user
@use '@geoscene/core/assets/geoscene/themes/dark/main.css';

// 使用原生CSS的中的@import
// @import '@geoscene/core/assets/geoscene/themes/dark/main.css';
</style>

7.3 入门示例组件

<template>
    <div ref="mapRef" class="geoscene-map"></div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import '@geoscene/core/assets/geoscene/themes/light/main.css'
import geosceneConfig from '@geoscene/core/config'
import Map from '@geoscene/core/Map'
import MapView from '@geoscene/core/views/MapView'

const props = defineProps<{
    id: string
    mapId: string
    fixed: boolean
}>()
/**
 * @ClassName GeoSceneMap
 * @Description GeoScene地图组件
 * @Author xuyizhuo
 * @Date 2024/3/30 16:12
 */
const mapRef = ref<HTMLDivElement | string>('')
// GeoScene地图
let geosceneMap: GeoSceneMap | undefined

// 初始化地图
function initMap() {
    console.log('init map')
    // 设置静态资源的访问路径,内网环境需要设置,不然前端的样式有些问题
    geosceneConfig.assetsPath = 'https://ynyth.jcdiq.cn/geoscene/assets'
    // 设置字体库的访问路径,内网环境需要设置,不然地图绘制标签时找不到字体,显示不出标签文本。
    geosceneConfig.fontsUrl = 'https://ynyth.jcdiq.cn/geoscene/fonts'
    const map = new Map({
        basemap: 'tianditu-vector', // 设置底图,
    })

    const mapView = new MapView({
        container: mapRef.value, // 绘制地图的容器
        map,
        center: [104.02480673856877, 27.79702076736095], // 设置地图的中心点
        // zoom: 5, // 设置地图的缩放层级,ArcGIS地图中有瓦片图层才会生效,建议优先使用比例尺设置。
        scale: 36978595.474472, // 设置比例尺
        // 移除默认的地图组件
        ui: {
            components: []
        },
    })
    
    // 移除ArcGIS中所以的地图微件
    // mapView.ui.components = []
}

onMounted(initMap)
</script>

<style lang="scss" scoped>
.geoscene-map {
	width: 100%;
    height: 100%;
}
</style>

<!--<style lang="scss">
@use '@geoscene/core/assets/geoscene/themes/light/main.css';
</style>-->

8 数据格式转换工具

8.1 terraformer

支持ArcGIS的Geometry与GeoJSON的项目转换

npm使用:https://www.npmjs.com/package/@terraformer/arcgis

github仓库:https://github.com/terraformer-js/terraformer

# 依赖
pnpm install @terraformer/arcgis

# ts类型校验
pnpm i @types/terraformer__arcgis -D
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值