腾讯地图的配图和整体色调,较之高德、百度和天地图更加美观,是国内使用教广泛的互联网地图之一,在WebGIS开发中,有广泛的应用。但不同于谷歌、天地图、高德等互联网地图,腾讯地图的切片方式和服务URL自成体系。本文详细介绍如何通过Leaflet加载腾讯地图,如使用其他JS SDK,参照本文的加载思路,进行相应修改即可。
Leaflet加载腾讯地图的开发示例(load-tecent-map.html)
一、自定义腾讯地图服务获取函数
腾讯地图完全遵从TMS标准,且服务URL中存在z、x、y、x16和y16等关键参数,在加载时,需要自定义z、x、y和x16、y16的值,并正确拼接服务地址。下面对服务获取函数的定义进行介绍。
L.TileLayer.WebDogTileLayer = L.TileLayer.extend({
getTileUrl: function (tilePoint) {
var urlArgs,
getUrlArgs = this.options.getUrlArgs;
if (getUrlArgs) {
var urlArgs = getUrlArgs(tilePoint);
} else {
urlArgs = {
z: tilePoint.z,
x: tilePoint.x,
y: tilePoint.y,
};
}
return L.Util.template(
this._url,
L.extend(urlArgs, this.options, {
s: this._getSubdomain(tilePoint),
})
);
},
});
L.tileLayer.webdogTileLayer = function (url, options) {
return new L.TileLayer.WebDogTileLayer(url, options);
};
二、定义腾讯地图加载函数
下面定义加载腾讯各类型地图的加载函数,方便在不同地图间的切换,Leaflet中定义方式如下所示。
var initOptions = {
subdomains: "012",
getUrlArgs: function (tilePoint) {
return {
z: tilePoint.z,
x: tilePoint.x,
y: Math.pow(2, tilePoint.z) - 1 - tilePoint.y,
x16: Math.floor(tilePoint.x / 16.0),
y16: Math.floor(
(Math.pow(2, tilePoint.z) - 1 - tilePoint.y) / 16.0
),
};
},
};
L.tileLayer.tecent = function (option) {
option = option || {};
var layer;
var opts = { ...initOptions, ...option };
switch (option.layer) {
// 矢量图
case "vec":
default:
layer = L.tileLayer.webdogTileLayer(
"http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0",
opts
);
break;
// 单图层-影像图
case "img_d":
layer = L.tileLayer.webdogTileLayer(
"http://p{s}.map.gtimg.com/sateTiles/{z}/{x16}/{y16}/{x}_{y}.jpg",
opts
);
break;
// 单图层-影像注记
case "img_z":
layer = L.tileLayer.webdogTileLayer(
"http://rt{s}.map.gtimg.com/tile?z={z}&x={x}&y={y}&styleid=2&version=376",
opts
);
break;
//图层叠加-影像图(含注记)
case "img":
layer = L.layerGroup([
L.tileLayer.tecent({
name: "底图",
layer: "img_d",
}),
L.tileLayer.tecent({
name: "注记",
layer: "img_z",
}),
]);
break;
// 单图层-地形图
case "ter_d":
layer = L.tileLayer.webdogTileLayer(
"http://p{s}.map.gtimg.com/demTiles/{z}/{x16}/{y16}/{x}_{y}.jpg",
opts
);
break;
// 单图层-地形注记
case "ter_z":
layer = L.tileLayer.webdogTileLayer(
"http://rt{s}.map.gtimg.com/tile?z={z}&x={x}&y={y}&type=vector&styleid=3&version=376",
opts
);
break;
//图层叠加-地形图(含注记)
case "ter":
layer = L.layerGroup([
L.tileLayer.tecent({
name: "底图",
layer: "ter_d",
}),
L.tileLayer.tecent({
name: "注记",
layer: "ter_z",
}),
]);
break;
}
return layer;
};
三、图层加载函数使用及添加图层控制控件
Leaflet提供了图层控制的控件,方便在地图底图的切换和业务图层的显示与隐藏进行控制,下面以上述腾讯地图加载类函数为例,对图层控制的使用进行说明。
let vec = new L.tileLayer.tecent({ layer: "vec", name: "矢量图" });
let img_d = new L.tileLayer.tecent({ layer: "img_d", name: "影像图" });
let img_z = new L.tileLayer.tecent({ layer: "img_z", name: "影像注记" });
let img = new L.tileLayer.tecent({
layer: "img",
name: "影像图(含注记)",
});
let ter_d = new L.tileLayer.tecent({ layer: "ter_d", name: "地形图" });
let ter_z = new L.tileLayer.tecent({ layer: "ter_z", name: "地形注记" });
let ter = new L.tileLayer.tecent({
layer: "ter",
name: "地形图(含注记)",
});
var options = {
center: [31.24, 121.5],
zoom: 15, // initial zoom of map
layers: [vec],
};
var map = L.map("mapdiv", options);
L.marker([31.24, 121.5])
.addTo(map)
.bindTooltip("上海东方明珠")
.openTooltip();
const baseLayers = {
矢量图: vec,
影像图: img_d,
影像注记: img_z,
"影像图(含注记)": img,
地形图: ter_d,
地形注记: ter_z,
"地形图(含注记)": ter,
// 实时路况: time,
};
// 添加图层控制控件
L.control.layers(baseLayers).addTo(map);
四、加载腾讯地图的完整代码
<!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" />
<title>LeafletJS加载腾讯地图 - 优吉斯(YouGIS)</title>
<link href="../lib/leaflet/leaflet.css" rel="stylesheet" />
<script src="../lib/jquery/jquery.min.js"></script>
<script src="../lib/leaflet/leaflet.js"></script>
<style>
* {
padding: 0;
margin: 0;
}
#location {
position: fixed;
padding: 5px;
left: 0;
bottom: 0;
background-color: #fff;
z-index: 999;
font-size: 12px;
font-weight: bold;
color: blue;
border-top-right-radius: 5px;
/* width: 255px; */
}
#mapdiv {
width: 100vw;
height: calc(100vh - 156px);
}
#promptInfo {
z-index: 999;
position: absolute;
color: red;
font-size: large;
font-weight: bold;
margin-left: 80px;
margin-top: 20px;
}
</style>
</head>
<body>
<iframe src="../yougis.html" style="width: 100vw; height: 156px"></iframe>
<div id="mapdiv">
<div id="promptInfo"></div>
</div>
<div id="location"></div>
<script>
L.TileLayer.WebDogTileLayer = L.TileLayer.extend({
getTileUrl: function (tilePoint) {
var urlArgs,
getUrlArgs = this.options.getUrlArgs;
if (getUrlArgs) {
var urlArgs = getUrlArgs(tilePoint);
} else {
urlArgs = {
z: tilePoint.z,
x: tilePoint.x,
y: tilePoint.y,
};
}
return L.Util.template(
this._url,
L.extend(urlArgs, this.options, {
s: this._getSubdomain(tilePoint),
})
);
},
});
L.tileLayer.webdogTileLayer = function (url, options) {
return new L.TileLayer.WebDogTileLayer(url, options);
};
var initOptions = {
subdomains: "012",
getUrlArgs: function (tilePoint) {
return {
z: tilePoint.z,
x: tilePoint.x,
y: Math.pow(2, tilePoint.z) - 1 - tilePoint.y,
x16: Math.floor(tilePoint.x / 16.0),
y16: Math.floor(
(Math.pow(2, tilePoint.z) - 1 - tilePoint.y) / 16.0
),
};
},
};
L.tileLayer.tecent = function (option) {
option = option || {};
var layer;
var opts = { ...initOptions, ...option };
switch (option.layer) {
// 矢量图
case "vec":
default:
layer = L.tileLayer.webdogTileLayer(
"http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0",
opts
);
break;
// 单图层-影像图
case "img_d":
layer = L.tileLayer.webdogTileLayer(
"http://p{s}.map.gtimg.com/sateTiles/{z}/{x16}/{y16}/{x}_{y}.jpg",
opts
);
break;
// 单图层-影像注记
case "img_z":
layer = L.tileLayer.webdogTileLayer(
"http://rt{s}.map.gtimg.com/tile?z={z}&x={x}&y={y}&styleid=2&version=376",
opts
);
break;
//图层叠加-影像图(含注记)
case "img":
layer = L.layerGroup([
L.tileLayer.tecent({
name: "底图",
layer: "img_d",
}),
L.tileLayer.tecent({
name: "注记",
layer: "img_z",
}),
]);
break;
// 单图层-地形图
case "ter_d":
layer = L.tileLayer.webdogTileLayer(
"http://p{s}.map.gtimg.com/demTiles/{z}/{x16}/{y16}/{x}_{y}.jpg",
opts
);
break;
// 单图层-地形注记
case "ter_z":
layer = L.tileLayer.webdogTileLayer(
"http://rt{s}.map.gtimg.com/tile?z={z}&x={x}&y={y}&type=vector&styleid=3&version=376",
opts
);
break;
//图层叠加-地形图(含注记)
case "ter":
layer = L.layerGroup([
L.tileLayer.tecent({
name: "底图",
layer: "ter_d",
}),
L.tileLayer.tecent({
name: "注记",
layer: "ter_z",
}),
]);
break;
// //实时路况
// case "time":
// var time = new Date().getTime();
// layer = L.tileLayer(
// "http://tm.tecent.com/trafficengine/mapabc/traffictile?v=1.0&;t=1&x={x}&y={y}&z={z}&&t=" +
// time,
// {
// name: option.name,
// }
// );
// break;
}
return layer;
};
let vec = new L.tileLayer.tecent({ layer: "vec", name: "矢量图" });
let img_d = new L.tileLayer.tecent({ layer: "img_d", name: "影像图" });
let img_z = new L.tileLayer.tecent({ layer: "img_z", name: "影像注记" });
let img = new L.tileLayer.tecent({
layer: "img",
name: "影像图(含注记)",
});
let ter_d = new L.tileLayer.tecent({ layer: "ter_d", name: "地形图" });
let ter_z = new L.tileLayer.tecent({ layer: "ter_z", name: "地形注记" });
let ter = new L.tileLayer.tecent({
layer: "ter",
name: "地形图(含注记)",
});
// let time = new L.tileLayer.tecent({ layer: "time", name: "实时路况" });
$(document).ready(function () {
var options = {
center: [31.24, 121.5],
zoom: 15, // initial zoom of map
layers: [vec],
};
var map = L.map("mapdiv", options);
L.marker([31.24, 121.5])
.addTo(map)
.bindTooltip("上海东方明珠")
.openTooltip();
const baseLayers = {
矢量图: vec,
影像图: img_d,
影像注记: img_z,
"影像图(含注记)": img,
地形图: ter_d,
地形注记: ter_z,
"地形图(含注记)": ter,
// 实时路况: time,
};
// 添加图层控制控件
L.control.layers(baseLayers).addTo(map);
// 设置初始显示内容
let initInfo =
"请通过右上角图层控制切换地图, 点击地图左下角展示坐标<br/>";
initInfo += "当前选择地图:" + vec.options.name + "<br/>";
initInfo += "服务地址:" + vec._url;
document.getElementById("promptInfo").innerHTML = initInfo;
// 图层切换事件, 设置显示的提示信息
map.on("baselayerchange", function (e) {
let info =
"请通过右上角图层控制切换地图, 点击地图左下角展示坐标<br/>";
info += "当前选择地图:" + e.name + "<br/>";
if (e.layer._url) {
info += "服务地址:" + e.layer._url;
} else if (e.layer._layers) {
for (k in e.layer._layers) {
let v = e.layer._layers[k];
info += "服务地址" + k + ":" + v._url + "<br/>";
}
}
document.getElementById("promptInfo").innerHTML = info;
});
map.on("click", (e) => {
let lnglat =
"鼠标点击位置坐标:" + e.latlng.lng + " , " + e.latlng.lat;
$("#location")[0].innerText = lnglat;
});
window.map = map;
});
</script>
</body>
</html>
评论区