Skip to content

Commit

Permalink
Remove callback from loadImage (#3422)
Browse files Browse the repository at this point in the history
* Remove callback from loadImage

* Update changelog

* Fix lint
  • Loading branch information
HarelM authored Nov 28, 2023
1 parent ef5a2fa commit dec7af2
Show file tree
Hide file tree
Showing 9 changed files with 474 additions and 530 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

### ✨ Features and improvements

⚠️ Changed the `GeoJSONSource`'s `getClusterExpansionZoom`, `getClusterChildren`, `getClusterLeaves` methods to return a `Promise` instead of a callback usage ([#3421](https://github.com/maplibre/maplibre-gl-js/pull/3421))
- ⚠️ Removed callback usage from `map.loadImage` in continue to below change ([#3422](https://github.com/maplibre/maplibre-gl-js/pull/3422))
- ⚠️ Changed the `GeoJSONSource`'s `getClusterExpansionZoom`, `getClusterChildren`, `getClusterLeaves` methods to return a `Promise` instead of a callback usage ([#3421](https://github.com/maplibre/maplibre-gl-js/pull/3421))
- ⚠️ Changed the `setRTLTextPlugin` function to return a promise instead of using callback ([#3418](https://github.com/maplibre/maplibre-gl-js/pull/3418)) this also changed how the RTL pluing code is handled internally by splitting the main thread and worker thread code.
- _...Add new stuff here..._

Expand Down
13 changes: 3 additions & 10 deletions src/ui/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import packageJSON from '../../package.json' assert {type: 'json'};

import {GetResourceResponse, getJSON} from '../util/ajax';
import {ImageRequest} from '../util/image_request';
import type {GetImageCallback} from '../util/image_request';

import {RequestManager, ResourceType} from '../util/request_manager';
import {Style, StyleSwapOptions} from '../style/style';
Expand Down Expand Up @@ -2304,7 +2303,7 @@ export class Map extends Camera {
* domains must support [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS).
*
* @param url - The URL of the image file. Image file must be in png, webp, or jpg format.
* @param callback - if not provided, this method will return a promise, otherwise use `callback(error, data)`. Called when the image has loaded or with an error argument if there is an error.
* @returns a promise that is resolved when the image is loaded
*
* @example
* Load an image from an external URL.
Expand All @@ -2315,14 +2314,8 @@ export class Map extends Camera {
* ```
* @see [Add an icon to the map](https://maplibre.org/maplibre-gl-js/docs/examples/add-image/)
*/
loadImage(url: string, callback?: GetImageCallback): Promise<GetResourceResponse<HTMLImageElement | ImageBitmap>> {
if (!callback) {
return ImageRequest.getImage(this._requestManager.transformRequest(url, ResourceType.Image), new AbortController());
} else {
ImageRequest.getImage(this._requestManager.transformRequest(url, ResourceType.Image), new AbortController())
.then((response) => callback(null, response.data, {cacheControl: response.cacheControl, expires: response.expires}))
.catch(callback);
}
loadImage(url: string): Promise<GetResourceResponse<HTMLImageElement | ImageBitmap>> {
return ImageRequest.getImage(this._requestManager.transformRequest(url, ResourceType.Image), new AbortController());
}

/**
Expand Down
7 changes: 1 addition & 6 deletions src/util/image_request.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import {RequestParameters, ExpiryData, makeRequest, sameOrigin, getProtocolAction, GetResourceResponse} from './ajax';
import {RequestParameters, makeRequest, sameOrigin, getProtocolAction, GetResourceResponse} from './ajax';

import {arrayBufferToImageBitmap, arrayBufferToImage, extend, isWorker, isImageBitmap} from './util';
import {webpSupported} from './webp_supported';
import {config} from './config';
import {createAbortError} from './abort_error';

/**
* The callback that is being called after an image was fetched
*/
export type GetImageCallback = (error?: Error | null, image?: HTMLImageElement | ImageBitmap | null, expiry?: ExpiryData | null) => void;

type ImageQueueThrottleControlCallback = () => boolean;

export type ImageRequestQueueItem = {
Expand Down
244 changes: 113 additions & 131 deletions test/examples/add-image-stretchable.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,146 +29,128 @@
'https://maplibre.org/maplibre-gl-js/docs/assets/popup_debug.png'
};

loadImages(images, (loadedImages) => {
map.on('load', () => {
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 stretched
stretchY: [[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.on('load', async () => {
const debugPopup = await map.loadImage(images['popup-debug']);
const popup = await map.loadImage(images['popup']);
map.addImage('popup-debug', debugPopup.data, {
// 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 stretched
stretchY: [[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', popup.data, {
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'
}
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]
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [40, 30]
},
'properties': {
'image-name': 'popup',
'name': 'Line 1\nLine 2\nLine 3'
}
'properties': {
'image-name': 'popup',
'name': 'Line 1\nLine 2\nLine 3'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-40, -30]
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-40, -30]
},
'properties': {
'image-name': 'popup-debug',
'name': 'One longer line'
}
'properties': {
'image-name': 'popup-debug',
'name': 'One longer line'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-40, 30]
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-40, 30]
},
'properties': {
'image-name': 'popup',
'name': 'One longer line'
}
'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-overlap': 'always',
'text-overlap': 'always'
}
});
}
]
}
});
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'text-field': ['get', 'name'],
'icon-text-fit': 'both',
'icon-image': ['get', 'image-name'],
'icon-overlap': 'always',
'text-overlap': 'always'
}
});

// the original, unstretched image for comparison
map.addSource('original', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, -70]
}
// the original, unstretched image for comparison
map.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-overlap': 'always',
'text-overlap': 'always'
}
});
}
]
}
});
map.addLayer({
'id': 'original',
'type': 'symbol',
'source': 'original',
'layout': {
'text-field': 'unstretched image',
'icon-image': 'popup-debug',
'icon-overlap': 'always',
'text-overlap': 'always'
}
});
});

function loadImages(urls, callback) {
const results = {};
for (const 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 callback
if (Object.keys(results).length === Object.keys(urls).length) {
callback(results);
}
};
}
}
</script>
</body>
</html>
55 changes: 25 additions & 30 deletions test/examples/add-image.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,33 @@
'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL'
});

map.on('load', () => {
map.loadImage(
'https://upload.wikimedia.org/wikipedia/commons/7/7c/201408_cat.png',
(error, image) => {
if (error) throw error;
map.addImage('cat', image);
map.addSource('point', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, 0]
}
}
]
map.on('load', async () => {
image = await map.loadImage('https://upload.wikimedia.org/wikipedia/commons/7/7c/201408_cat.png');
map.addImage('cat', image.data);
map.addSource('point', {
'type': 'geojson',
'data': {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [0, 0]
}
}
});
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'point',
'layout': {
'icon-image': 'cat',
'icon-size': 0.25
}
});
]
}
});
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'point',
'layout': {
'icon-image': 'cat',
'icon-size': 0.25
}
);
});
});
</script>
</body>
Expand Down
Loading

0 comments on commit dec7af2

Please sign in to comment.