缘起近期在项目中遇到这么一个需求,需要在地图上展示一组格网数据,格网大小为2m*2m
,地图api
用的mapboxgl
。起初拿到这个需要感觉很easy,在地图上添加一个fill
图层就好啦 。把格网面数据添加到地图上之后,在大比例尺下显示正常,但是当地图层级小于15级时,渲染出的结果会消失 。
文章插图
简单理一下原因,应该是在地图缩小后,每个网格所占的像素太小,所以就消失了 。
但是这种情况又需要查看数据,要如何实现呢?mapboxgl
在处理symbol
图层的时候,会遇到点位自动避让问题,导致部分点位不显示 。解决方法是把layout
中的icon-allow-overlap
设置为true
,这样就相当于关闭了自动避让功能,所有点图标保持可见状态 。但是针对fill
图层却没有这么一个属性 。
首先分析下数据,我的原始数据是通过模型导出的
tiff
格式的栅格数据,然后在后台根据tiff
格式数据中每个像素所在行列号以及其灰度值生成带属性的格网数据,其中像素的灰度值就是在渲染时需要分类展示的值 。既然原始tiff
数据的灰度值就是所用的属性值,那是不是直接添加到地图就好了 。接下来的解决方案就是看是否能直接用mapboxgl
直接加载tiff
数据,并渲染出自己想要的效果 。mapboxgl加载tiff查看
mapboxgl
文档,可以看到mapboxgl
支持image
图层,只需传入url和coordinates// 添加至地图map.addSource('some id', {type: 'image',url: 'https://www.mapbox.com/images/foo.png',coordinates: [[-76.54, 39.18],[-76.52, 39.18],[-76.52, 39.17],[-76.54, 39.17]]});
可是,当我把地址换成tiff
数据时却报错了 。下面为报错内容:Could not load image because of The source image could not be decoded.. Please make sure to use a supported image type such as PNG or JPEG. Note that SVGs are not supported可以简单理解为不支持
tiff
格式 。tiff文件解析既然
mapboxgl
的image
图层不支持tiff
格式,那是不是可以把tiff
数据导出成png
呢,于是使用arcmap
打开了tiff
数据,导出数据格式也支持png
,但是在保存时又报错了 。文章插图
【mapboxgl加载tiff】经过分析,发现是
tiff
数据波段数量的原因,我的这份数据波段数为1,从网上下载了一份测试数据,波段数为3,可以成功导出 。文章插图
在查找相关解决方案的时候,看到这么个工具,geotiff.js,可以通过
js
解析tiff
数据并渲染,leaflet
有个扩展就是用的这个工具,https://github.com/stuartmatthews/leaflet-geotiff 。查看geotiff.js
相关文档,发现其实用起来还是挺方便的,通过简单的代码实现的我的需求 。先使用
geotiff.js
解析tiff
数据,再配合使用canvas
绘制图片导出base64
格式数据,然后就可以使用添加到mapboxgl
图层了 。核心代码如下:
async function getData() {GeoTIFF.fromUrl(url).then(tiff => {console.log(tiff)getImage(tiff)});}async function getImage(tiff) {const image = await tiff.getImage();let bbox = await image.getBoundingBox();let data = https://www.huyubaike.com/biancheng/await image.readRasters({samples: rgbBands // 波段数量,一个波段:[0],三个波段:[2,1,0]});let base64Image = getBase64Image(data)addToMapboxgl(base64Image)}function getBase64Image(data) {let thumbnailPixelHeight = data.heightlet thumbnailPixelWidth = data.widthlet canvas = document.createElement('canvas')canvas.width = thumbnailPixelWidthcanvas.height = thumbnailPixelHeightlet ctx = canvas.getContext("2d")let totalPixelCount = 0for (let y = 0; y < thumbnailPixelHeight; y++) {for (let x = 0; x < thumbnailPixelWidth; x++) {let colour = 'rgb(0, 0, 0, 0)' // let the default be no data (transparent)// 根据灰度值所在范围渲染颜色if (data[0][totalPixelCount] > 0) {if (data[0][totalPixelCount] > 50 && data[0][totalPixelCount] <= 55) {colour = `rgb(15, 255, 0, 1)`} else if (data[0][totalPixelCount] > 55 && data[0][totalPixelCount] <= 60) {colour = `rgb(155, 255, 0, 1)`} else if (data[0][totalPixelCount] > 60 && data[0][totalPixelCount] <= 65) {colour = `rgb(255, 255, 0, 1)`} else {colour = `rgb(255, 255, 0, 1)`}}ctx.fillStyle = colourctx.fillRect(x, y, 1, 1)totalPixelCount++}}let canvasImage = canvas.toDataURL("image/png")return canvasImage}// 将图片添加到地图function addToMapboxgl(image) {map.addSource('tiff-source', {"type": "image","url": image,"coordinates": [[114.425597191307, 38.1091563484708],[114.538187627939, 38.1091563484708],[114.538187627939, 37.9627378349512],[114.425597191307, 37.9627378349512]]});map.addLayer({id: 'tiff-layer','type': 'raster','source': 'tiff-source','paint': {'raster-fade-duration': 0}});}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- excel2010如何加载宏呢?一起学一学吧!
- excel分析工具库怎么加载?
- excel2010如何加载宏
- Excel 2007加载宏所出现的问题
- 微信加载小程序超时无法启动怎么办?
- 电脑开机时不能加载本地储存怎么办?
- 微信资源包加载失败怎么回事?
- iphone照片加载不出来感叹号?
- 微信加载不出别人的表情包?
- 微信图片无法加载?