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,
    });
相关推荐
GISBox2 天前
PostGIS数据通过GISBox发布WFS/WMS全攻略
数据库·postgresql·wms·gis·postgis·矢量·gisbox
NULIWEIMENXIANG2 天前
ArcPy 程序调用 QGIS 进程实现几何拓扑检查
python·arcgis·gis
我才是银古3 天前
为什么要做 GeoPipeAgent
gis·ai平台
夜郎king4 天前
耒阳童车产业园POI实证分析——基于高德地图,还原“百亿园区”真实面貌
大数据·人工智能·gis·空间分析
ct9785 天前
Cesium的时间与时钟系统
gis·webgl·cesium
奔跑的呱呱牛8 天前
GeoJSON 在大数据场景下为什么不够用?替代方案分析
java·大数据·servlet·gis·geojson
奔跑的呱呱牛8 天前
GeoJSON vs TopoJSON:不仅是体积差异,而是数据模型的差异
gis·geojson·topojson
GISBox9 天前
技术干货:3DTiles转OSGB的适用场景及标准操作流程
gis·数据修复·3dtiles·osgb·gisbox·切片转换·反切
qq_2837200511 天前
Cesium实战(三):加载天地图(影像图,注记图)避坑指南
json·gis·cesium
GISBox11 天前
OSGB与3DTiles格式转换技术指南:从原理到实践
gis·cesium·倾斜摄影·3dtiles·osgb·gisbox·切片转换