openlayer地图颜色修改

1、需求描述

在地理信息系统中,客户想要不同于原色的地图颜色,让页面看起来更有科技感。本文的目标是对openlayer加载的天地图的颜色进行修改

2、参考文章

(1)blog.csdn.net/linzi199005...

(2)blog.csdn.net/weixin_4495...

3、最终效果

4、实现方式

4.1通过css实现

通过css的filter属性,将模糊或颜色偏移等图形效果应用于元素。

javascript 复制代码
  :deep(.ol-layer) {
   filter: invert(100%) hue-rotate(180deg);

    /* -webkit-filter: invert(100%) hue-rotate(180deg); */
}

使用这种方式能修改地图的颜色,但是需要注意的是,这种实现是对所有的ol-layer都改变的颜色。即,不仅是天地图底图会被修改颜色,所有加载进地图的图层的颜色都会被修改。例如:imageLayer、overLayer等都会受到影响。

4.2 图层加载时修改颜色

4.2.1外部调用实现

使用openlayer的RasterSource,对数据进行转换。RasterSource是使用运算函数将来自任意数量输入源的数据转换为输出像素值的一种源。

颜色转换函数

javascript 复制代码
import ImageLayer from 'ol/layer/Image';
import RasterSource from 'ol/source/Raster';

// 定义颜色转换方法
const reverseFunc = (pixelsTemp: any) => {
  // 蓝色
  for (let i = 0; i < pixelsTemp.length; i += 4) {
    const r = pixelsTemp[i];
    const g = pixelsTemp[i + 1];
    const b = pixelsTemp[i + 2];
    // 设置灰度值
    const grey = r * 0.3 + g * 0.59 + b * 0.11;
    // console.log(grey);
    // 将rgb的值替换为灰度值
    // pixelsTemp[i] = grey;
    // pixelsTemp[i + 1] = grey;
    // pixelsTemp[i + 2] = grey;
    // 基于灰色设置为蓝色
    pixelsTemp[i] = 55 - grey; //R
    pixelsTemp[i + 1] = 255 - grey; //G
    pixelsTemp[i + 2] = 305 - grey; //B
  }
};
//图层颜色转换
const translate = (layerOrigin: any) => {
  const raster = new RasterSource({
    sources: [layerOrigin],
    // 这里设置为img类型,为了优化速度
    operationType: 'image',
    operation: function (pixels: any, _data) {
      // 执行颜色转换方法
      reverseFunc(pixels[0].data);
      return pixels[0];
    },
    // 线程数
    threads: 10,
    lib: {
      // 允许operation使用外部方法
      reverseFunc: reverseFunc,
    },
  });
  // 创建新图层
  const layer = new ImageLayer({
    source: raster,
  });
  return layer;
};
//图层加载
const map=new Map({...})
const layerOrigin=new TileLayer({
  source:new XYZ({
    url: tiandituVecUrl + '&tk=' + tiandituKey,
  })
})
const layer=translate(layerOrigin)
map.addLayer(layer)

使用这个方法,存在不好调整地图颜色问题,我们在reverseFunc中输出我们设置的灰度值。查看灰度值的众数,这个众数就是地图的基本色调计算后的灰度值,然后再根据这个数计算。

注意:使用这个方法可能会出现image跨域的问题。如果遇到请使用4.3的方法。

4.3 内部函数实现

影像地图加载时,通过tileLoadFunction指定瓦片加载的方法。在此方法中对加载的图片进行颜色转换。

javascript 复制代码
const layer = new TileLayer({
      source: new XYZ({
        url: tiandituVecUrl + '&tk=' + tiandituKey,
        // layer: 'img',
        tileLoadFunction: function (imageTile: any, src) {
          const img = new Image();
          img.crossOrigin = '';
          img.onload = function () {
            const canvas = document.createElement('canvas');
            const w = img.width;
            const h = img.height;
            canvas.width = w;
            canvas.height = h;
            const context = canvas.getContext('2d') as any;
            context.drawImage(img, 0, 0, w, h, 0, 0, w, h);
            const imageData = context.getImageData(0, 0, w, h);
            for (let i = 0; i < imageData?.height; i++) {
              for (let j = 0; j < imageData?.width; j++) {
                let x = i * 4 * imageData.width + j * 4;
                //灰度计算
                imageData.data[x] =
                  imageData.data[x + 1] =
                  imageData.data[x + 2] =
                    imageData.data[x] * 0.3 +
                    imageData.data[x + 1] * 0.59 +
                    imageData.data[x + 2] * 0.11;
                    //颜色计算
                imageData.data[x] = 55 - imageData.data[x];
                imageData.data[x + 1] = 255 - imageData.data[x + 1];
                imageData.data[x + 2] = 305 - imageData.data[x + 2];
              }
            }
            context?.putImageData(imageData, 0, 0);
            imageTile.getImage().src = canvas.toDataURL('image/png');
          };
          img.src = src;
        },
      }),
      // Opacity: 1,
      // format: new parseGeoJson(),
      zIndex: -1,
    });

也可以拿出来封装成一个函数

javascript 复制代码
export function tileLoadFunction(imageTile: any, src) {
  const img = new Image();
  img.crossOrigin = '';
  img.onload = function () {
    const canvas = document.createElement('canvas');
    const w = img.width;
    const h = img.height;
    canvas.width = w;
    canvas.height = h;
    const context = canvas.getContext('2d') as any;
    context.drawImage(img, 0, 0, w, h, 0, 0, w, h);
    const imageData = context.getImageData(0, 0, w, h);
    for (let i = 0; i < imageData?.height; i++) {
      for (let j = 0; j < imageData?.width; j++) {
        const x = i * 4 * imageData.width + j * 4;

        imageData.data[x] =
          imageData.data[x + 1] =
          imageData.data[x + 2] =
            imageData.data[x] * 0.3 + imageData.data[x + 1] * 0.59 + imageData.data[x + 2] * 0.11;
        imageData.data[x] = 55 - imageData.data[x];
        imageData.data[x + 1] = 255 - imageData.data[x + 1];
        imageData.data[x + 2] = 305 - imageData.data[x + 2];
      }
    }
    context?.putImageData(imageData, 0, 0);
    imageTile.getImage().src = canvas.toDataURL('image/png');
  };
  img.src = src;
}

const layerOrigin = new TileLayer({
      source: new XYZ({
        url: tiandituVecUrl + '&tk=' + tiandituKey,
        tileLoadFunction: (imageTile, src) => tileLoadFunction(imageTile, src) as any,
      }),
      // Opacity: 1,
      // format: new parseGeoJson(),
      zIndex: -1,
    });
相关推荐
GIS工具-gistools20211 天前
如何在 QGIS 中打开 Esri 文件地理数据库(GDB)
gis·qgis
放逐者-保持本心,方可放逐2 天前
一文了解 gis 相关服务=》及前端地图服务相关总结
前端·wms·gis·wmts·wfs·wcs·ogc
supermapsupport3 天前
iClent3D for Cesium 实现无人机巡检飞行效果
gis·cesium·supermap·webgis
枝上棉蛮4 天前
免费GIS工具箱:轻松将glb文件转换成3DTiles文件
gis·数字孪生·数据格式转换·3dtiles·地理信息系统·glb·gis软件
supermapsupport7 天前
iClient3D for Cesium 实现限高分析
3d·vue·gis·cesium·supermap·webgis
松果猿15 天前
独家攻略!GISer必备:轻松获取GIS数据的实用技巧,赶紧收藏!(二)
gis
moonless022217 天前
【GISer精英计划_00】从二进制到协议、到计算机通信、到服务器
网络协议·gis·计算机组成原理
兔子小姐_20 天前
如何下载Blender插件BlanderGIS
arcgis·gis·blender
安迁岚21 天前
【遥感综合实习】专题一 多时相多波段遥感影像的机器学习地物分类研究
人工智能·机器学习·arcgis·分类·gis
疯狂学习GIS22 天前
全球气象数据ERA5的下载方法
python·gis·rs·学术工作效率·gis数据·遥感数据·气象数据