maptalks.tileclip
v0.63.1
Published
[maptalks](https://github.com/maptalks/maptalks.js) TileLayer tiles merge/clip/transform etc tool
Downloads
1,401
Readme
maptalks.tileclip
maptalks TileLayer tiles merge/clip/transform etc tool
This plugin requires the runtime environment to support OffscreenCanvas. Pay attention to relevant compatibility. Especially the Safari browser
Considering performance, all operations are completed within the Web Worker
If you are familiar with other map engines, you can also apply them to other map engines leaflet demo
Examples
Fetch Tile
Clip Tile
Clip By Custom Prj
Rectify Tile
Reproject Tile
Terrain Encode
- mapzen terrain tile encode
- arcgis terrain tile encode
- qgis gray terrain tile encode
- terrain encode with colors
- color terrain tile
postProcessing
- flipY
- css filter
- tile opacity
- tile mosaic
- tile old photo
- tile invert color
- gaussian Blur
- tiles globalCompositeOperation
- get tile with mosaic
Others
- water mark
- underground by clip tile
- terrain-tiles-blendmode
- terrain-tiles-blendmode shadow
- leaflet clip demo
- leaflet gettile demo
- leaflet reproject tile demo
- leaflet-imagetile-clip demo
- maplibre reproject EPSG4326 to EPSG3857 demo
Install
NPM
npm i maptalks
#or
# npm i maptalks-gl
npm i maptalks.tileclipCDN
<script type="text/javascript" src="https://unpkg.com/maptalks-gl/dist/maptalks-gl.js"></script>
<script src="https://unpkg.com/maptalks.tileclip/dist/maptalks.tileclip.js"></script>API
getTileActor()
return TileActor instance
import {
getTileActor,
getBlankTile,
get404Tile,
getBlankVTTile
} from 'maptalks.tileclip'
const tileActor = getTileActor();TileActor class
Tile clip worker interaction class. about maptalks. Actor details
import {
getTileActor
} from 'maptalks.tileclip'
const tileActor = getTileActor();Methods
| method | describe | | --------------------------------------- | ------------------------------------------------------------------- | | getTile(options) | Request tile support for batch and some processing | | getTileWithMaxZoom(options) | Cutting tiles, automatically cutting beyond the maximum level limit | | layoutTiles(options) | Tile layout arrangement | | reProjectTile(options) | Tile reprojection | | rectifyTile(options) | Corrective tiles, only applicable to Chinese users | | rectifyBaiduTile(options) | Corrective baidu tiles, only applicable to Chinese users | | injectMask(maskId, Polygon/MultiPolygon)| Inject geojson data for tile clipping service | | removeMask(maskId) | remove Inject geojson data | | maskHasInjected(maskId) | Has the geojson data been injected | | clipTile(options) | Crop tiles using injected geojson data | | tileIntersectMask(options) | Does tile intersect with mask | | encodeTerrainTile(options) | Encode other terrain tiles into mapbox terrain service format | | colorTerrainTile(options) | Terrain tile color matching | | terrainTileFixBoundary(options) | Reset the skirt edge of the terrain tile using neighbor tiles | | imageSlicing(options) | Cut a large image into multiple small images | | injectImage(options) | inject image source for getImageTile | | removeImage(imageId) | remove image source | | imageHasInjected(imageId) | Has the image data been injected | | getImageTile(options) | get tile data from injectImage | | getVTTile(options) | get VT tile, support merge vt data and custom prorperties |
Common Types
// postProcessing params
export type postProcessingOptionsType = {
flipY?:boolean;
filter?: string; //[CanvasRenderingContext2D.filter](https://mdn.org.cn/en-US/docs/Web/API/CanvasRenderingContext2D/filter)
opacity?: number;//tile opacity if need
gaussianBlurRadius?: number;// gaussian Blur Radius if need
mosaicSize?: number;//Mosaic pixel size
oldPhoto?: boolean;//Old photo effect
invertColor?:boolean;// invert Color
}
//fetch params
export type fetchOptionsType = {
referrer?: string;//fetch referrer
headers?: Record<string, string>;// fetch headers params. if need
fetchOptions?: Record<string, any>;//fetch options. if need, If it exists, headers will be ignored
timeout?: number;//fetch timeout if need
indexedDBCache?: boolean;//cache tile data by IndexedDB
}
// image reutrn result params
//tile default return ImageBitMap
export type returnResultType = {
returnUint32Buffer?:boolean;//return to Unit32 ArrayBuffer
returnBlobURL?: boolean;// to return Blob URL by createObjectURL() When the blob URL is no longer in use, be sure to destroy its value revokeObjectURL()
returnBase64?: boolean;// return base64
quality?:number;//image quality 0-1,MIME types is image/webp https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/MIME_types/Common_types
}
Method Details
all methods return Promise with cancel() method
getTile(options)get tile ImageBitmap by fetch in worker, returnPromiseoptions.url:tile url or tiles urls...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
tileActor.getTile({
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/12/1663/3425',
//or url:[ur1,ur2],
fetchOptions: {
referrer: document.location.href,
headers: {
...
}
...
},
oldPhoto: true,
}).then(imagebitmap => {
consle.log(imagebitmap);
}).catch(error => {
//do some things
})
//or if you want to cancel task
const promise = tileActor.getTile({
...
});
//mock cancel fetch task
setTimeout(() => {
promise.cancel();
}, 2000);
promise.then((imagebitmap) => {
}).catch(error => {
//do some things
console.error(error);
})getTileWithMaxZoom(options)get tile ImageBitmap by fetch in worker, returnPromise. When the level exceeds the maximum level, tiles will be automatically cutoptions.x:tile coloptions.y:tile rowoptions.z:tile zoomoptions.maxAvailableZoom:tile The maximum visible level, such as 18options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x} or tiles urlTemplatesoptions?.subdomains:subdomains, such as [1, 2, 3, 4, 5]...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
const {
x,
y,
z
} = tile;
const urlTemplate = baseLayer.options.urlTemplate;
const maxAvailableZoom = 18;
tileActor.getTileWithMaxZoom({
x,
y,
z,
urlTemplate,
//or urlTemplate:[urlTemplate1,urlTemplate2],
maxAvailableZoom,
fetchOptions: {
referrer: document.location.href,
headers: {
...
}
...
}
}).then(imagebitmap => {
consle.log(imagebitmap);
}).catch(error => {
//do some things
})
//or if you want to cancel task
const promise = tileActor.getTileWithMaxZoom({
...
});
//mock cancel fetch task
setTimeout(() => {
promise.cancel();
}, 2000);
promise.then((imagebitmap) => {
}).catch(error => {
//do some things
console.error(error);
})layoutTile(options)layout tiles ImageBitmap by fetch in worker, returnPromise.options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x}options.tiles: tile Data setoptions?.subdomains:subdomains, such as [1, 2, 3, 4, 5]...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
const {
x,
y,
z
} = tile;
const urlTemplate = baseLayer.options.urlTemplate;
tileActor.layoutTiles({
urlTemplate,
tiles: [
[x, y, z],
[x + 1, y, z],
[x, y + 1, z],
[x + 1, y + 1, z]
]
fetchOptions: {
referrer: document.location.href,
headers: {
...
}
...
}
}).then(imagebitmap => {
consle.log(imagebitmap);
}).catch(error => {
//do some things
})
//or if you want to cancel task
const promise = tileActor.layoutTiles({
...
});
//mock cancel fetch task
setTimeout(() => {
promise.cancel();
}, 2000);
promise.then((imagebitmap) => {
}).catch(error => {
//do some things
console.error(error);
})reProjectTile(options)Reprojection tile in worker, returnPromiseoptions.x:tile coloptions.y:tile rowoptions.z:tile zoomoptions.projection: Projection code, only supportEPSG:4326,EPSG:3857. Note that only global standard pyramid slicing is supportedoptions.maxAvailableZoom:tile The maximum visible level, such as 18options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x} or tiles urlTemplatesoptions?.subdomains:subdomains, such as [1, 2, 3, 4, 5]options?.isGCJ02: Is it the isGCJ02 coordinate systemoptions?.errorLog: Is there a printing error...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
const {
x,
y,
z
} = tile;
const maxAvailableZoom = 18;
tileActor.reProjectTile({
x,
y,
z,
urlTemplate,
projection: 'EPSG:4326',
maxAvailableZoom: 18,
}).then(imagebitmap => {
callback(imagebitmap);
}).catch(error => {
//do some things
console.error(error);
})
//or if you want to cancel task
const promise = tileActor.reProjectTile({
...
});
//mock cancel fetch task
setTimeout(() => {
promise.cancel();
}, 2000);
promise.then((imagebitmap) => {
}).catch(error => {
//do some things
console.error(error);
})rectifyTile(options)rectify tile ImageBitmap by fetch in worker, returnPromise. When the level exceeds the maximum level, tiles will be automatically cutoptions.x:tile coloptions.y:tile rowoptions.z:tile zoomoptions.maxAvailableZoom:tile The maximum visible level, such as 18options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x} or tiles urlTemplatesoptions.projection: 'EPSG:4326' | 'EPSG:3857';options.tileBBOX:tile BBOX[minx,miny,maxx,maxy]options.transform: 'WGS84-GCJ02' | 'GCJ02-WGS84',options.tileSize: tile sizeoptions?.subdomains:subdomains, such as [1, 2, 3, 4, 5]...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
// console.log(tile);
const {
x,
y,
z
} = tile;
const urlTemplate = baseLayer.options.urlTemplate;
const maxAvailableZoom = 18;
tileActor.rectifyTile({
x,
y,
z,
urlTemplate,
maxAvailableZoom,
tileBBOX: baseLayer._getTileBBox(tile),
projection: baseLayer.getProjection().code,
tileSize: baseLayer.getTileSize().width,
transform: 'GCJ02-WGS84',
mapZoom: map.getZoom()
}).then(imagebitmap => {
callback(imagebitmap);
}).catch(error => {
//do some things
console.error(error);
})
};
});rectifyBaiduTile(options)rectify baidu tile ImageBitmap by fetch in worker, returnPromise. When the level exceeds the maximum level, tiles will be automatically cutoptions.x:tile coloptions.y:tile rowoptions.z:tile zoomoptions.maxAvailableZoom:tile The maximum visible level, such as 18options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x} or tiles urlTemplatesoptions.tileBBOX:tile BBOX[minx,miny,maxx,maxy]options.transform: 'BAIDU-WGS84' | 'BAIDU-GCJ02',options.tileSize: tile sizeoptions?.subdomains:subdomains, such as [1, 2, 3, 4, 5]...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
// console.log(tile);
const {
x,
y,
z
} = tile;
const urlTemplate = baseLayer.options.urlTemplate;
const maxAvailableZoom = 18;
tileActor.rectifyBaiduTile({
x,
y,
z,
urlTemplate,
maxAvailableZoom,
tileBBOX: baseLayer._getTileBBox(tile),
tileSize: baseLayer.getTileSize().width,
transform: 'BAIDU-WGS84',
mapZoom: map.getZoom()
}).then(imagebitmap => {
callback(imagebitmap);
}).catch(error => {
//do some things
console.error(error);
})
};
});injectMask(maskId,Polygon/MultiPolygon)inject Mask(GeoJSON. Polygon) for clip tiles . returnPromisemaskId: mask id, Cache mask data in the workerPolygon/MultiPolygonGeoJSON Polygon/MultiPolygon GeoJSON SPEC
const maskId = 'china';
const polygon = {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": []
}
}
tileActor.injectMask(maskId, polygon).then(data => {
// baseLayer.addTo(map);
}).catch(error => {
console.error(error);
})removeMask(maskId)remove Mask from cache . returnPromisemaskId: mask id
const maskId = 'china';
tileActor.removeMask(maskId).then(data => {
}).catch(error => {
console.error(error);
})maskHasInjected(maskId)Has the mask been injected . returnBooleanmaskId: mask id
const maskId = 'china';
const result = tileActor.maskHasInjected(maskId);clipTile(options)clip tile by mask . returnPromiseoptions.tile:tile ImageBitmap data or http urloptions.tileBBOX:tile BBOX[minx,miny,maxx,maxy]options.projection: Projection code, such as : EPSG:3857options.maskId:mask keyoptions?.tileSize:tile sizeoptions?.reverse:whether or not clip reverseoptions?.bufferSize: Buffer contour pixel size...returnResultTypereturnResultType params
import * as maptalks from 'maptalks-gl';
import {
getTileActor
} from 'maptalks.tileclip';
const tileActor = getTileActor();
const maskId = 'china';
const baseLayer = new maptalks.TileLayer('base', {
debug: true,
urlTemplate: '/arcgisonline/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x}',
subdomains: ["a", "b", "c", "d"],
// bufferPixel: 1
})
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
//get Tile data
tileActor.getTile({
url: maptalks.Util.getAbsoluteURL(url)
}).then(imagebitmap => {
//clip tile
tileActor.clipTile({
tile: imagebitmap,
tileBBOX: baseLayer._getTileBBox(tile),
projection: baseLayer.getProjection().code,
tileSize: baseLayer.getTileSize().width,
maskId,
}).then(image => {
callback(image);
}).catch(error => {
//do some things
console.error(error);
})
}).catch(error => {
//do some things
console.error(error);
})
};
});
const polygon = {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": []
}
}
tileActor.injectMask(maskId, polygon).then(data => {
baseLayer.addTo(map);
}).catch(error => {
console.error(error);
})tileIntersectMask(options)Does tile intersect with mask . returnPromiseoptions.tileBBOX:tile BBOX[minx,miny,maxx,maxy]options.maskId:mask key
import * as maptalks from 'maptalks-gl';
import {
getTileActor
} from 'maptalks.tileclip';
const tileActor = getTileActor();
const maskId = 'china';
const baseLayer = new maptalks.TileLayer('base', {
debug: true,
urlTemplate: '/arcgisonline/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x}',
subdomains: ["a", "b", "c", "d"],
// bufferPixel: 1
})
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
const tileBBOX = baseLayer._getTileBBox(tile);
const blankTile = () => {
callback(maptalks.getBlankTile())
}
tileActor.tileIntersectMask({
tileBBOX,
maskId
}).then(result => {
// callback(result);
const {
intersect
} = result;
if (intersect) {
tileActor.getTile({
url: maptalks.Util.getAbsoluteURL(url)
}).then(imagebitmap => {
callback(imagebitmap);
}).catch(error => {
//do some things
console.error(error);
blankTile();
})
} else {
blankTile();
}
}).catch(error => {
//do some things
console.error(error);
blankTile();
})
};
});
const polygon = {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": []
}
}
tileActor.injectMask(maskId, polygon).then(data => {
baseLayer.addTo(map);
}).catch(error => {
console.error(error);
})encodeTerrainTile(options)transform other terrain tile to mapbox terrain rgb tile by fetch in worker, returnPromiseoptions.url:tile urloptions.terrainType:'mapzen' | 'tianditu' | 'cesium'|'arcgs'|'qgis-gray'options?.terrainWidthdefault is 65options?.minHeightmin height when terrainType is 'qgis-gray'options?.maxHeightmax height when terrainType is 'qgis-gray'options?.tileSizedefault value is 256options?.terrainColorsColored terrain tiles. Color interpolation based on altitude...fetchOptionsTypefetchOptionsType params...returnResultTypereturnResultType params
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
//transform mapzen terrain tile to mapbox terrain rgb tile
tileActor.encodeTerrainTile({
url: maptalks.Util.getAbsoluteURL(url),
terrainType: 'mapzen',
// timeout: 5000
}).then(imagebitmap => {
callback(imagebitmap)
}).catch(error => {
//do some things
console.error(error);
})
};
});colorTerrainTile(options)Terrain tile color matching, returnPromiseoptions.tile:tile data, is ImageBitMap or http urloptions.colors: Color Mapping Table...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
const colors = [
[0, "#4B2991"],
[176, "#872CA2"],
[353, "#C0369D"],
[530, "#EA4F88"],
[706, "#FA7876"],
[883, "#F6A97A"],
[1060, "#EDD9A3"],
[1236, "#EDD9A3"],
[1413, "#ffffff"],
[1590, "#ffffff"]
]
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
tileActor.getTile({
url: maptalks.Util.getAbsoluteURL(url)
}).then(imagebitmap => {
tileActor.colorTerrainTile({
tile: imagebitmap,
colors
}).then(image => {
callback(image);
}).catch(error => {
console.error(error);
})
}).catch(error => {
//do some things
// console.error(error);
callback(maptalks.get404Tile())
})
};
});terrainTileFixBoundary(options)Reset the skirt edge of the terrain tile using neighbor tiles , returnPromiseoptions.tiles:tiles collection...returnResultTypereturnResultType params
const tile = {
x,
y,
z,
image: ...
};
const tileRight = {
x: x + 1,
y,
z: image: ...
}
const tileBottom = {
x,
y: y + 1,
z,
image: ...
}
tileActor.terrainTileFixBoundary({
tiles: [tile, tileRight, tileBottom],
returnUint32Buffer: true
}).then(imagebitmap => {
}).catch(error => {
//do some things
// console.error(error);
callback(maptalks.get404Tile())
})imageSlicing(options)slice big image in worker, returnPromiseoptions.url:image url or images urls...fetchOptionsTypefetchOptionsType params...postProcessingOptionsTypepostProcessingOptions params...returnResultTypereturnResultType params
tileActor.imageSlicing({
url: './big.png',
//or url:[ur1,ur2],
fetchOptions: {
referrer: document.location.href,
headers: {
...
}
...
}
}).then(result => {
consle.log(result);
}).catch(error => {
//do some things
})injectImage(options)inject Image for getImageTile . returnPromiseoptions.url:image urloptions.imageBBOX:image BBOX[minx,miny,maxx,maxy]. Note that the coordinates of the bounding box should be consistent with the projected imageoptions.imageId:image url...fetchOptionsTypefetchOptionsType params
const imageId = 'china';
tileActor.injectImage({
imageId,
url: './test.jpg',
imageBBOX: [120, 31, 121, 32]
}).then(data => {
// baseLayer.addTo(map);
}).catch(error => {
console.error(error);
})removeImage(imageId)remove image from cache . returnPromiseimageId: image id
const imageId = 'china';
tileActor.removeImage(maskId).then(data => {
}).catch(error => {
console.error(error);
})imageHasInjected(imageId)Has the image been injected . returnBooleanimageId: image id
const imageId = 'china';
const result = tileActor.imageHasInjected(maskId);getImageTile(options)get tile data from image . returnPromiseoptions.tileBBOX:tile BBOX[minx,miny,maxx,maxy]options.projection: Projection code, such as : EPSG:3857options.imageId:mask keyoptions?.tileSize:tile size...postProcessingOptionsTypepostProcessingOptionsType params...returnResultTypereturnResultType params
import * as maptalks from 'maptalks-gl';
import {
getTileActor
} from 'maptalks.tileclip';
const tileActor = getTileActor();
const imageId = 'china';
const baseLayer = new maptalks.TileLayer('base', {
debug: true,
urlTemplate: '/arcgisonline/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x}',
subdomains: ["a", "b", "c", "d"],
// bufferPixel: 1
})
baseLayer.on('renderercreate', function(e) {
//load tile image
// img(Image): an Image object
// url(String): the url of the tile
e.renderer.loadTileBitmap = function(url, tile, callback) {
tileActor.getImageTile({
imageId,
projection: baseLayer.getProjection().code,
tileSize: baseLayer.getTileSize().width,
tileBBOX: baseLayer._getTileBBox(tile),
}).then(imagebitmap => {
// console.log(imagebitmap);
callback(imagebitmap);
}).catch(error => {
//do some things
console.error(error);
})
};
});
tileActor.injectImage({
imageId,
url: './unnamed.jpg',
imageBBOX: [...m1, ...m2]
}).then(data => {
baseLayer.addTo(groupLayer);
}).catch(error => {
console.error(error);
})getVTTile(options)get vt tile arraybuffer by fetch in worker, returnPromiseoptions.url:tile url or tiles urlsoptions?.customProperties:custom features propertiesfunction
customProperties: (layerName, layer, feature, featureIndex) => {
feature.properties = feature.properties || {};
if (layerName === 'suzhou_area') {
feature.properties.name1 = 'hello'
}
if (layerName === 'suzhou_line') {
feature.properties.name1 = 'world'
}
},...fetchOptionsTypefetchOptionsType params
const layer = new maptalks.VectorTileLayer("geo", {
style,
debugTileData: true,
version: 1,
// urlTemplate: './../assets/data/suzhou_line/{z}/{x}/{y}.pbf'
urlTemplate: 'xxx'
});
const roadTileUrl = 'xxx';
layer.on('renderercreate', function(e) {
e.renderer.loadTileArrayBuffer = function(url, tile, callback, options) {
console.log(options.command);
const {
x,
y,
z
} = tile;
const url1 = roadTileUrl.replace("{x}", x).replace('{y}', y).replace('{z}', z);
tileActor.getVTTile({
//will merge mvt data
url: [url, url1],
customProperties: (layerName, layer, feature, featureIndex) => {
feature.properties = feature.properties || {};
if (layerName === 'suzhou_area') {
feature.properties.name1 = 'hello'
}
if (layerName === 'suzhou_line') {
feature.properties.name1 = 'world'
}
},
indexedDBCache: true
}).then(buffer => {
callback(null, buffer);
}).catch(error => {
console.log(error);
callback(error);
})
};
});