Add a stretchable image to the map
This example uses a stretchable image as a background for text. Stretchable images allow some parts of the image to stretch while keeping other parts, such as corners, at a constant size. Set the layout
property 'icon-text-fit': 'both'
to use the image as background for the text.
<!DOCTYPE html><html><head><meta charset="utf-8"><title>Add a stretchable image to the map</title><meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"><link href="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css" rel="stylesheet"><script src="https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js"></script><style>body { margin: 0; padding: 0; }#map { position: absolute; top: 0; bottom: 0; width: 100%; }</style></head><body><div id="map"></div> <script> // TO MAKE THE MAP APPEAR YOU MUST // ADD YOUR ACCESS TOKEN FROM // https://account.mapbox.com mapboxgl.accessToken = '<your access token here>';var map = new mapboxgl.Map({container: 'map',style: 'mapbox://styles/mapbox/streets-v11',zoom: 0.1}); var images = {'popup': 'https://docs.mapbox.com/mapbox-gl-js/assets/popup.png','popup-debug':'https://docs.mapbox.com/mapbox-gl-js/assets/popup_debug.png'}; loadImages(images, function (loadedImages) {map.on('load', function () {map.addImage('popup-debug', loadedImages['popup-debug'], {// The two (blue) columns of pixels that can be stretched horizontally:// - the pixels between x: 25 and x: 55 can be stretched// - the pixels between x: 85 and x: 115 can be stretched.stretchX: [[25, 55],[85, 115]],// The one (red) row of pixels that can be stretched vertically:// - the pixels between y: 25 and y: 100 can be stretchedstretchY: [[25, 100]],// This part of the image that can contain text ([x1, y1, x2, y2]):content: [25, 25, 115, 100],// This is a high-dpi image:pixelRatio: 2});map.addImage('popup', loadedImages['popup'], {stretchX: [[25, 55],[85, 115]],stretchY: [[25, 100]],content: [25, 25, 115, 100],pixelRatio: 2}); map.addSource('points', {'type': 'geojson','data': {'type': 'FeatureCollection','features': [{'type': 'Feature','geometry': {'type': 'Point','coordinates': [40, -30]},'properties': {'image-name': 'popup-debug','name': 'Line 1\nLine 2\nLine 3'}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [40, 30]},'properties': {'image-name': 'popup','name': 'Line 1\nLine 2\nLine 3'}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [-40, -30]},'properties': {'image-name': 'popup-debug','name': 'One longer line'}},{'type': 'Feature','geometry': {'type': 'Point','coordinates': [-40, 30]},'properties': {'image-name': 'popup','name': 'One longer line'}}]}});map.addLayer({'id': 'points','type': 'symbol','source': 'points','layout': {'text-field': ['get', 'name'],'icon-text-fit': 'both','icon-image': ['get', 'image-name'],'icon-allow-overlap': true,'text-allow-overlap': true}}); // the original, unstretched image for comparisonmap.addSource('original', {'type': 'geojson','data': {'type': 'FeatureCollection','features': [{'type': 'Feature','geometry': {'type': 'Point','coordinates': [0, -70]}}]}});map.addLayer({'id': 'original','type': 'symbol','source': 'original','layout': {'text-field': 'unstretched image','icon-image': 'popup-debug','icon-allow-overlap': true,'text-allow-overlap': true}});});}); function loadImages(urls, callback) {var results = {};for (var name in urls) {map.loadImage(urls[name], makeCallback(name));} function makeCallback(name) {return function (err, image) {results[name] = err ? null : image; // if all images are loaded, call the callbackif (Object.keys(results).length === Object.keys(urls).length) {callback(results);}};}}</script> </body></html>