1. 程式人生 > >前端OpenLayers實現陰影效果(canvas繪製)

前端OpenLayers實現陰影效果(canvas繪製)

以往通過前端繪製的方式實現向量地圖的視覺化,往往是使用ArcGIS的前端API,底層是通過svg的方式實現,優點,是可以使用svg的濾鏡,css3等方式實現比較絢麗的地圖視覺化效果,比如,陰影,動畫等,svg的內建filter很多很方便,缺點是使用svg的filter可能導致渲染速度變慢,如果是比較多的向量點,可能導致效率低下,最近嘗試使用canvas的方式是否也能實現類似效果,我所選擇的前端API是OpenLayers4.6版本,底層只能是canvas或webgl,預設是canvas渲染,openLayers3以後的版本,已經放棄了低效的svg繪圖,轉為canvas,以前總覺得用canvas會很麻煩,濾鏡的效果可能無法實現,或者實現起來很費勁,介面可能沒有開放出來,通過這次的嘗試,發現canvas也不是想象中的那麼難用。

 下面舉例說明,向量地圖載入,選中,高亮的要素,需要實現浮動的效果,svg的實現思路就是設定要素g的filter為

url('#shadow'),svg的濾鏡很好實現,下面是程式碼:

<filter id="blurMe1">
    <feColorMatrix in="SourceAlpha" result="matrixOut" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"/>
  <feGaussianBlur in="matrixOut" stdDeviation="5" our="blurOut"/>
    <feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
 </filter>
然後是使用該濾鏡的svg要數
<circle cx="280" cy="60" r="50" fill="green"
          filter="url(#blurMe1)" />
實現的效果,就是原始圖增加高斯模糊濾鏡,然後,上面疊加原始圖,進行融合




圖一是原始圖,圖二隻有高斯模糊濾鏡,圖三是想要的浮動效果,組合而成,其實就是陰影效果啊

下面想要達到的效果


openlayers的實現思路就是,高亮的要數放到單獨一個圖層裡面,然後設定該圖層的陰影效果,這樣不會影響其他層的

渲染

 addHighlightLayer(mapObj, layer) {
        if (layer) {
            mapObj.removeLayer(layer);
        }
        layer = new Vector({
            source: new SourceVector(),
            style: () => {
                const fill = new Fill({
                    color: 'raba(0,0,0,1)'
                });
                const style = new Style({
                    // fill:fill,
                    fill: fill,
                    stroke: new Stroke({
                        color: 'rgba(255, 255, 255, 1)',
                        width: 1
                    })
                });
                // fill.setColor(pattern);
                return style;
            }
        });
        mapObj.addLayer(layer);
        this.onBindLayerClick(layer);
        return layer;
    }

    onBindLayerClick(layer) {
        layer.on('precompose', evt => {
            evt.context.shadowBlur = 25;
            evt.context.shadowColor = 'black';
        });
        layer.on('postcompose', evt => {
            evt.context.shadowBlur = 0;
            evt.context.shadowColor = 'black';
        });
    }
然後就是高亮的時候,新增一個要素,有一點需要注意的是,需要動態設定高亮圖層的樣式為選中要數的原來樣式,主要是填充顏色
                        map.highlightLayer.setStyle(
                            () => {
                                return new Style({
                                    fill: new Fill({ color: (f.style && f.style.getFill) ? f.style.getFill().getColor() : '#aaa' }),
                                    stroke: new Stroke({ color: 'rgba(255, 255, 255, 0.2)', width: 2 })
                                });
                            }
                        );
                        map.highlightLayer.getSource().addFeature(f);

總結:

動態設定樣式的時候,只能是函式返回值方式,如果直接指定style物件,總報錯。總體來說,實現效果很好,繪圖速度很快,尤其在移動端瀏覽器依然可以通用,使用ArcGIS js API在啟動的時候載入的資原始檔比較大,大概2M,尤其在移動端,網速慢

情況下影響很大顯示的很慢,改用openlayers實現就很快了,資原始檔很小,可以動態打包進去,或者可以使用Leaflet實現,

Leaflet預設也是svg實現的。