日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

行政区划遮罩 -mapbox

發布時間:2023/12/13 综合教程 41 生活家
生活随笔 收集整理的這篇文章主要介紹了 行政区划遮罩 -mapbox 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用mapboxgl 實現特定的地圖效果

最近完成的一個項目,dashboard 地圖模塊的需要和第三方對接,對接要求使用mapboxgl 來對接。以前的項目一直用leaflet庫來處理地圖需求,mapboxgl 庫對我來說很陌生。學習研究一段時間,在基本實現了產品設計的地圖交互功能后,我在這里寫記錄。
先上張設計效果圖:

一、要求實現的功能

1.加載深圳地圖瓦片、顏色采用暗色調。
2.地圖附有藍色遮罩層,鼠標hover時 ,該區域高亮并展示相應的數據。
3. 攝像頭點位在地圖上顯示,兩種類型,一個綠色一個藍色,要求有聚合功能并根據攝像頭類型和數量來決定icon在地圖上顯示綠色或者藍色。

二、代碼實現

mapboxgl底層是使用h5 的canvas 技術,這就決定了里面所有的鼠標事件都是根據鼠標的(x,y)坐標來觸發。同時也可以解析為什么地圖頁面被tranform拉伸(css3 樣式) 后, mapboxgl 的事件觸發會失靈的原因。

2.1.加載深圳地圖瓦片、顏色采用暗色調

2.1.1 加載深圳地圖瓦片(矢量地圖),地圖背景設置成圖紙規定的顏色

const mapStyle = 'xxxxx'; // 地圖的樣式配置,里面有一些地圖的基本信息和地圖一些圖層layers設置
var map = new mapboxgl.Map({
   
     
     
          container: 'map', // container id
          style: mapStyle ,
          center: [114.185125079355, 22.6322002129776], // starting position
          zoom: 10,
          attributionControl: false
      });

瓦片采用暗色調,如果mapStyle(文件具體格式參照mapboxgl官網:https://docs.mapbox.com/help/glossary/style/) 提供的地圖瓦片(矢量地圖瓦片)不是自己想要的色調,那就需要用代碼修改mapStyle里面的配置。
改地圖的一些屬性前,第一要解決的問題就是:我怎么知道地圖里面有哪些配置,哪些layers?
1.可以查看瀏覽器的network的接口抓包 。
2. 用console.log(map)打印地圖對象。
下面截圖來自mapboxgl 官網和supermap 官網例子:


地圖的所有信息都會寫入到map 對象里面,_layers里面記錄了所有覆蓋在地圖上面的圖層,里面是一個對象集合,每個對象里面都有layer 的id 、type、layout 、paint 等屬性。跟photoshop 一樣,canvas 繪制的地圖就是一層一層的圖層疊加起來的圖片,每一層圖層都有自己的一些設計,每個圖層都有自己指定的圖層序號(id)。要修改某個圖層只需要知道layer id 就行。
supermap地圖的第一層一般都是background 圖層,backgound 規定了地圖的背景顏色和透明度。上面的效果圖地圖的背景色是指定顏色的。mapboxgl 提供了 map.getLayers() 、 map.removeLayer()、map.addLayers() 、map.setPaintProperty()等api。supermap官網提供的地圖有background 這層layer,我這里只需要修改這一層圖層的顏色就行。

map.on('load',function(){
   
     
     
  map.setPaintProperty('background', 'background-color', '#45516E');
})

2.1.2 修改地圖其他圖層的覆蓋物顏色

supermap 提供的地圖瓦片是白色瓦片,和UI設計不符。解決的方法有兩個,一要求supermap 直接提供深色主題的地圖瓦片,二前端自己處理,在地圖加載完成后切換瓦片的顏色。
layer 里面的 type 是說明當前圖層的類型。
type分為:
fill: 類似于canvas 里的fill,在給定的經緯度區域內填充內容
line: 沿著經緯度點畫線
symbol: 圖標或者label
circle: 在指定點位上畫圓形
heatmap:熱力圖

從type 上分析,地圖最顯眼圖層塊應該是type 為fill 和line 類型的layer。要切換地圖主題顏色,這就需要考慮這兩種類型。主要修改它們的fill-color 和line-color 屬性,同時還要考慮顏色層次和地形的區分,比如綠地、水系 、高速路、省道等不同覆蓋物使用不同的顏色或者不同的透明度。具體需要修改哪些layers,我們可以先研究下map 里面的layers ,再挑一些比較顯眼的瓦片layer 修改。

map.setPaintProperty('background', 'background-color', '#45516E');
  	// 獲取地圖上所有的layers,因為是遍歷object 對象,可以用object.keys來遍歷
    Object.keys(map.style._layers).map(v=>{
   
     
     
    	const opt = map.style._layers[v]; 
        // 修改綠地、水系的瓦片顏色
        if((opt.id.includes('綠地')||opt.id.includes('水系')) && opt.type=='fill'){
   
     
     
          map.setPaintProperty(opt.id, 'fill-color', '#182c4e');
        }
        // 修改道路的顏色
        if((opt.id.includes('高速')||opt.id.includes('國道')||opt.id.includes('省道')) && opt.type=='line'){
   
     
     
          map.setPaintProperty(opt.id, 'line-color', '#182c4f');
        }
      })

2.2 地圖藍色遮罩層,地區邊界線亮色顯示,在藍色遮罩層上添加區域名稱

2.2.1 地圖藍色遮罩層,地區邊界線亮色顯示

如果地圖有按照地區邊界區分的layer,可以考慮直接修改或者復制一個圖層疊在地圖最上端,這個方案是最簡單明了的。通常情況下和第三方對接,對方提供的東西很可能性不能完全滿足己方的需要。再對接后我獲取到的地圖layers 并沒有這樣一個圖層。這種情況該怎么處理?最優方案是反推對方,要求對方提供對應的文件。次選方案從網上搜索一個深圳相關的geoJson文件,然后加載到地圖上層。開發項目的時候,我同時執行了兩種方案。但最終只能使用此選方案。地圖體系不同,地圖邊界線的經緯度就有些偏差,網上下載的geoJson 加載到地圖上,放大后可以看出邊緣有一些部分不太重合,同時geoJson 圖層整體都有些偏移。這些都需要在地圖加載前做同樣的經緯度偏差處理。

var sourceName = 'blueMask'; // 資源名稱,自定義
      map.addSource(sourceName, {
   
     
     
      type: 'geojson', 
      data: geoJson, // 網上下載的geoJson的地圖文件,使用前經過偏差算法處理
    });
   // 藍色遮罩層顏色設定,透明度通過feature-state 的值的情況來設定顏色透明度
    map.addLayer({
   
     
     
      id: 'addlayermask',
      type: 'fill',
      source: sourceName,
      layout: {
   
     
     },
      paint: {
   
     
     
        'fill-color': '#286BFF',
        'fill-opacity': ['case', ['boolean', ['feature-state', 'hover'], false], 0.3, 0],
      },
    });
    // 設置地圖區域邊沿的線寬和顏色值
    map.addLayer({
   
     
     
      id: `${
     
       
       sourceName}-line`,
      type: 'line',
      source: sourceName,
      layout: {
   
     
     },
      paint: {
   
     
     
        'line-width': 1.5,
        'line-color': '#286BFF',
      },
    });

2.2.2 鼠標hover ,區域圖層高亮,并彈窗顯示區域的介紹信息:

let hoveredStateId = null;
 let listener1 = function(e) {
   
     
     
    map.getCanvas().style.cursor = 'pointer';// 設定鼠標移入的樣式
    if (e.features.length > 0) {
   
     
     
      if (hoveredStateId) {
   
     
      
        map.setFeatureState({
   
     
      source: sourceName, id: hoveredStateId }, {
   
     
      hover: false });// 先還原成默認狀態
      }
      hoveredStateId = e.features[0].id; // ps:加載的geoJson  feature 里面必須設定一個id 屬性,用于定位哪個區域需要高亮。如果原文件沒有,可以手動在原文件上添加id 屬性并設置對應的id 數字
      map.setFeatureState({
   
     
      source: sourceName, id: hoveredStateId }, {
   
     
      hover: true });
    // 鼠標hover 時 彈窗顯示區域的介紹信息
	popup .setLngLat([lnglat[0], lnglat[1]]) // 彈窗的經緯度位置,可以設成下面區域名稱的經緯度附近坐標
	            .setHTML(
	              `<div class=cameraDes>
	              區域信息介紹
	          </div>`,
	            )
	            .addTo(map);
    }
  };

  map.on('mousemove', 'addlayermask', listener1);
  // 鼠標移出事件,改變hover 的值
  let listener2 = function() {
   
     
     
    map.getCanvas().style.cursor = ''; //改變鼠標樣式
    if (hoveredStateId) {
   
     
     
      map.setFeatureState({
   
     
      source: sourceName, id: hoveredStateId }, {
   
     
      hover: false });
    }
    hoveredStateId = null;// 還原或者情況
  };
  // 鼠標離開時 去掉高亮狀態
   map.on('mouseleave', 'addlayermask', listener2);
     })

2.2.3 在藍色遮罩層上添加區域名稱

/**
 * 增加區域的名稱和區域名字
 * @param map 地圖實例
 * @param markClass  marker 的頁面樣式
 * @param geoJson geoJson 格式的地圖數據
 */

export function addRegionName(map, markClass, geoJson) {
   
     
     
  geoJson.features.forEach((v) => {
   
     
     
    const el = document.createElement('div'); 
    el.className = markClass;
    const t = document.createTextNode(v.properties.name);
    el.appendChild(t);
    new mapboxgl.Marker({
   
     
     
      element: el,// 只支持原生的html 元素
    })
      .setLngLat(v.properties.center)// 使用geoJson 里面的center 屬性來
      .addTo(map);
  });
}

2.3 攝像頭點位在地圖上顯示,兩種類型,一個綠色一個藍色,要求有聚合功能并根據攝像頭類型和數量來決定顯示綠色或者藍色

如果單單只是要實現攝像頭點位的藍綠色圖標,mapboxgl提供了marker 、circle 、canvas 、symbol。這里我直接采用最簡單的circle ,同時也方便后面的cluster 處理。

const sourceName = {
   
     
     
    type: 'FeatureCollection',
    features: [
      {
   
     
     
        type: 'Feature',
        geometry: {
   
     
     
          type: 'Point',     // 攝像頭使用point類型,在地圖上渲染
          coordinates: [0, 0],// 攝像頭的經緯度
        },
        properties: {
   
     
     
          title: 'camera',
          areaType: 1,// 自定義屬性,
        },
      },
    ],
  };
  map.addLayer({
   
     
     
    id: layerId,// 這個id 是自定義的,layerId 是通過函數的參數傳遞進來的
    type: 'circle',
    filter: ['!', ['has', 'point_count']], // 渲染條件,只渲染沒有point_count 屬性的點位。point_count 屬性是聚合cluster 的屬性。這里只渲染非聚合的
    source: sourceName,// sourceName,格式為geoJson,areaType 是自定義的屬性,可以在渲染前把所有的攝像頭點位寫入sourceName 變量里面
    paint: {
   
     
     
      'circle-color': ['case', ['==', ['get', 'areaType'], 1], '#286bff', '#0ebd73'],// 通過areaType 類型判斷攝像頭應該渲染什么顏色。如果 areaType === 1 渲染#286bff,不等就渲染#0ebd73
      'circle-radius': 5, //攝像頭圓圈的半徑,5px
    },
  });

 // Create a popup, 鼠標hover時攝像頭彈窗顯示攝像頭名稱.
  const popup = new mapboxgl.Popup({
   
     
     
    closeButton: false,
    closeOnClick: false,
  });
  map.on('mouseenter', layerId, function(e) {
   
     
     
    isHoverCameraIcon = true;
    // districtPop 是全局變量,這里做了彈窗的一個復位操作
    districtPop !== null && districtPop.remove();
    map.getCanvas().style.cursor = 'pointer';
    const coordinates = e.features[0].geometry.coordinates.slice();
    const description = e.features[0].properties.title; // 攝像頭名稱,屬性是自定義的

    // Ensure that if the map is zoomed out such that multiple
    // copies of the feature are visible, the popup appears
    // over the copy being pointed to.
    while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
   
     
     
      coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
    }

    // Populate the popup and set its coordinates
    // based on the feature found.
    if (description) {
   
     
     
      popup
        .setLngLat(coordinates)
        .setHTML(`<div class=cameraDes>${
     
       
       description}</div>`)// 彈窗的具體內容
        .addTo(map);
    }
  });

  map.on('mouseleave', layerId, function() {
   
     
     
    isHoverCameraIcon = false;
    map.getCanvas().style.cursor = '';
    popup.remove();
  });

2.3.1 攝像頭聚合功能,顏色定義,聚合圖標顯示攝像頭數量等功能

const mag1 = ['==', ['get', 'areaType'], 1];
const mag2 = ['==', ['get', 'areaType'], 2];
//添加聚會的圖層的source
 map.addSource( 'marker_market', {
   
     
     
      type: 'geojson',
      data: sourceName ,// 取上面的geojson 格式的文件
      cluster: true,
      clusterMaxZoom: 12,//允許聚合圖層最大的放大圖層
      clusterRadius: 20,//聚合后的攝像頭圖標半徑
      clusterProperties: {
   
     
     
        mag1: ['+', ['case', mag1, 1, 0]], // 統計聚合點areaType ==1 的數量,累計如果滿足mag1 的條件 ,clusterProperties 的mag1 的值就加1 否則加0
        mag2: ['+', ['case', mag2, 1, 0]], // 統計聚合點areaType ==2 的數量
      },
    });
 // 添加cluster 的 
map.addLayer({
   
     
     
    id: layerId, // layerId 隨便一個字符都行,不和其他layer 重名就好
    type: 'circle',
    filter: ['has', 'point_count'],// 只處理擁有point_count 屬性的的攝像頭點位
    source: sourceName,
    paint: {
   
     
     
      'circle-color': ['case', ['>=', ['get', 'mag1'], ['get', 'mag2']], '#286bff', '#0ebd73'], // 如果cluster 的mag1 屬性大于 mag2 屬性,優先顯示#286bff攝像頭顏色
      'circle-radius': ['step', ['get', 'point_count'], 5, 1, 10, 10, 12],// 聚合攝像頭數量 1個 圓的半徑為5px,1~10 個攝像頭 圓的半徑為10px,10個攝像頭以上,半徑為12px
    },
  });
  // 在聚合cluster圖標中間渲染攝像頭的數量
    map.addLayer({
   
     
     
    id: 'cluster-count',
    type: 'symbol',
    source: sourceName,
    filter: ['has', 'point_count'],
    layout: {
   
     
     
      'text-field': '{point_count_abbreviated}',
      'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
      'text-size': 12,// 規定字體的字號
    },
    paint: {
   
     
     
      'text-color': 'rgba(255,255,255,1)', // 字體顏色
    },
  });

  // 匯聚點擊即后,自動展開匯聚點。官網有這個例子
  map.on('click', layerId, function(e: any) {
   
     
     
    const features = map.queryRenderedFeatures(e.point, {
   
     
     
      layers: [layerId],
    });
    const clusterId = features[0].properties.cluster_id; // features
    if (clusterId) {
   
     
     
      map.getSource(sourceName).getClusterExpansionZoom(clusterId, function(err: any, zoom: any) {
   
     
     
        if (err) return;
        map.easeTo({
   
     
     
          center: features[0].geometry.coordinates,
          zoom: zoom,
        });
      });
    }
  });

如果攝像頭有變動,需要修改layer 的信息,這時有兩種方法。
1.刪除原圖層然后添加新圖層 :map.getLayer(layer) && map.removeLayer(layer)
2. 直接用mapboxgl 提供的api修改layer的屬性: map.getLayer(‘background’) && map.setPaintProperty(‘background’, ‘background-color’, ‘rgba(4,21,37,1)’);

這樣整地圖除底層的地圖瓦片外,其他的效果差不多就已經實現了。

總結

以上是生活随笔為你收集整理的行政区划遮罩 -mapbox的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 蜜臀久久精品久久久久久酒店 | 日本精品人妻无码免费大全 | 伊人成人动漫 | 大乳女喂男人吃奶 | 日韩精品在线观看一区二区 | 成年人91视频 | 亚洲中文字幕无码一区 | 欧美色人阁| www.国产免费 | 久久精品无码一区二区三区毛片 | 激情五月综合色婷婷一区二区 | 91高潮大合集爽到抽搐 | 国内外免费激情视频 | 黄页网站视频在线观看 | ass极品水嫩小美女ass | 成人无码精品1区2区3区免费看 | 午夜资源 | 色资源在线观看 | 欧美一区影院 | 国产精品精品久久久久久 | 成人国产精品久久久网站 | 冲田杏梨 在线 | 亚洲精品乱码久久久久久写真 | 狠狠婷 | 不卡中文字幕在线 | 国产乱淫av免费 | 少妇av一区二区 | 成人精品三级av在线看 | 三级网站在线播放 | 免费毛片视频网站 | 伊人超碰在线 | 成人女同av免费观看 | 8x8x成人| 午夜色av| 视频一区 国产 | 激情网页 | 哺乳期给上司喂奶hd | 大白屁股一区二区视频 | 日本大尺度电影免费观看全集中文版 | 国产一级片免费播放 | 美女国产精品 | 极品熟妇大蝴蝶20p 国产偷自拍视频 | 无码人中文字幕 | 国产夜色视频 | 午夜在线网站 | 可以看毛片的网站 | 影音先锋波多野结衣 | 日本福利视频一区 | 黄色性视频| 在线观看免费av网址 | 激情专区 | av在线资源观看 | 国产伦精品一区二区三区视频女 | 久久香蕉影视 | 超碰777| 精品国产不卡 | 丝袜制服影音先锋 | 国产精品电影网 | 青青草香蕉| 国产黄在线 | 天天干夜夜撸 | 精品xxx| 亚洲一区二区三区在线视频 | 亚洲成人精品一区 | 性的免费视频 | 自拍色图| 国产一区在线视频观看 | 性综艺节目av在线播放 | 中文字字幕一区二区三区四区五区 | 办公室摸腿吻胸激情视频 | 亚洲制服在线观看 | 中文字幕一区二区人妻 | 五月婷婷六月天 | 五十路息子 | 久久国产毛片 | 亚洲av无码乱码国产精品 | 国产精品v亚洲精品v日韩精品 | 午夜精品一区二区三 | 91精选国产 | 欧美日韩中文字幕一区二区 | 91青青草视频| 国产欧美一区二区精品性色超碰 | 国产又黄又嫩又滑又白 | 麻豆传媒mv | 熟女熟妇伦久久影院毛片一区二区 | 91av色| 少妇裸体挤奶汁奶水视频 | 欧美日韩在线观看一区 | 白嫩少妇激情无码 | 人妻无码中文久久久久专区 | 91av麻豆| 日韩和的一区二区 | 91精品国产综合久久福利 | 亚洲h在线观看 | 日韩乱码在线观看 | 韩国成人免费视频 | 91国偷自产一区二区三区老熟女 | 亚洲激情网站 | 在线免费观看av不卡 |