矢量切片(vector tile)是当前 WebGIS 较热技术,国内的高德、百度等在线地图都使用了矢量切片技术。相较于传统栅格切片,矢量切片好处很多。简单几点就是:轻量、客户端渲染、还可加密(栅格切片容易被爬取)。矢量切片格式一般有 GeoJSON、TopoJSON 、MVT (MapBox Vector Tile)、PBF。

下面是 Cesium 加载 MVT 矢量切片的代码,由于样式渲染使用的了 openlayers,所以首先需要安装 openlayers。

一、安装 openlayers

npm install openlayers

二、MVT 加载核心代码

```javascript

// mvtProvider.js

import * as Cesium from 'cesium'

import ol from 'openlayers/dist/ol-debug'

export function MVTProvider (options) {

options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT)

this._tilingScheme = Cesium.defined(options.tilingScheme) ? options.tilingScheme : new Cesium.WebMercatorTilingScheme({ ellipsoid: options.ellipsoid })

this._tileWidth = Cesium.defaultValue(options.tileWidth, 512)

this._tileHeight = Cesium.defaultValue(options.tileHeight, 512)

this._readyPromise = Cesium.when.resolve(true)

this._ol = ol

this._mvtParser = new this._ol.format.MVT()

this._styleFun = Cesium.defined(options.styleFun) ? options.styleFun : createMapboxStreetsV6Style

this._key = Cesium.defaultValue(options.key, '')

this._url = Cesium.defaultValue(options.url, 'https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/{z}/{x}/{y}.vector.pbf?access_token={k}')

var sw = this._tilingScheme._rectangleSouthwestInMeters

var ne = this._tilingScheme._rectangleNortheastInMeters

var mapExtent = [sw.x, sw.y, ne.x, ne.y]

this._resolutions = ol.tilegrid.resolutionsFromExtent(mapExtent, 22, this._tileWidth)

this._pixelRatio = 1

this._transform = [0.125, 0, 0, 0.125, 0, 0]

this._replays = ['Default', 'Image', 'Polygon', 'LineString', 'Text']

this._tileQueue = new Cesium.TileReplacementQueue()

this._cacheSize = 1000

}

Object.defineProperties(MVTProvider.prototype, {

proxy: {

get () {

return undefined

}

},

tileWidth: {

get () {

return this._tileWidth

}

},

tileHeight: {

get () {

return this._tileHeight

}

},

maximumLevel: {

get () {

return undefined

}

},

minimumLevel: {

get () {

return undefined

}

},

tilingScheme: {

get () {

return this._tilingScheme

}

},

rectangle: {

get () {

return this._tilingScheme.rectangle

}

},

tileDiscardPolicy: {

get () {

return undefined

}

},

errorEvent: {

get () {

return this._errorEvent

}

},

ready: {

get () {

return true

}

},

readyPromise: {

get () {

return this._readyPromise

}

},

credit: {

get () {

return undefined

}

},

hasAlphaChannel: {

get () {

return true

}

}

})

MVTProvider.prototype.getTileCredits = function () {

return undefined

}

function findTileInQueue (x, y, level, tileQueue) {

var item = tileQueue.head

while (item !== undefined && !(item.xMvt === x && item.yMvt === y && item.zMvt === level)) {

item = item.replacementNext

}

return item

}

function remove (tileReplacementQueue, item) {

var previous = item.replacementPrevious

var next = item.replacementNext

if (item === tileReplacementQueue._lastBeforeStartOfFrame) {

tileReplacementQueue._lastBeforeStartOfFrame = next

}

if (item === tileReplacementQueue.head) {

tileReplacementQueue.head = next

} else {

previous.replacementNext = next

}

if (item === tileReplacementQueue.tail) {

tileReplacementQueue.tail = previous

} else {

next.replacementPrevious = previous

}

item.replacementPrevious = undefined

item.replacementNext = undefined

--tileReplacementQueue.count

}

function trimTiles (tileQueue, maximumTiles) {

var tileToTrim = tileQueue.tail

while (tileQueue.count > maximumTiles &&

Cesium.defined(tileToTrim)) {

var previous = tileToTrim.replacementPrevious

remove(tileQueue, tileToTrim)

tileToTrim = null

tileToTrim = previous

}

}

MVTProvider.prototype.requestImage = function (x, y, level) {

var cacheTile = findTileInQueue(x, y, level, this._tileQueue)

if (cacheTile !== undefined) {

return cacheTile

}

var that = this

var url = this._url

url = url.replace('{x}', x).replace('{y}', y).replace('{z}', level).replace('{k}', this._key);

(function (x, y, z) {

var resource = Cesium.Resource.createIfNeeded(url)

return resource.fetchArrayBuffer().then((arrayBuffer) => {

var canvas = document.createElement('canvas')

canvas.width = 512

canvas.height = 512

var vectorContext = canvas.getContext('2d')

var features = that._mvtParser.readFeatures(arrayBuffer)

var styleFun = that._styleFun()

var extent = [0, 0, 4096, 4096]

var _replayGroup = new ol.render.canvas.ReplayGroup(0, extent, 8, true, 100)

for (var i = 0; i < features.length; i++) {

var feature = features[i]

var styles = styleFun(features[i], that._resolutions[level])

for (var j = 0; j < styles.length; j++) {

ol.renderer.vector.renderFeature_(_replayGroup, feature, styles[j], 16)

}

}

_replayGroup.finish()

_replayGroup.replay(vectorContext, that._pixelRatio, that._transform, 0, {}, that._replays, true)

if (that._tileQueue.count > that._cacheSize) {

trimTiles(that._tileQueue, that._cacheSize / 2)

}

canvas.xMvt = x

canvas.yMvt = y

canvas.zMvt = z

that._tileQueue.markTileRendered(canvas)

_replayGroup = null

return canvas

}).otherwise(() => {

})

}(x, y, level))

}

MVTProvider.prototype.pickFeatures = function () {

return undefined

}

function createMapboxStreetsV6Style () {

var fill = new ol.style.Fill({ color: '' })

var stroke = new ol.style.Stroke({ color: '', width: 1 })

var polygon = new ol.style.Style({ fill })

var strokedPolygon = new ol.style.Style({ fill, stroke })

var line = new ol.style.Style({ stroke })

var text = new ol.style.Style({

text: new ol.style.Text({

text: '', fill, stroke

})

})

var iconCache = {}

function getIcon (iconName) {

var icon = iconCache[iconName]

if (!icon) {

icon = new ol.style.Style({

image: new ol.style.Icon({

src: https://cdn.rawgit.com/mapbox/maki/master/icons/${iconName}-15.svg,

imgSize: [15, 15]

})

})

iconCache[iconName] = icon

}

return icon

}

var styles = []

return function (feature, resolution) {

var length = 0

var layer = feature.get('layer')

var cls = feature.get('class')

var type = feature.get('type')

var scalerank = feature.get('scalerank')

var labelrank = feature.get('labelrank')

var adminLevel = feature.get('admin_level')

var maritime = feature.get('maritime')

var disputed = feature.get('disputed')

var maki = feature.get('maki')

var geom = feature.getGeometry().getType()

if (layer === 'landuse' && cls === 'park') {

fill.setColor('#d8e8c8')

styles[length++] = polygon

} else if (layer === 'landuse' && cls === 'cemetery') {

fill.setColor('#e0e4dd')

styles[length++] = polygon

} else if (layer === 'landuse' && cls === 'hospital') {

fill.setColor('#fde')

styles[length++] = polygon

} else if (layer === 'landuse' && cls === 'school') {

fill.setColor('#f0e8f8')

styles[length++] = polygon

} else if (layer === 'landuse' && cls === 'wood') {

fill.setColor('rgb(233,238,223)')

styles[length++] = polygon

} else if (layer === 'waterway' &&

cls !== 'river' && cls !== 'stream' && cls !== 'canal') {

stroke.setColor('#a0c8f0')

mapbox矢量切片标准_Cesium 加载矢量切片(MapBox Vector Tile)相关推荐

  1. cesium加载arcgis切片

    cesium 加载arcmap切片 jpg // z 是缩放级别 x是从左到右 y是从上到下 var imageryUrl = '/images/{z}/{x}/{y}.jpg';//影像数据var ...

  2. cesium加载自定义的mapbox底图

    文章目录 1.实现效果 2.实现方法 2.1 mapbox自定义底图 2.2 cesium调用 Cesium实战系列文章总目录: 传送门 1.实现效果 2.实现方法 2.1 mapbox自定义底图 首 ...

  3. openlayer加载矢量切片

    数据是GIS的灵魂,没有数据也就谈不上GIS了,数据分为矢量数据和栅格数据,栅格数据也有一些短处,缺乏灵活性.实时性,数据完整性受损是比较突出的问题,矢量数据不同于栅格数据,比较灵活,数据完整,将两者 ...

  4. Cesium开发基础笔记总结(加载影像、加载地形数据、加载矢量)

    Cesium开发基础笔记总结 学习总结于GIS李胜老师博客 Cesium开发基础01加载影像数据 加载影像数据 Cesium中的影像图层类: 无论是二维地图还是三维地图,如果缺少了底图影像或电子地图, ...

  5. 如何使用Autodesk InfraWorks 360在三维地图上加载矢量道路

         之前有介绍过如何使用Autodesk InfraWorks 360加载水经注万能地图下载器下载的卫星地图和高程数据制作三维地图,在后续的设计中,针对现成的路网,可以不用再去画,可以通过万能地 ...

  6. Cesium开发:关于加载CGCS2000切片

    在线的天地图,发布的有两种切片投影格式,一个是 国家2000的坐标系,另一个是 Web Mercator的坐标系,通常我们在开发的时候,用的比较多是Web Mercator的坐标系切片. 在Cesiu ...

  7. Android标准Glide加载圆形图和圆角矩形图

    引入: implementation 'com.github.bumptech.glide:glide:4.9.0'annotationProcessor 'com.github.bumptech.g ...

  8. 优化OpenLayers加载ArcGIS切片服务的解决方案

    优化Openlayers加载切片服务(EPSG:4490) 使用  TileArcGISRest 加载服务时地址如下: https://sampleserver1.arcgisonline.com/A ...

  9. 【LoadingDialog】标准款待加载对话框

    上图是dialog的效果图,以下为代码: Java类: package com.jmheart.mechanicsbao.ui.util; import android.app.AlertDialog ...

最新文章

  1. python 中文字转拼音
  2. UART接口算法移植加密芯片的调试技巧——通讯调试
  3. Today:基于 Electron 和 Vue.js 的 GTD 应用
  4. 如此通俗的分布式锁讲解,如果还搞不定那就...
  5. 很好很强大,这款AI开发神器的图像标注吊打labelme
  6. Matlab向量与多项式
  7. 颜宁:给实验室博士的一些忠告
  8. Android-Universal-Image-Loader学习笔记(二)--LruDiscCache
  9. 2021CCF推荐国际学术会议A类及相关领域介绍
  10. C#实时判断串口连接状态
  11. 阿里云商标顾问注册申请流程、价格及常见问题解答
  12. 微信小程序Audio音频(有关歌曲和图片的路径)
  13. fpga 中的slew rate 什么意思
  14. 不是把,微信也能改?
  15. amd显卡测试大风车软件md,肉眼可见的撕裂 AMD将推出FreeSync2 HDR测试工具
  16. python实现求解最长公共子序列LCS问题
  17. Nginx是干什么的
  18. 翻转——C++青少年一级考资料
  19. 试题 算法训练 黑色星期五
  20. 采样 | 高压直流采样电路详解

热门文章

  1. 双十一丝般顺滑体验背后:阿里云洛神网络虚拟化系统揭秘
  2. 云原生全景图之六 | 托管 Kubernetes 和 PaaS 解决什么问题
  3. 云+X案例展 | 金融类:荣之联助力君康人寿构建新一代数据中心
  4. 被吹得天花乱坠的无服务器架构,究竟是什么?
  5. Cloud一分钟 | HR SaaS 平台北森云计算E轮融资1亿美金;云学堂宣布完成C轮5000万美元融资...
  6. php mysql 绕过_PHP中md5绕过
  7. linux共享软件_为什么 linux 要用 tar.gz,很少用 7z 或 zip?
  8. 秒杀场景_同步秒杀分析和实战_01
  9. java 批量为图片添加图标水印和文字水印
  10. Vue优化策略_项目上线_02