index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1634082_fc7stux6chb.css">
<title>mapbox、天地圖、vue</title>
<script>
window.TDT_CONFIG = {
// 當前項目域名:http://www.tianditu.gov.cn
HOME_URL:'http://192.168.0.106:8080',
// 矢量瓦片地址
VECTOR_URL: 'http://gisserver.tianditu.com',
// 地圖屬性配置
MAP:{
// 圖幅號
SHEET_NUMBER:'GS(2019)1719號 - 甲測資字1100471',
// 底圖地址
URL: 'http://t{s}.tianditu.gov.cn/',
// 級別
ZOOM: 2,
// 中心點
CENTER: [104.09215287988154, 40.277052933991797],
// 底圖key
TOKEN: '66c315d7235737b75bef98fbb3fb0c00'
}
}
</script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
BaseMap.vue
<template>
<div class="visual-map" :class="`visual-map-${device}`">
<div id="map-container"></div>
<VisualLayer v-if="loaded" :legends="legends" />
<Legend :legends="legends" />
<Regional />
</div>
</template>
<script>
import { mapState } from "vuex";
import "mapbox-gl/dist/mapbox-gl.css";
import MapboxGl from "mapbox-gl";
import VisualLayer from './VisualLayer.vue'
import Legend from './Legend.vue'
import Regional from './Regional.vue'
import chinaJson from '../../json/china.json'
import config from "../../config";
const {
HOME_URL,
MAP: { ZOOM, URL, CENTER, TOKEN, SHEET_NUMBER }
} = window.TDT_CONFIG;
const { projectDir } = config;
const MAP_TYPES = [
{
mapType: "vec",
active: true
},
{
mapType: "cva",
active: true
}
];
let map = null;
export default {
name:"BaseMap",
components: {
VisualLayer,
Legend,
Regional
},
props:{
loaded:{
type:Boolean
}
},
data () {
return {
legends:{
province:{
total:[
{
color:'#792A19',
grade:['10000']
},
{
color:'#A94D34',
grade:['5000','9999']
},{
color:'#CA613E',
grade:['1000','4999']
},{
color:'#F18334',
grade:['500','999']
},{
color:'#FFC54D',
grade:['100','499']
},{
color:'#f9d892',
grade:['10','99']
},{
color:'#fdf7b9',
grade:['1','9']
},{
color:'#FEFEFE',
grade:['0']
},
],
today:[
{
color:'#792A19',
grade:['200']
},
{
color:'#A94D34',
grade:['100','199']
},{
color:'#CA613E',
grade:['50','99']
},{
color:'#F18334',
grade:['20','49']
},{
color:'#FFC54D',
grade:['10','19']
},{
color:'#FDF7B9',
grade:['1','9']
},{
color:'#FEFEFE',
grade:['0']
},
]
},
city:{
total:[
{
color:'#792A19',
grade:['1000']
},
{
color:'#A94D34',
grade:['500','999']
},
{
color:'#CA613E',
grade:['100','499']
},{
color:'#F18334',
grade:['50','99']
},{
color:'#FFC54D',
grade:['20','49']
},{
color:'#f9d892',
grade:['10','19']
},{
color:'#fdf7b9',
grade:['1','9']
},{
color:'#FEFEFE',
grade:['0']
},
],
today:[
{
color:'#792A19',
grade:['500']
},
{
color:'#A94D34',
grade:['100','499']
},
{
color:'#CA613E',
grade:['50','99']
},{
color:'#F18334',
grade:['20','49']
},{
color:'#FFC54D',
grade:['10','19']
},{
color:'#f9d892',
grade:['5','9']
},{
color:'#fdf7b9',
grade:['1','4']
},{
color:'#FEFEFE',
grade:['0']
},
]
}
}
}
},
computed:{
...mapState([
'device'
])
},
mounted() {
this.initMap();
},
methods: {
initMap() {
// 獲取底圖的數據源和對應的圖層
const { sources, layers } = this.getBaseMap(MAP_TYPES);
// mapbox 樣式
let style = {
version: 8,
sprite: `${HOME_URL}${projectDir}/mapbox/sprite/sprite`,
glyphs: `${HOME_URL}${projectDir}/mapbox/font/{fontstack}/{range}.pbf`,
sources,
layers
};
map = new MapboxGl.Map({
container: "map-container",
center: CENTER,
zoom: ZOOM,
minZoom: 1,
maxZoom: 18,
style,
transformRequest: (url, resourceType) => {
if (resourceType === "Tile" && url.indexOf("DataServer") > -1) {
let random = Math.floor(Math.random() * 7);
return {
url: url.replace("{s}", random)
};
}
}
});
// 添加審圖號
let control = this.getSheetNumberControl();
map.addControl(control, 'bottom-left');
// 底圖加載完畢
map.on("style.load", () => {
this.$emit("map-loaded", map);
// 添加國界數據
this.addChinaBorder();
});
},
/**
* 添加中國國界圖層
* */
addChinaBorder() {
map.addSource('china_border_source', {
'type': 'geojson',
'data': chinaJson
});
map.addLayer({
'id': 'china_border_layer',
'type': 'line',
'source': 'china_border_source',
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': 'red',
'line-width': 3,
'line-opacity':0.5
}
});
},
/**
* 獲取數據源和底圖圖層
* */
getBaseMap(mapTypes) {
let sources = {},
layers = [];
mapTypes.forEach(type => {
let active = true;
// 底圖
if (typeof type === "object") {
active = type.active;
type = type.mapType;
}
let sourceId = "osm-" + type + "-tiles";
sources[sourceId] = {
type: "raster",
tiles: [`${URL}DataServer?T=${type}_w&x={x}&y={y}&l={z}&tk=${TOKEN}`],
tileSize: 256
};
let layerId = "tdt-" + type + "-tiles";
let layer = {
id: layerId,
type: "raster",
source: sourceId,
minZoom: 1,
maxZoom: 18,
layout: {
visibility: active ? "visible" : "none"
}
};
layers.push(layer);
});
return {
sources,
layers
};
},
/**
* 添加審圖號
*/
getSheetNumberControl () {
function SheetNumberControl() { }
SheetNumberControl.prototype.onAdd = function(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'mapboxgl-ctrl';
this._container.innerHTML = '<img src="http://api.tianditu.gov.cn/v4.0/image/logo.png" style="position: absolute;bottom: 5px;" width="53px" height="22px" opacity="0"><div class="sheetNumber" style="position:absolute;bottom:2px;left:70px;white-space:nowrap;">'+SHEET_NUMBER+'</div>';
return this._container;
};
SheetNumberControl.prototype.onRemove = function () {
this._container.parentNode.removeChild(this._container);
this._map = undefined;
};
return new SheetNumberControl();
}
}
};
</script>
<style scoped lang="scss">
.visual-map{
position:relative;
width: 100vw;
height: 100vh;
}
#map-container {
width: 100%;
height: 100%;
}
.visual-map-mobile{
height: 50vh;
}
</style>