Mapboxgl + KrigingJS 实现插值图

(1)主要过程:结合Kriging.js 实现 Mapboxgl 上的插值图

(2)效果:

(3)代码

HTML 、CSS:

<head>
    <meta charset="UTF-8" />
    <title>Mapboxgl(canvas) + kriging.js</title>
    <style>
        html,
        body,
        #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <link rel="stylesheet" href="../lib/js/geoglobe/mapbox-gl.css" type="text/css" />
    <script type="text/javascript" src="../lib/js/geoglobe/mapbox-gl.js"></script>
    <script type="text/javascript" src="../lib/js/turf/turf_new.min.js"></script>
    <script type="text/javascript" src="../lib/js/interpolation/kriging_noModule.js"></script>
    <!-- 行政区划数据 (为了偷懒使用了js的形式) -->
    <script src="./data/wuhanShi.js"></script>
    <body>
        <!-- 用于绘制插值图的canvas -->
        <canvas id="canvasMap" style="display: none; opacity: 0.2"></canvas>
        <div id="map"></div>
        <script src="./js/mapboxKriging.js"></script>
    </body>
</head>

完整 JS:


// 颜色范围 (自定义)
const colors = [
    'rgba(0,0,0,0)',
    'rgb( 82 , 184 , 70 )',
    'rgb(90,187,68)',
    'rgb(98,189,66)',
    'rgb(106,192,63)',
    'rgb(114,194,61)',
    'rgb(122,197,59)',
    'rgb(130,199,57)',
    'rgb(138,202,55)',
    'rgb(146,204,52)',
    'rgb(154,207,50)',
    'rgb(162,209,48)',
    'rgb(171,212,46)',
    'rgb(179,215,44)',
    'rgb(187,217,41)',
    'rgb(195,220,39)',
    'rgb(203,222,37)',
    'rgb(211,225,35)',
    'rgb(219,227,33)',
    'rgb(227,230,30)',
    'rgb(235,232,28)',
    'rgb( 243 , 235 , 26 )',
    'rgb(243,230,26)',
    'rgb(243,224,27)',
    'rgb(243,219,27)',
    'rgb(244,213,28)',
    'rgb(244,208,28)',
    'rgb(244,203,29)',
    'rgb(244,197,29)',
    'rgb(244,192,30)',
    'rgb(244,186,30)',
    'rgb(244,181,30)',
    'rgb(245,176,31)',
    'rgb(245,170,31)',
    'rgb(245,165,32)',
    'rgb(245,159,32)',
    'rgb(245,154,33)',
    'rgb(245,149,33)',
    'rgb(246,143,34)',
    'rgb(246,138,34)',
    'rgb(246,132,35)',
];

let canvasImg, // 用于插值的画布
    map, // 地图实例
    points, // 插值点 通过随机数产生;
    range; // 插值范围

// 插值范围 外边界
// 可以使用 turf.js 库,获取行政区划的bbox,即为外边界
let xlim = [113.70228083999996, 115.08257304000006];
let ylim = [29.96907695999994, 31.36125996000004];

// 用于将canvas导出的图片放置在地图上合适位置
let coordinates = [
    [xlim[0], ylim[1]],
    [xlim[0], ylim[0]],
    [xlim[1], ylim[0]],
    [xlim[1], ylim[1]],
];

// 地图初始化
function init() {
    map = new mapboxgl.Map({
        container: 'map',
        style: {
            version: 8,
            sources: {
                cartodb: {
                    tiles: ['http://b.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png'],
                    tileSize: 256,
                    type: 'raster',
                },
            },
            layers: [
                {
                    id: 'cartodb',
                    type: 'raster',
                    source: 'cartodb',
                },
            ],
        },
        center: [114.44515001943142, 30.649477958235423],
        zoom: 8.3,
        pitch: 0,
    });
    // 地图加载
    map.on('load', () => {
        createPoints();
        addStateLayer();
        cavasLayer();
    });
}
// 添加边界图层
function addStateLayer() {
    let wuhanFeatures = [];
    wuhanShi.features.forEach((element) => {
        wuhanFeatures.push({
            type: 'Feature',
            properties: element.attributes,
            geometry: {
                type: 'Polygon',
                coordinates: element.geometry.rings,
            },
        });
    });
    map.addSource('wuhan', {
        type: 'geojson',
        data: {
            type: 'FeatureCollection',
            features: wuhanFeatures,
        },
    });
    map.addLayer({
        id: 'wuhan',
        source: 'wuhan',
        type: 'line',
        paint: {
            'line-color': 'black',
            'line-width': 2,
        },
    });

    //  插值范围
    range = wuhanFeatures[0].geometry.coordinates;
}
// 创建用于插值的随机数据点
function createPoints() {
    var randomPoints = turf.randomPoint(25, {
        bbox: [113.70228083999996, 29.96907695999994, 115.08257304000006, 31.36125996000004],
    });
    randomPoints.features.forEach((item, index) => {
        item.properties = {
            z: Math.round(Math.random() * 100),
            id: index,
        };
    });
    // console.log(randomPoints); // 打印randomPoints查看插值点数据
    // 插值点图层
    map.addSource('point', {
        type: 'geojson',
        data: randomPoints,
    });
    map.addLayer({
        id: 'point',
        source: 'point',
        type: 'circle',
        paint: {
            'circle-color': 'black',
        },
    });

    // 插值点数据
    points = randomPoints.features;
}
//进行克里金插值
function loadkriging() {
    var canvas = document.getElementById('canvasMap');
    canvas.width = 1000;
    canvas.height = 1000;
    var n = points.length;
    var t = []; // 数值
    var x = []; // 经度
    var y = []; // 纬度
    for (var i = 0; i < n; i++) {
        t.push(points[i].properties.z);
        x.push(points[i].geometry.coordinates[0]);
        y.push(points[i].geometry.coordinates[1]);
    }
    //对数据集进行训练
    var variogram = kriging.train(t, x, y, 'exponential', 0, 100);

    //使用variogram对象使polygons描述的地理位置内的格网元素具备不一样的预测值,最后一个参数,是插值格点精度大小
    var grid = kriging.grid(range, variogram, (ylim[1] - ylim[0]) / 250);

    //将得到的格网grid渲染至canvas上
    kriging.plot(canvas, grid, [xlim[0], xlim[1]], [ylim[0], ylim[1]], colors);

    // 将插值结果进行处理,转换为图片格式以便作为图层接入mapboxgl地图中
    return drawImage(0, 0, 0.5);
}
// canvas图片处理
function drawImage(x, y, alpha) {
    // 获取canvas元素对应的DOM对象
    var canvas = document.getElementById('canvasMap');
    // 获取在canvas上绘图的CanvasRenderingContext2D对象
    var ctx = canvas.getContext('2d');
    // 绘制图片
    // ctx.drawImage(image, x, y);
    // 获取从x、y开始,宽为image.width、高为image.height的图片数据
    // 也就是获取绘制的图片数据
    var imgData = ctx.getImageData(x, y, canvas.width, canvas.height);
    for (var i = 0, len = imgData.data.length; i < len; i += 4) {
        // 改变每个像素的透明度
        imgData.data[i + 3] = imgData.data[i + 3] * alpha;
    }
    // 将获取的图片数据放回去。
    ctx.putImageData(imgData, x, y);
    return canvas.toDataURL('image/png');
}

// 添加一个raster图层到地图中,使用的数据源是canvas转换为的图片形式(插值结果)
function cavasLayer() {
    map.addSource('kriging', {
        type: 'image',
        url: loadkriging(),
        coordinates: [coordinates[0], coordinates[3], coordinates[2], coordinates[1]],
    });
    map.addLayer({
        id: 'kriging',
        type: 'raster',
        source: 'kriging',
        paint: {
            'raster-opacity': 1,
        },
    });
}


init();

我觉得应该不能再详细了...

(4)还存在的问题:目前够用。如有问题请联系我改正!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值