Skip to content

maptalks/maptalks.tileclip

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

maptalks.tileclip

maptalks TileLayer tiles merge/clip/transform tool

  • This plugin requires the runtime environment to support OffscreenCanvas. Pay attention to relevant compatibility

  • 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

Common

Clip By Custom Prj

Transform Tile

Terrain Encode

postProcessing

Others

Install

NPM

npm i maptalks
#or
# npm i maptalks-gl
npm i maptalks.tileclip

CDN

<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
} 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
transformTile(options) Tile reprojection
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

Types

export type postProcessingOptionsType = {
    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
}

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 
}

//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 
}

Method Details

all methods return Promise with cancel() method

  • getTile(options) get tile ImageBitmap by fetch in worker, return Promise
    • options.url:tile url or tiles urls
    • ...fetchOptionsType fetchOptionsType params
    • ...postProcessingOptionsType postProcessingOptionsType params
    • ...returnResultType returnResultType 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, return Promise. When the level exceeds the maximum level, tiles will be automatically cut
    • options.x:tile col
    • options.y:tile row
    • options.z:tile zoom
    • options.maxAvailableZoom:tile The maximum visible level, such as 18
    • options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x} or tiles urlTemplates
    • options?.subdomains:subdomains, such as [1, 2, 3, 4, 5]
    • ...fetchOptionsType fetchOptionsType params
    • ...postProcessingOptionsType postProcessingOptionsType params
    • ...returnResultType returnResultType 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);
})
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);
})
  • transformTile(options) Reprojection tile in worker, return Promise
    • options.x:tile col
    • options.y:tile row
    • options.z:tile zoom
    • options.projection: Projection code, only support EPSG:4326, EPSG:3857. Note that only global standard pyramid slicing is supported
    • options.maxAvailableZoom:tile The maximum visible level, such as 18
    • options.urlTemplate:tile urlTemplate.https://services.arcgisonline.com/ArcGIS/rest/services/Word_Imagery/MapServer/tile/{z}/{y}/{x} or tiles urlTemplates
    • options?.subdomains:subdomains, such as [1, 2, 3, 4, 5]
    • options?.isGCJ02: Is it the isGCJ02 coordinate system
    • options?.errorLog: Is there a printing error
    • ...fetchOptionsType fetchOptionsType params
    • ...postProcessingOptionsType postProcessingOptionsType params
    • ...returnResultType returnResultType params
const {
    x,
    y,
    z
} = tile;
const maxAvailableZoom = 18;
tileActor.transformTile({
    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.transformTile({
    ...
});
//mock cancel fetch task
setTimeout(() => {
    promise.cancel();
}, 2000);

promise.then((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 worker
    • Polygon/MultiPolygon GeoJSON 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 . return Promise

    • maskId: mask id
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
const maskId = 'china';
const result = tileActor.maskHasInjected(maskId);
  • clipTile(options) clip tile by mask . return Promise
    • options.tile:tile ImageBitmap data
    • options.tileBBOX:tile BBOX [minx,miny,maxx,maxy]
    • options.projection: Projection code, such as : EPSG:3857
    • options.maskId:mask key
    • options?.tileSize:tile size
    • options?.reverse:whether or not clip reverse
    • options?.bufferSize: Buffer contour pixel size
    • ...returnResultType returnResultType 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 . return Promise

    • options.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, return Promise
    • options.url:tile url
    • options.terrainType:'mapzen' | 'tianditu' | 'cesium'|'arcgs'|'qgis-gray'
    • options?.terrainWidth default is 65
    • options?.minHeight min height when terrainType is 'qgis-gray'
    • options?.maxHeight max height when terrainType is 'qgis-gray'
    • options?.tileSize default value is 256
    • options?.terrainColors Colored terrain tiles. Color interpolation based on altitude
    • ...fetchOptionsType fetchOptionsType params
    • ...returnResultType returnResultType 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, return Promise
    • options.tile:tile data, is ImageBitMap
    • options.colors: Color Mapping Table
    • ...postProcessingOptionsType postProcessingOptionsType params
    • ...returnResultType returnResultType 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 , return Promise
    • options.tiles:tiles collection
    • ...returnResultType returnResultType 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, return Promise
    • options.url:image url or images urls
    • ...fetchOptionsType fetchOptionsType params
    • ...postProcessingOptionsType postProcessingOptions params
    • ...returnResultType returnResultType 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 . return Promise

    • options.url:image url
    • options.imageBBOX:image BBOX [minx,miny,maxx,maxy]. Note that the coordinates of the bounding box should be consistent with the projected image
    • options.imageId:image url
    • ...fetchOptionsType fetchOptionsType 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 . return Promise

    • imageId: image id
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
const imageId = 'china';
const result = tileActor.imageHasInjected(maskId);
  • getImageTile(options) get tile data from image . return Promise
    • options.tileBBOX:tile BBOX [minx,miny,maxx,maxy]
    • options.projection: Projection code, such as : EPSG:3857
    • options.imageId:mask key
    • options?.tileSize:tile size
    • ...postProcessingOptionsType postProcessingOptionsType params
    • ...returnResultType returnResultType 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, return Promise
    • options.url:tile url or tiles urls
    • ...fetchOptionsType fetchOptionsType 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],
            indexedDBCache: true
        }).then(buffer => {
            callback(null, buffer);

        }).catch(error => {
            console.log(error);
            callback(error);
        })
    };
});

About

maptalks TileLayer clip tool

Resources

License

Stars

Watchers

Forks

Packages

No packages published