<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Add custom icons with Markers</title> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <link href="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.css" rel="stylesheet" /> <script src="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.js"></script> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } </style> <style> .marker { display: block; border: none; border-radius: 50%; cursor: pointer; padding: 0; } </style> </head> <body> <div id="map"></div> <script type="text/javascript"> mapboxgl.accessToken = "<your access token here>"; const map = new mapboxgl.Map({ container: "map", style: "mapbox://styles/mapbox/streets-v9", }); // ============================================自定义点标记图标============================================ const size = 16; const mapOnDevice = { width: size, height: size, data: new Uint8Array(size * size * 4), onAdd: function () { const canvas = document.createElement("canvas"); canvas.width = this.width; canvas.height = this.height; this.context = canvas.getContext("2d"); }, render: function () { const img = document.createElement("img"); img.src = "../images/map-off-device.png"; const _this = this; const context = this.context; img.onload = function () { //onload必须使用 context.drawImage(this, 0, 0); _this.data = context.getImageData( 0, 0, this.width, this.height ).data; }; // Update this image's data with data from the canvas. // Continuously repaint the map, resulting // in the smooth animation of the dot. // Return `true` to let the map know that the image was updated. return true; }, }; const mapOffDevice = { width: size, height: size, data: new Uint8Array(size * size * 4), onAdd: function () { const canvas = document.createElement("canvas"); canvas.width = this.width; canvas.height = this.height; this.context = canvas.getContext("2d"); }, render: function () { const img = document.createElement("img"); img.src = "../images/map-on-device.png"; const _this = this; const context = this.context; img.onload = function () { //onload必须使用 context.drawImage(this, 0, 0); _this.data = context.getImageData( 0, 0, this.width, this.height ).data; }; return true; }, }; map.on("load", () => { //给地图添加图片 map.addImage("map-on-device", mapOnDevice, { pixelRatio: 2 }); map.addImage("map-off-device", mapOffDevice, { pixelRatio: 2 }); // 给地图添加点坐标数据 map.addSource("dot-point", { type: "geojson", data: { type: "FeatureCollection", features: [ { type: "Feature", properties: { icon: "off", description: "<strong>Seersucker Bike Ride and Social</strong><p>Feeling dandy? Get fancy, grab your bike, and take part in this year's Seersucker Social bike ride from Dandies and Quaintrelles. After the ride enjoy a lawn party at Hillwood with jazz, cocktails, paper hat-making, and more. 11:00-7:00 p.m.</p>", }, geometry: { type: "Point", coordinates: [0, 0], // icon position [lng, lat] }, }, { type: "Feature", properties: { icon: "off", description: "<strong>Seersucker Bike Ride and Social</strong><p>Feeling dandy? Get fancy, grab your bike, and take part in this year's Seersucker Social bike ride from Dandies and Quaintrelles. After the ride enjoy a lawn party at Hillwood with jazz, cocktails, paper hat-making, and more. 11:00-7:00 p.m.</p>", }, geometry: { type: "Point", coordinates: [120.14834116918742, 30.254049032495487], // icon position [lng, lat] }, }, { type: "Feature", properties: { icon: "on", description: "<strong>Seersucker Bike Ride and Social</strong><p>Feeling dandy? Get fancy, grab your bike, and take part in this year's Seersucker Social bike ride from Dandies and Quaintrelles. After the ride enjoy a lawn party at Hillwood with jazz, cocktails, paper hat-making, and more. 11:00-7:00 p.m.</p>", }, geometry: { type: "Point", coordinates: [113.04037307827997, 23.49690412696048], // icon position [lng, lat] }, }, { type: "Feature", properties: { icon: "on", description: "<strong>Seersucker Bike Ride and Social</strong><p>Feeling dandy? Get fancy, grab your bike, and take part in this year's Seersucker Social bike ride from Dandies and Quaintrelles. After the ride enjoy a lawn party at Hillwood with jazz, cocktails, paper hat-making, and more. 11:00-7:00 p.m.</p>", }, geometry: { type: "Point", coordinates: [112.44129776283133, 38.157152588126856], // icon position [lng, lat] }, }, { type: "Feature", properties: { icon: "on", description: "<strong>Seersucker Bike Ride and Social</strong><p>Feeling dandy? Get fancy, grab your bike, and take part in this year's Seersucker Social bike ride from Dandies and Quaintrelles. After the ride enjoy a lawn party at Hillwood with jazz, cocktails, paper hat-making, and more. 11:00-7:00 p.m.</p>", }, geometry: { type: "Point", coordinates: [120.3812863499452, 36.08056916369821], // icon position [lng, lat] }, }, ], }, }); // 给地图添加图层 map.addLayer({ id: "places", type: "symbol", source: "dot-point", layout: { "icon-image": "map-{icon}-device", }, }); // ============================================标记悬浮事件============================================ var popup = new mapboxgl.Popup({ closeButton: false, closeOnClick: false, }); map.on("mouseenter", "places", (e) => { // Change the cursor style as a UI indicator. map.getCanvas().style.cursor = "pointer"; var coordinates = e.features[0].geometry.coordinates.slice(); var description = e.features[0].properties.description; // 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. popup.setLngLat(coordinates).setHTML(description).addTo(map); }); map.on("mouseleave", "places", () => { map.getCanvas().style.cursor = ""; popup.remove(); }); // ============================================标记点击事件============================================ map.on("click", "places", (e) => { console.log(e); console.log("点击事件"); }); }); </script> </body> </html>