vue前端等值线开发

    前端开发过程中会有各种的图表效果,今天讲一下等值线,首先我使用的是克里斯金这个插kriging.js,
还有就是turf.js插件。上代码安装完插件之后引入
import * as Cesium from 'cesium'
// import kriging from '@sakitam-gis/kriging';
import * as turf from '@turf/turf'
const lineGeoJson = turf.lineString(list)
    // 缓冲距离(单位:米)
    const bufferDistance = 25

    // 使用Turf库的缓冲函数进行线的缓冲
    const bufferedLine = turf.buffer(lineGeoJson, bufferDistance, {
      units: 'meters'
    })
    const res: any = [[]]
    const resa: any = []
    bufferedLine.geometry.coordinates[0].forEach((element) => {
      res[0].push([element[0], element[1]])
      resa.push(element[0])
      resa.push(element[1])
    })

    const len = res[0].length - 1
    if (res[0][len] != undefined) {
      res[0].push(res[0][len])
    }

    // console.log("res", res);
    this.extent = Cesium.PolygonGeometry.computeRectangle({
      polygonHierarchy: new Cesium.PolygonHierarchy(
        Cesium.Cartesian3.fromDegreesArray(resa)
      )
    });

这里的turf.buffer方法是可以把传入的点生成一个缓冲区 这样的话传入的数据生成的画面不至于太纤细,具体效果可以看,缓冲区

let canvasViewer: any = null
    canvasViewer = document.createElement('canvas');
    canvasViewer.width = this.IsolineWidth;
    canvasViewer.height = this.IsolineHeight;
    canvasViewer.getContext('2d').globalAlpha = 1;//设置透明度
    const n = list.length;
    const value: any = [];
    const lngs: any = [];
    const lats: any = [];
    for (let i = 0; i < n; i++) {
      // 高度值
      const r = Number(Math.random() / 100);
      value.push(list[i][2] + r);
      // 经纬度点
      lngs.push(list[i][0]);// 经度
      lats.push(list[i][1]); // 纬度
    }
    const colors = [
     {min:10,max:20,color: '#f1b079'},
     {min:20,max:40,color: '#f1b079'}
    ...
      ];
    // console.log('value', value);
    // console.log('lngs', lngs);
    // console.log('lats', lats);
    const minlng: any = Cesium.Math.toDegrees(this.extent.west);//转换为经纬度
    const minlat: any = Cesium.Math.toDegrees(this.extent.south);
    const maxlng: any = Cesium.Math.toDegrees(this.extent.east);
    const maxlat: any = Cesium.Math.toDegrees(this.extent.north);
    const variogram = kriging.train(value, lngs, lats, "exponential", 0, 200);
    const grid = kriging.grid(res, variogram, (maxlat - minlat) / 500);
    //将得到的格网grid渲染至canvas上。
    kriging.plot(canvasViewer, grid, [minlng, maxlng], [minlat, maxlat], colors);

以上是用插件把生成效果添加到,canvas画布上 然后把生成的画布添加到cesium上去

this.viewer.entities.add({
      id: "isolineView",
      polygon: {
        show: true,
        // clampToGround: true,
        hierarchy: new Cesium.CallbackProperty(function () {//回调函数实现叠加的多边形画面随数据变化而动态变化,直接赋值的话显示会闪烁
          return {
            positions: Cesium.Cartesian3.fromDegreesArray(coords_data)
          }
        }, false),
        material: new Cesium.ImageMaterialProperty({//填充多边形的材质的属性
          image: canvas,//使用贴图的方式将结果贴到面上
          transparent: true,
          color: new Cesium.Color(1.0, 1.0, 1.0, 0.65),
        })
      }
    })

添加完等值线图之后把区域线条也添加上去就完事了

 const pointGrid = this.toGeometry(grid.targetArr)

      const lines = turf.isolines(pointGrid, breaks, { zProperty: 'temperature' })
      const pointArrs = this.poinspips(lines, res)
      // Cesium.GeoJonDataSource.clampToGround = false
      Cesium.GeoJsonDataSource.load(pointArrs, {
        clampToGround: true,
        stroke: new Cesium.Color(255, 250, 250, 1),
        strokeWidth: 0.75,
      }).then((dataSource) => {
        if (this.viewer.dataSources.getByName('geojson_map')) {
          this.viewer.dataSources.remove(this.viewer.dataSources.getByName('geojson_map')[0])
        }
        // 添加 geojson
        this.viewer.dataSources.add(dataSource);
        // 给定义好的 geojson 的 name 赋值(这里的 dataSource 就是定义好的geojson)
        dataSource.name = "geojson_map";
      })

/* 设置格式 */
  public toGeometry(stationData) {
    const dataset: any = {
      "type": "FeatureCollection",
      "features": []
    };
    for (let i = 0; i < stationData.length; i++) {
      const geom = {
        "type": "Point",
        "coordinates": [stationData[i][0], stationData[i][1]]
      };
      dataset.features.push({
        "type": "Feature",
        "properties": {
          "temperature": stationData[i][2],
        },
        "geometry": geom
      });
    }
    return dataset;
  }

}

当然了里面还有turf.isolines处理过后的geojson数据这是为了cesium加载数据方便,下面是数据的格式,根据具体需求去处理

  pointss: [
        [114.33082, 22.80038, 21.52160168],
        [114.3308447, 22.80004, 30.90271926],
        [114.3308367, 22.79961, 140.4738089],
        [114.3308033, 22.79927, 300.1216358],
        [114.3307886, 22.79887, 39.76725519],
        [114.3307744, 22.79857, 89.51673284],
        ...
        ]

数组里面前面是经纬度 后面是具体的数据值,也可以根据具体的颜色范围设置自己的颜色值区间,这样的话需要修改kriging.js赋值方式,这样的话就不能通过npm安装插件了,需要手动下载kriging.js放到静态文件里面引入下面是kriging.js源码修改,turf.isolines方法可以看看

kriging.plot = function (canvas, grid, xlim, ylim, colors, idx) {
    // Clear screen
    var ctx = canvas.getContext("2d");
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Starting boundaries
    var range = [xlim[1] - xlim[0], ylim[1] - ylim[0], grid.zlim[1] - grid.zlim[0]];
    var i, j, x, y, z;
    var n = grid.length;
    var m = grid[0].length;
    var wx = Math.ceil(grid.width * canvas.width / (xlim[1] - xlim[0]));
    var wy = Math.ceil(grid.width * canvas.height / (ylim[1] - ylim[0]));
    for (i = 0; i < n; i++)
      for (j = 0; j < m; j++) {
        if (grid[i][j] == undefined) continue;
        x = canvas.width * (i * grid.width + grid.xlim[0] - xlim[0]) / range[0];
        y = canvas.height * (1 - (j * grid.width + grid.ylim[0] - ylim[0]) / range[1]);
        z = (grid[i][j] - grid.zlim[0]) / range[2];
        if (z < 0.0) z = 0.0;
        if (z > 1.0) z = 1.0;
        zs = grid[i][j]
        // ctx.fillStyle = colors[Math.floor((colors.length - 1) * z)];
        ctx.fillStyle = colors[getaidx(zs, idx)];//这个方法做了修改
        // ctx.fillStyle = colors[Math.floor((colors.length - 1) * z)];
        ctx.fillRect(Math.round(x - wx / 2), Math.round(y - wy / 2), wx, wy);
      }

  };
  getaidx = function (v, d) {//这个方法做了修改
    for (let i = 0; i < d.length; i++)
      if (v <= d[i]) {
        return i;//根据值来选定颜色索引号,小于等于
      }
    return d.length;
  }

最后效果看下在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值