[maptalks](https://github.com/maptalks/maptalks.js) TileLayer tiles merge/clip/transform etc tool
npm install maptalks.tileclipmaptalks 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
* fetch tile
* fetch and merge tiles
* tiles filter by mask(only load tiles in mask)
* maxAvailableZoom
* maxAvailableZoom tiles
* maxAvailableZoom terrain
* maxAvailableZoom fetch by different
* vt tile
* vt tiles will merge mvt data
* vt tiles will merge mvt data and custom properties
* clip by polygon
* clip by polygon with holes
* clip by multipolygon
* clip by multipolygon with holes
* clip reverse
* clip buffer
* maxAvailableZoom polygon clip
* maxAvailableZoom tiles polygon clip
* update mask
* mask remove/add
* get tile and clip from single image
* EPSG:4326
* custom SpatialReference
* identify projection
* EPSG:9807
* tilerectify-gcj02-wgs84
* tilerectify-wgs84-gcj02
* tilerectify-baidu-wgs84
* tilerectify urltempalte is function
* Reproject EPSG4326 to EPSG3857
* Reproject EPSG3857 to EPSG4326
* mapzen terrain tile encode
* arcgis terrain tile encode
* qgis gray terrain tile encode
* terrain encode with colors
* color terrain tile
* flipY
* css filter
* tile opacity
* tile mosaic
* tile old photo
* tile invert color
* gaussian Blur
* tiles globalCompositeOperation
* get tile with mosaic
* 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
``sh`
npm i maptalks
#ornpm i maptalks-gl
npm i maptalks.tileclip
`html`
return TileActor instance
`js
import {
getTileActor,
getBlankTile,
get404Tile,
getBlankVTTile
} from 'maptalks.tileclip'
const tileActor = getTileActor();
`
Tile clip worker interaction class. about maptalks. Actor details
`js
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
`ts
// postProcessing params
export type postProcessingOptionsType = {
flipY?:boolean;
filter?: string; //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
fetchOptions?: Record
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, return Promiseoptions.url
+ :tile url or tiles urls...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js
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, return Promise. 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]...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js
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, return Promise .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]...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js
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, return Promiseoptions.x
+ :tile coloptions.y
+ :tile rowoptions.z
+ :tile zoomoptions.projection
+ : Projection code, only support EPSG: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...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js
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, return Promise. 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 urlTemplates options.projection
+ : 'EPSG:4326' | 'EPSG:3857'; options.tileBBOX
+ :tile BBOX [minx,miny,maxx,maxy]options.transform
+ : 'WGS84-GCJ02' | 'GCJ02-WGS84', options.tileSize
+ : tile size options?.subdomains
+ :subdomains, such as [1, 2, 3, 4, 5]...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js`
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, return Promise. 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 urlTemplates options.tileBBOX
+ :tile BBOX [minx,miny,maxx,maxy]options.transform
+ : 'BAIDU-WGS84' | 'BAIDU-GCJ02', options.tileSize
+ : tile size options?.subdomains
+ :subdomains, such as [1, 2, 3, 4, 5]...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js`
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 . return Promise
+ maskId: mask id, Cache mask data in the workerPolygon/MultiPolygon
+ GeoJSON Polygon/MultiPolygon GeoJSON SPEC
`js
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 . return Promise
+ maskId: mask id
`js
const maskId = 'china';
tileActor.removeMask(maskId).then(data => {
}).catch(error => {
console.error(error);
})
`
* maskHasInjected(maskId) Has the mask been injected . return Boolean
+ maskId: mask id
`js`
const maskId = 'china';
const result = tileActor.maskHasInjected(maskId);
* clipTile(options) clip tile by mask . return Promiseoptions.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 size options?.reverse
+ :whether or not clip reverse options?.bufferSize
+ : Buffer contour pixel size...returnResultType
+ returnResultType params
`js
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 . return Promise
+ options.tileBBOX:tile BBOX [minx,miny,maxx,maxy]options.maskId
+ :mask key
`js
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, return Promiseoptions.url
+ :tile urloptions.terrainType
+ :'mapzen' | 'tianditu' | 'cesium'|'arcgs'|'qgis-gray'options?.terrainWidth
+ default is 65options?.minHeight
+ min height when terrainType is 'qgis-gray'options?.maxHeight
+ max height when terrainType is 'qgis-gray'options?.tileSize
+ default value is 256options?.terrainColors
+ Colored terrain tiles. Color interpolation based on altitude...fetchOptionsType
+ fetchOptionsType params...returnResultType
+ returnResultType params
`js
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, return Promiseoptions.tile
+ :tile data, is ImageBitMap or http urloptions.colors
+ : Color Mapping Table...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js
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 , return Promiseoptions.tiles
+ :tiles collection ...returnResultType
+ returnResultType params
`js
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, return Promiseoptions.url
+ :image url or images urls...fetchOptionsType
+ fetchOptionsType params...postProcessingOptionsType
+ postProcessingOptions params...returnResultType
+ returnResultType params
`js
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 . return Promise
+ options.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...fetchOptionsType
+ fetchOptionsType params
`js
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 . return Promise
+ imageId: image id
`js
const imageId = 'china';
tileActor.removeImage(maskId).then(data => {
}).catch(error => {
console.error(error);
})
`
* imageHasInjected(imageId) Has the image been injected . return Boolean
+ imageId: image id
`js`
const imageId = 'china';
const result = tileActor.imageHasInjected(maskId);
* getImageTile(options) get tile data from image . return Promiseoptions.tileBBOX
+ :tile BBOX [minx,miny,maxx,maxy]options.projection
+ : Projection code, such as : EPSG:3857options.imageId
+ :mask keyoptions?.tileSize
+ :tile size ...postProcessingOptionsType
+ postProcessingOptionsType params...returnResultType
+ returnResultType params
`js
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, return Promiseoptions.url
+ :tile url or tiles urls options?.customProperties
+ :custom features properties function
`js`
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'
}
},
+ ...fetchOptionsType fetchOptionsType params
`js
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);
})
};
});
``