openlayers中巧用canvas濾鏡,自由切換你的地圖風格

前言

高德地圖、百度地圖等等圖商現在都提供一些自定義地圖風格,用戶可以自己設計地圖樣式,這樣使得地圖使用靈活了很多。
百度地圖個性化編輯平臺
百度地圖個性化

高德地圖自定義地圖
高德地圖自定義

從openlayers3開始,其底層渲染從SVG切換到了canvas,據說渲染效率提高了不少。在canvas上,我們可以實現很多比較炫酷的可視化操作,如之前的空氣質量態勢圖動態風場等等。今天,來分享一個好玩的,通常CSS3濾鏡,改變地圖風格。

1、原理

1、通過地圖的渲染事件,獲取到canvas上下文context;
2、設置context的filter屬性。
3、重新渲染圖層。

  map.on('precompose', function(evt){
      var ctx = evt.context;
      ctx.filter = filter;//設置濾鏡值
  })
  map.render();

filter值類型爲字符串,默認值爲"none";
precompose事件會在地圖渲染前發生,因此在渲染前,改變filter值,即可讓地圖按設置的濾鏡進行渲染。

關於濾鏡的屬性,可以參考菜鳥教程中的《CSS3 filter(濾鏡)》
也可以參考MDN web docs中的《CanvasRenderingContext2D.filter》

2、示例

我們看上一幅原圖:
原圖

1)灰度濾鏡: 設置filter值爲 grayscale(100%)

灰度濾鏡

2)褐色: 設置filter值爲 sepia(100%)

褐色濾鏡

3、複合濾鏡

可以使用多個濾鏡,值之間用空格隔開,如:contrast(150%) saturate(200%)
複合濾鏡

利用複合濾鏡,我們可以更靈活的變換地圖風格,是不是挺好玩,大家可以下來試試。

3、完整代碼

js代碼


var app = {
    baseLayer: undefined,
    map: undefined,
    filter: 'none',
    key: undefined,
    init: function(){
        this.baseLayer = new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
            })
        });

        this.map = new ol.Map({
            target: 'map',
            view: new ol.View({
                projection: 'EPSG:4326',
                center: [118, 36],
                zoom: 7
            }),
            layers: [this.baseLayer]
        });

        this.map.on('precompose', function(evt){
            let ctx = evt.context;
            ctx.filter = this.filter;
        }.bind(this))
    }
}

app.init();


function fs(type){
    switch (type) {
        //反色
        case 'invert':
            type = 'invert' + '(100%)'
            break;
        //褐色
        case 'sepia':
                type = 'sepia' + '(100%)'
                break;
        //灰度
        case 'grayscale':
            type = 'grayscale' + '(100%)'
            break;
        //複合
        case 'complex':
                type = 'contrast(150%) saturate(200%)'
                break;
        //默認
        default:
            type = 'none';
            break;
    }
    app.filter = type;
    app.map.render();
}

html代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://openlayers.org/en/v4.6.5/css/ol.css" type="text/css">
    <title>濾鏡</title>
    <script src="https://openlayers.org/en/v4.6.5/build/ol.js"></script>
    <style>
        head,body, #map{
            height: 100%;
            width: 100%;
            margin: 0%;
            padding: 0%;
        }
        .ol-attribution{
            display: none;
        }
        .ol-zoom{
            display: none;
        }
        .input-group-btn{
            top: 2%;
            left: 1%;
            z-index: 1;
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="app">
        <div id="map"></div>        
        <div class="input-group-btn">
            <button type="button" class="btn btn-default" onclick="fs('invert')">反色</button>
            <button type="button" class="btn btn-default" onclick="fs('sepia')">褐色</button>
            <button type="button" class="btn btn-default" onclick="fs('grayscale')">灰度</button>
            <button type="button" class="btn btn-default" onclick="fs('complex')">複合濾鏡</button>
            <button type="button" class="btn btn-default" onclick="fs('none')">原色</button>
        </div>
    </div>
    <script src="./app.js"></script>
</body>
</html>

4、precompose事件

需要說明的是,precompose事件不僅僅只有map對象有,ol.layer.vector對象也具備這個事件,因此如果需要對圖層進行濾鏡操作,可以試試在layer的precompose事件中進行。
另外,也可以利用渲染事件中的上下文,實現圖層的陰影效果。有興趣嘗試一下吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章