歡迎您光臨本站 註冊首頁

基於leaflet.js實現修改地圖主題樣式的流程分析

←手機掃碼閱讀     kyec555 @ 2020-06-10 , reply:0

今天遇到了一點點的小情況,我自己根據leaflet.js做了一個離線地圖,公司要用來做態勢,但是地圖的底圖用的是高德的原圖,樣式是下面這樣的:

在這裡插入圖片描述

但是態勢的主題是如下的這種淡藍色:

在這裡插入圖片描述

這就造成了本次的需求,需要可以修改樣式的主題,由於本人是個後端小佬,前端菜雞,所以實現起來發生了一些困難,這裡簡單介紹下實現的路程。
 首先看下效果:

在這裡插入圖片描述

然後介紹下艱辛的過程:
 首先,需要用到一個基於leaflet.js的插件:
 https://github.com/hnrchrdl/leaflet-tilelayer-colorizr
 但是在使用這個插件的時候出現了一些問題,這裡不贅述了,大致就是我加載的地圖瓦片是其他的服務器,但是這個插件似乎不能支持跨域,廢了很大的心思我終於解決了這個問題。
 這裡我先提供解決的方式:

  /*   * L.TileLayer.Colorizr is a regular tilelayer with mapped colors.   */  (function () {   // L.TileLayer.Colorizr =    var Colorizr = L.TileLayer.extend({    initialize: function (url, options) {     options = L.extend({}, L.TileLayer.prototype.options, {      colorize: function (pixel) {       return pixel;      },      crossOrigin: 'Anonymous'     }, options);     L.TileLayer.prototype.initialize.call(this, url, options);     L.setOptions(this, options);     this.setColorizr(this.options.colorize);     this.on('tileload', function (e) {      this._colorize(e.tile);     });    },    setColorizr: function (colorizrFactory) {     if (!colorizrFactory || typeof colorizrFactory !== 'function') {      throw 'The colorize option should be a function and return an object with at least one of "r", "g", "b", or "a" properties. Got:' +      typeof colorizrFactory;     } else {      this.options.colorize = colorizrFactory;     }     this.redraw(false);    },    _createTile: function () {     var tile = L.TileLayer.prototype._createTile.call(this);     tile.crossOrigin = "Anonymous";     return tile;    },    _colorize: function (img) {     if (img.getAttribute('data-colorized')) {      img.hidden = false;      return;     }else {      img.hidden = true;     }     var _img = img;     var img = new Image();     img.crossOrigin = 'Anonymous';     img.src = _img.src;     var _this = this;     img.onload = function () {      var canvas = document.createElement("canvas");      canvas.width = img.width;      canvas.height = img.height;      var ctx = canvas.getContext("2d");      ctx.drawImage(img, 0, 0);      var imgd = ctx.getImageData(0, 0, canvas.width, canvas.height);      var pix = imgd.data;      for (var i = 0, n = pix.length; i < n; i += 4) {       var pixel = _this.options.colorize({r: pix[i], g: pix[i + 1], b: pix[i + 2], a: pix[i + 3]});       if (!!!pixel || pixel !== Object(pixel) || Object.prototype.toString.call(pixel) === '[object Array]') {        if (i === 0) {         throw 'The colorize option should return an object with at least one of "r", "g", "b", or "a" properties.';        }       } else {        if (pixel.hasOwnProperty('r') && typeof pixel.r === 'number') {         pix[i] = pixel.r;        }        if (pixel.hasOwnProperty('g')) {         pix[i + 1] = pixel.g;        }        if (pixel.hasOwnProperty('b')) {         pix[i + 2] = pixel.b;        }        if (pixel.hasOwnProperty('a')) {         pix[i + 3] = pixel.a;        }       }      }      ctx.putImageData(imgd, 0, 0);      _img.setAttribute('data-colorized', true);      _img.src = canvas.toDataURL();     };    }   });   (function (factory, window) {    // define an AMD module that relies on 'leaflet'    if (typeof define === 'function' && define.amd) {     define(['leaflet'], factory);     // define a Common JS module that relies on 'leaflet'    } else if (typeof exports === 'object') {     module.exports = factory(require('leaflet'));    }    // attach your plugin to the global 'L' variable    if (typeof window !== 'undefined' && window.L) {     window.L.tileLayer.colorizr = factory(L);    }   }(function (L) {    return function (url, options) {     return new Colorizr(url, options);    };   }, window));  })()

 

 

用上面的代碼直接頂替掉下面這個js插件中的所有代碼

在這裡插入圖片描述

以下是使用的方式:

   var map = L.map("map", {    center: [34.694, 113.587],    renderer: L.svg(),    zoom: 16,    zoomControl: false, // + -號放大縮小    attributionControl: false // 右下角leaflet.js圖標   });   // http://192.168.0.105:9090/img/{z}/{x}/{y}.png // 這個是瓦片地圖的地址   L.tileLayer.colorizr("http://localhost:9090/img/{z}/{x}/{y}.png", {    maxZoom: 18,    minZoom: 3,    colorize: function (pixel) {     // 這個方法用來調整所有的圖片上的rgb值,pixel是圖片原有的rgb值     pixel.r += 13;     pixel.g += 17;     pixel.b += 90;     return pixel;    }   }).addTo(map);

 

需要注意的是,可以配合著給圖片加濾鏡來做:

  .leaflet-zoom-animated img {     -webkit-filter: invert(50%) grayscale(0) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(10%) !important;     -ms-filter: invert(1) grayscale(0) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(10%) !important;     -moz-filter: invert(1) grayscale(0) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(10%) !important;     filter: invert(1) grayscale(0) saturate(0.5) brightness(1.6) opacity(1) hue-rotate(334deg) sepia(1%) !important;    }

 

通過修改colorize的返回值就可以實現修改地圖的樣式了。
 總結下實現思路: 這種方法主要是通過攔截地圖瓦片數據,然後通過canvas(本人後端,不是太懂,反正這東西能操作圖片)操作圖片來修改圖片的rgb值,從而達到修改地圖樣式的目的。
 最後,感謝下友好的國際友人(雖然沒能幫到我),嘻嘻。
 可以看看我們有趣的聊天記錄

最後的最後,給大家附上一個我自己基於leaflet。js實現的離線地圖服務器(下載與部署一體)

                                                   

   


[kyec555 ] 基於leaflet.js實現修改地圖主題樣式的流程分析已經有253次圍觀

http://coctec.com/docs/javascript/show-post-237833.html