mapbox加载图片类型图标
聚合图:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Create and style clusters</title> 6 <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> 7 <link href="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.css" rel="stylesheet"> 8 <script src="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.js"></script> 9 <style> 10 body { margin: 0; padding: 0; } 11 #map { position: absolute; top: 0; bottom: 0; width: 100%; } 12 </style> 13 </head> 14 <body> 15 <div id="map"></div> 16 17 <script> 18 mapboxgl.accessToken = 'pk.eyJ1IjoiY3B0aHJzdW4iLCJhIjoiY2x4YjlvdjhrMGY5eTJrcHliaDRtd21heCJ9.1VEpXCZB8_yFFFdkwz9V-w'; 19 const map = new mapboxgl.Map({ 20 container: 'map', 21 // Choose from Mapbox's core styles, or make your own style with Mapbox Studio 22 style: 'mapbox://styles/mapbox/dark-v11', 23 center: [-103.5917, 40.6699], 24 zoom: 3 25 }); 26 27 map.on('load', () => { 28 // Add a new source from our GeoJSON data and 29 // set the 'cluster' option to true. GL-JS will 30 // add the point_count property to your source data. 31 map.addSource('earthquakes', { 32 type: 'geojson', 33 // Point to GeoJSON data. This example visualizes all M1.0+ earthquakes 34 // from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program. 35 data: 'https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson', 36 cluster: true, 37 clusterMaxZoom: 14, // Max zoom to cluster points on 38 clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50) 39 }); 40 41 map.addLayer({ 42 id: 'clusters', 43 type: 'circle', 44 source: 'earthquakes', 45 filter: ['has', 'point_count'], 46 paint: { 47 // Use step expressions (https://docs.mapbox.com/style-spec/reference/expressions/#step) 48 // with three steps to implement three types of circles: 49 // * Blue, 20px circles when point count is less than 100 50 // * Yellow, 30px circles when point count is between 100 and 750 51 // * Pink, 40px circles when point count is greater than or equal to 750 52 'circle-color': [ 53 'step', 54 ['get', 'point_count'], 55 '#51bbd6', 56 100, 57 '#f1f075', 58 750, 59 '#f28cb1' 60 ], 61 'circle-radius': [ 62 'step', 63 ['get', 'point_count'], 64 20, 65 100, 66 30, 67 750, 68 40 69 ] 70 } 71 }); 72 73 map.addLayer({ 74 id: 'cluster-count', 75 type: 'symbol', 76 source: 'earthquakes', 77 filter: ['has', 'point_count'], 78 layout: { 79 'text-field': ['get', 'point_count_abbreviated'], 80 'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'], 81 'text-size': 12 82 } 83 }); 84 85 map.addLayer({ 86 id: 'unclustered-point', 87 type: 'circle', 88 source: 'earthquakes', 89 filter: ['!', ['has', 'point_count']], 90 paint: { 91 'circle-color': '#11b4da', 92 'circle-radius': 4, 93 'circle-stroke-width': 1, 94 'circle-stroke-color': '#fff' 95 } 96 }); 97 98 // inspect a cluster on click 99 map.on('click', 'clusters', (e) => { 100 const features = map.queryRenderedFeatures(e.point, { 101 layers: ['clusters'] 102 }); 103 const clusterId = features[0].properties.cluster_id; 104 map.getSource('earthquakes').getClusterExpansionZoom( 105 clusterId, 106 (err, zoom) => { 107 if (err) return; 108 109 map.easeTo({ 110 center: features[0].geometry.coordinates, 111 zoom: zoom 112 }); 113 } 114 ); 115 }); 116 117 // When a click event occurs on a feature in 118 // the unclustered-point layer, open a popup at 119 // the location of the feature, with 120 // description HTML from its properties. 121 map.on('click', 'unclustered-point', (e) => { 122 const coordinates = e.features[0].geometry.coordinates.slice(); 123 const mag = e.features[0].properties.mag; 124 const tsunami = 125 e.features[0].properties.tsunami === 1 ? 'yes' : 'no'; 126 127 // Ensure that if the map is zoomed out such that 128 // multiple copies of the feature are visible, the 129 // popup appears over the copy being pointed to. 130 if (['mercator', 'equirectangular'].includes(map.getProjection().name)) { 131 while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) { 132 coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360; 133 } 134 } 135 136 new mapboxgl.Popup() 137 .setLngLat(coordinates) 138 .setHTML( 139 `magnitude: ${mag}<br>Was there a tsunami?: ${tsunami}` 140 ) 141 .addTo(map); 142 }); 143 144 map.on('mouseenter', 'clusters', () => { 145 map.getCanvas().style.cursor = 'pointer'; 146 }); 147 map.on('mouseleave', 'clusters', () => { 148 map.getCanvas().style.cursor = ''; 149 }); 150 }); 151 </script> 152 153 </body> 154 </html>
自定义图片
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Add custom icons with Markers</title> 6 <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> 7 <link href="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.css" rel="stylesheet"> 8 <script src="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.js"></script> 9 <style> 10 body { margin: 0; padding: 0; } 11 #map { position: absolute; top: 0; bottom: 0; width: 100%; } 12 </style> 13 </head> 14 <body> 15 <style> 16 .marker { 17 display: block; 18 border: none; 19 border-radius: 50%; 20 cursor: pointer; 21 padding: 0; 22 } 23 </style> 24 25 <div id="map"></div> 26 27 <script> 28 mapboxgl.accessToken = 'pk.eyJ1IjoiY3B0aHJzdW4iLCJhIjoiY2x4YjlvdjhrMGY5eTJrcHliaDRtd21heCJ9.1VEpXCZB8_yFFFdkwz9V-w'; 29 const geojson = { 30 'type': 'FeatureCollection', 31 'features': [ 32 { 33 'type': 'Feature', 34 'properties': { 35 'message': 'Foo', 36 'imageId': 1011, 37 'iconSize': [60, 60] 38 }, 39 'geometry': { 40 'type': 'Point', 41 'coordinates': [-66.324462, -16.024695] 42 } 43 }, 44 { 45 'type': 'Feature', 46 'properties': { 47 'message': 'Bar', 48 'imageId': 870, 49 'iconSize': [50, 50] 50 }, 51 'geometry': { 52 'type': 'Point', 53 'coordinates': [-61.21582, -15.971891] 54 } 55 }, 56 { 57 'type': 'Feature', 58 'properties': { 59 'message': 'Baz', 60 'imageId': 837, 61 'iconSize': [40, 40] 62 }, 63 'geometry': { 64 'type': 'Point', 65 'coordinates': [-63.292236, -18.281518] 66 } 67 } 68 ] 69 }; 70 71 const map = new mapboxgl.Map({ 72 container: 'map', 73 // Choose from Mapbox's core styles, or make your own style with Mapbox Studio 74 style: 'mapbox://styles/mapbox/streets-v12', 75 center: [-65.017, -16.457], 76 zoom: 5 77 }); 78 79 // Add markers to the map. 80 for (const marker of geojson.features) { 81 // Create a DOM element for each marker. 82 const el = document.createElement('div'); 83 const width = marker.properties.iconSize[0]; 84 const height = marker.properties.iconSize[1]; 85 el.className = 'marker'; 86 el.style.backgroundImage = `url(https://picsum.photos/id/${marker.properties.imageId}/${width}/${height})`; 87 el.style.width = `${width}px`; 88 el.style.height = `${height}px`; 89 el.style.backgroundSize = '100%'; 90 91 el.addEventListener('click', () => { 92 window.alert(marker.properties.message); 93 }); 94 95 // Add markers to the map. 96 new mapboxgl.Marker(el) 97 .setLngLat(marker.geometry.coordinates) 98 .addTo(map); 99 } 100 </script> 101 102 </body> 103 </html>
mapboxGL中多图标加载的实现
1 map.on('load',() => { 2 const canvas = document.createElement('canvas') 3 const ctx = canvas.getContext('2d') 4 const img = new Image() 5 img.src = './lib/merge.png' 6 img.onload = async () => { 7 canvas.width = img.width 8 canvas.height = img.height 9 ctx.drawImage(img, 0, 0) 10 fetch('./lib/merge.json').then(res => res.json()).then(res => { 11 for (const k in res) { 12 const { width, height, x, y } = res[k] 13 const data = ctx.getImageData(x, y, width, height).data 14 map.addImage(k, { width, height, data }) 15 } 16 map.addSource('points', { 17 type: 'geojson', 18 data: { 19 type: 'FeatureCollection', 20 features: [ 21 { 22 "type": "Feature", 23 "properties": { icon: 'zgyh' }, 24 "geometry": { "type": "Point", "coordinates": [107.0132554, 22.1441921] } 25 }, 26 { 27 "type": "Feature", 28 "properties": { icon: 'jsyh' }, 29 "geometry": { "type": "Point", "coordinates": [107.0223554, 22.1443921] } 30 }, 31 { 32 "type": "Feature", 33 "properties": { icon: 'nyyh' }, 34 "geometry": { "type": "Point", "coordinates": [107.0344554, 22.1444921] } 35 } 36 ] 37 } 38 39 }); 40 map.addLayer({ 41 'id': 'points-h', 42 'type': 'symbol', 43 'source': 'points', 44 'layout': { 45 'icon-allow-overlap': true, 46 'icon-image': ['get', 'icon'], 47 'icon-size': [ 48 "interpolate", 49 [ 50 "exponential", 51 1.5 52 ], 53 [ 54 "zoom" 55 ], 56 5, 0.5, 57 10, 0.8 58 ] 59 }, 60 }); 61 }) 62 } 63 })