缘起近期在项目中遇到这么一个需求,需要在地图上展示一组格网数据 , 格网大小为2m*2m
,地图api
用的mapboxgl
。起初拿到这个需要感觉很easy,在地图上添加一个fill
图层就好啦 。把格网面数据添加到地图上之后,在大比例尺下显示正常,但是当地图层级小于15级时 , 渲染出的结果会消失 。
![mapboxgl加载tiff](https://m.360buyimg.com/jdcms/jfs/t1/51254/33/21620/571516/63372a6eE4a8d1256/0707cd79c8b5d78a.gif)
文章插图
简单理一下原因,应该是在地图缩小后,每个网格所占的像素太?。跃拖Я?。
但是这种情况又需要查看数据,要如何实现呢?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](http://img.zhejianglong.com/231017/1GZAB7-1.png)
文章插图
经过分析 , 发现是
tiff
数据波段数量的原因,我的这份数据波段数为1,从网上下载了一份测试数据,波段数为3,可以成功导出 。![mapboxgl加载tiff](http://img.zhejianglong.com/231017/1GZCD3-2.png)
文章插图
在查找相关解决方案的时候,看到这么个工具,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}});}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 男生假发一般多少钱 男士假发多少钱一顶
- 驱动加载失败怎么办 驱动加载失败怎么办啊
- 创维电视加载插件失败是什么原因
- 无法加载插件怎么办
- 王者荣耀cdk在哪里兑换
- AI开始界面一直加载怎么解决
- 电脑开机加载慢是什么原因 开机运行慢的处理窍门
- 网络延迟加载失败什么意思 加载驱动失败什么意思
- 电脑游戏加载慢是什么原因呢 电脑游戏加载慢是什么原因
- windows预览体验计划加载不出来 windows预览体验计划打不开