openlayers 加载nginx发布的松散型arcgis瓦片
openlayers官方案例中有加载arcgis瓦片服务的例子,但是只为了加载瓦片就安装一套arcgis未免过于繁琐,因此选用松散切片文件+nginx 的方式发布,旨在快速便捷。
关于切片要求
本次案例中我的切片是在本机用 arcgis desktop 直接切好,切图配置按照arcgis online服务设置(就是这个服务)
arcgis desktop 生成切片
- 使用 ArcToolbox -> Data Management Tools -> Tile Cache -> Generate Tile Cache Tiling Scheme 工具生成切片配置文件;
按照上面说的服务配置,特别注意两点:
1)在 Advanced Options 中设置 Origin 为 X: -2.0037508342787E7,Y: 2.0037508342787E7
2)在 Advanced Options 中设置Tile Format 为PNG(为了解析时统一后缀),Storage Format 为 EXPLODED(也就是松散型切片,生成的瓦片是图片) - 使用 ArcToolbox -> Data Management Tools -> Tile Cache -> Manage Tile Cache 工具生成切片;
这一步设置 Input Tiling Scheme 为 IMPORT_SCHEME,就可以选择刚才生成的切片配置文件来切片了。
发布切片
这一步没什么好说的,丢到nginx的html文件夹就行了,按照路径测试一下能不能访问到图片。
openlayers 加载瓦片
这个步骤主要是使用ol/source/XYZ的tileUrlFunction来拼接瓦片路径。arcgis切片文件夹组织的特点是
1)以一个大写字母开头,level就是"L",col就是"C",row就是"R"。
2)级别使用2位十进制,行列使用8位16进制。
我们要做的就是根据切片配置设置正确的TileGrid(如果按上一步设置,就可以用下面的代码加载,否则需要自行设置正确的参数),然后将切片请求坐标转成arcgis瓦片路径。
具体实现见下面代码:
import TileLayer from "ol/layer/Tile"
import XYZ from 'ol/source/XYZ';
import TileGrid from 'ol/tilegrid/TileGrid';
import {get as getProjection} from 'ol/proj';
import {getTopLeft} from 'ol/extent';
_createArcgisLayer() {
let url = url //服务地址,必需
let projection = getProjection(`EPSG:3857`)
let projectionExtent = projection.getExtent()
let origin = getTopLeft(projectionExtent)
let res0 = 156543.03392800014
let resNum = 18
let resolutions = []
if (!resolutions.length) {
for (let z = 0; z < resNum; ++z) {
resolutions[z] = res0 / Math.pow(2, z)
}
}
let widgetLayer = new TileLayer({
source: new XYZ({
tileUrlFunction: (coords) => {//把原本的切片请求坐标转成arcgis切片文件路径
let l = "L" + fillZero(coords[0], 2, 10)
let c = "C" + fillZero(coords[1], 8, 16)
let r = "R" + fillZero(coords[2], 8, 16)
return `${url}/Layers/_alllayers/${l}/${r}/${c}.png`
},
projection,
tileGrid: new TileGrid({//设置正确的TileGrid才能使切片请求坐标正确
origin,
resolutions,
}),
}),
})
return widgetLayer
},
// 这个方法用于补全和转进制
fillZero(c, len, b) {
return c.toString(b).padStart(len,'0')
},
addLayer() {
let layer = _createArcgisLayer()
map.add(layer)
},