将数据压缩到图片并在前端做解析渲染

概述

在做前后端数据交互的时候,你一定遇到过这样的问题:数据量大,尤其是在气象行业!在本文,讲解一种将数据压缩到图片并在前端实现数据的解析与展示的功能。

流程

整体操作流程图如下图:

实现的效果

1.前端绘制数据图; 2.移动鼠标展示鼠标所在位置的值; 3.间隔展示数据值;

关键实现

1、获取图片并解析数据

var img = new Image();
img.src = 'css/ws_china.png';
img.onload = function () {
  var canvas = document.createElement('canvas');
  width = img.width;
  height = img.height;
  dx = (geoBounds[2] - geoBounds[0])/width;
  dy = (geoBounds[3] - geoBounds[1])/height;
  canvas.height = height;
  canvas.width = width;
  document.body.appendChild(canvas);
  var ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);
  imgPixels = ctx.getImageData(0, 0, width, height);
  var image = ctx.createImageData(width, height);
  // canvas先绘制行,在绘制列
  for(var j = 0;j<height;j++){
    for(var i = 0;i<width;i++){
      var _ji = (j * 4) * width + i * 4;
      var r = imgPixels.data[_ji], g = imgPixels.data[_ji+1] ,b = imgPixels.data[_ji+2];
      var val = r * 256 + g + b * 0.01;
      val = Number(val.toFixed(2));
      var c = getColor(val);
      image.data[_ji + 0] = parseInt(c[0]);
      image.data[_ji + 1] = parseInt(c[1]);
      image.data[_ji + 2] = parseInt(c[2]);
      image.data[_ji + 3] = val === 0 ? 0 : parseInt(c[3]);
    }
  }
  ctx.putImageData(image, 0, 0);
}

2、前端渲染数据图

用ol里面最简单的方式,staticImage的方式渲染,代码如下:

var imageLayer = new ol.layer.Image({
  source: null,
  opacity: 0.85
});
map.addLayer(imageLayer);
var source = new ol.source.ImageStatic({
  url: canvas.toDataURL("image/png"),
  imageExtent: bounds
});
imageLayer.setSource(source);

3、鼠标移动效果

通过注册map的pointermove事件,结合overlay实现鼠标移动展示鼠标所在位置的值。

var popup = new ol.Overlay({
  element: document.getElementById('popup'),
  position: null,
  positioning: 'center-left',
  offset: [16, 0]
});
map.addOverlay(popup);
map.on('pointermove', function (e) {
  var geoPt = ol.proj.toLonLat(e.coordinate);
  var val = getVal(geoPt);
  if(val) {
    document.getElementById('popup').innerText = val.toFixed(1);
    popup.setPosition(e.coordinate);
  } else  {
    popup.setPosition(null);
  }
});

4、在地图上渲染值

在地图上的渲染:1、用vector实现数据的展示;2、按照屏幕位置,做了等间距展示;3、奇偶行数的错行展示。

var textLayer = new ol.layer.Vector({
  source: null,
  opacity: 0.85,
  style: function (feat) {
    var val = feat.get("val");
    if(val) {
      return new ol.style.Style({
        text: new ol.style.Text({
          font: 'normal 14px 黑体',
          text: val.toFixed(1),
          fill: new ol.style.Fill({
            color: '#ff0000'
          }),
          stroke: new ol.style.Stroke({
            color: '#ffff',
            width: 2
          })
        })
      })
    } else {
      return null;
    }
    
  }
});
map.addLayer(textLayer);
var _source = new ol.source.Vector({
  features: []
});
textLayer.setSource(_source);
map.on("moveend", function () {
  _source.clear();
    var extent = map.getView().calculateExtent();
    var geoExtent = ol.proj.transformExtent(extent, 'EPSG:3857', 'EPSG:4326');
    var lonmin, lonmax, latmin, latmax;
    lonmin = geoExtent[0] > geoBounds[0] ? geoExtent[0] : geoBounds[0];
    latmin = geoExtent[1] < geoBounds[1] ? geoExtent[1] : geoBounds[1];
    lonmax = geoExtent[2] > geoBounds[2] ? geoExtent[2] : geoBounds[2];
    latmax = geoExtent[3] < geoBounds[3] ? geoExtent[3] : geoBounds[3];
    var topLeft = [lonmin, latmax];
    var topLeft3857 = ol.proj.fromLonLat(topLeft);
    var topLeftPixel = map.getPixelFromCoordinate(topLeft3857);
    var topLeftSetPixel = [topLeftPixel[0] + intervalPixel, topLeftPixel[1]];
    var topLeftSet3857 = map.getCoordinateFromPixel(topLeftSetPixel);
    var topLeftSet = ol.proj.toLonLat(topLeftSet3857);
    var intervalDegree = topLeftSet[0] - topLeft[0];
    var nx = Math.floor((lonmax - lonmin) / intervalDegree),
      ny = Math.floor((latmax - latmin) / intervalDegree * 2);
    var _features = [];
    // y是固定的,x根据奇偶行变换
    for(var i = 0;i<=ny;i++) {
      var lat = latmax - i * intervalDegree / 2;
      var lonAdd = i%2 !==0 ? intervalDegree / 2 : 0;
      for(var j=0;j<=nx;j++) {
        var lon = lonmin + j * intervalDegree;
        lon = lon + lonAdd ;
        var lonLat = [lon + dx/2, lat + dy/2];
        var coord = ol.proj.fromLonLat(lonLat);
        if(ol.extent.containsCoordinate(extent, coord)) {
          var val = getVal(lonLat);
          _features.push(new ol.Feature({
            geometry: new ol.geom.Point(coord),
            val: val
          }));
        }
      }
    }
    _source.addFeatures(_features);
});

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券