diff --git a/dev-demos/features/tile/raster/satellite.tsx b/dev-demos/features/tile/raster/satellite.tsx index f2e3610b66..c0b63f6c78 100644 --- a/dev-demos/features/tile/raster/satellite.tsx +++ b/dev-demos/features/tile/raster/satellite.tsx @@ -1,6 +1,11 @@ import { Scene, RasterLayer } from '@antv/l7'; import { GaodeMap } from '@antv/l7-maps'; import React, { useEffect } from 'react'; +import { encodeParams, sign } from './signGenerator'; +const canvas = document.createElement('canvas'); +canvas.width = 256; +canvas.height = 256; +const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; export default () => { useEffect(() => { @@ -8,42 +13,139 @@ export default () => { id: 'map', pickBufferScale: 1.0, map: new GaodeMap({ - center: [121.268, 30.3628], + center: [127.471855, 46.509622], // 绥化市-北林区 pitch: 0, style: 'blank', zoom: 10, }), }); - const layerTile = new RasterLayer({ - zIndex: 1, - }); - layerTile.source( - '//t{0-4}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=f1f2021a42d110057042177cd22d856f', - { - parser: { - type: 'rasterTile', - tileSize: 256, + const Base64toArrayBuffer = (base64Data) => { + const padding = '='.repeat((4 - (base64Data.length % 4)) % 4); + const base64 = (base64Data + padding).replace(/-/g, '+').replace(/_/g, '/'); + + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; + } + + const getUrlQueryParams = (url = location.search): any => { + const params = {}; + const keys = url.match(/([^?&]+)(?==)/g); + const values = url.match(/(?<==)([^&]*)/g); + for (const index in keys) { + // @ts-ignore + params[keys[index]] = values?.[index]; + } + return params; + }; + + + // const layerTile = new RasterLayer({ + // zIndex: 1, + // }); + // layerTile.source( + // '//t{0-4}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=f1f2021a42d110057042177cd22d856f', + // { + // parser: { + // type: 'rasterTile', + // tileSize: 256, - }, - }, - ); + // }, + // }, + // ); const layerTile2 = new RasterLayer({ zIndex: 0, - }); - layerTile2.source( - 'http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', + }).source( + // 'http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', + `https://openapi.alipay.com/gateway.do?x={x}&y={y}&z={z}&index=1001&crow_type=101`, { parser: { type: 'rasterTile', + dataType:'customArrayBuffer', tileSize: 256, - }, + + getCustomData: ({x,y,z},callback)=>{ + const biz_content = { x, y, z, index:1001, crow_type:101 }; + const newUrl = sign('anttech.ai.cv.rs.xytile.get', biz_content, { + charset: 'utf-8', + version: '1.0', + }); + + const signStr = Object.keys(encodeParams(newUrl)) + .sort() + .map((key) => { + let data = encodeParams(newUrl)[key]; + if (Array.prototype.toString.call(data) !== '[object String]') { + data = JSON.stringify(data); + } + return `${key}=${data}`; + }) + .join('&'); + + const url = `https://openapi.alipay.com/gateway.do?${signStr}`; + fetch(url).then(res=>res.json()).then(response=>{ + const bufferData = Base64toArrayBuffer(response?.anttech_ai_cv_rs_xytile_get_response?.image || ''); + callback(null, bufferData); + + }) + }, + format: async (data: any) => { + // console.log(bands) + const blob: Blob = new Blob([new Uint8Array(data)], { + type: 'image/png', + }); + const img = await createImageBitmap(blob); + ctx.clearRect(0, 0, 256, 256); + ctx.drawImage(img, 0, 0, 256, 256); + const imgData = ctx.getImageData(0, 0, 256, 256).data; + const channelR: number[] = []; + const channelG: number[] = []; + const channelB: number[] = []; + for (let i = 0; i < imgData.length; i += 4) { + const R = imgData[i]; + const G = imgData[i + 1]; + const B = imgData[i + 2]; + channelR.push(R); + channelG.push(G); + channelB.push(B); + } + return [ + { rasterData: channelR, width: 256, height: 256 }, + // { rasterData: channelG, width: 256, height: 256 }, + // { rasterData: channelB, width: 256, height: 256 }, + ]; + }, + // operation: { + // type:'rgb', + // options:{ + // RMinMax:[0,255], + // GMinMax:[0,255], + // BMinMax:[0,255], + // } + // }, + } + }, ); + layerTile2.style({ + opacity: 1, + clampLow: false, + clampHigh: false, + domain: [0, 150], + rampColors: { + colors: ['rgba(0, 0, 0, 0)','rgba(0, 0, 0, 0)','#EAC300','#EAC300' ], + positions: [0,0.2,0.6,1], + }, + }); scene.on('loaded', () => { - scene.addLayer(layerTile); + // scene.addLayer(layerTile); scene.addLayer(layerTile2); }); }, []); diff --git a/dev-demos/features/tile/raster/signGenerator.ts b/dev-demos/features/tile/raster/signGenerator.ts new file mode 100644 index 0000000000..3ca68c6548 --- /dev/null +++ b/dev-demos/features/tile/raster/signGenerator.ts @@ -0,0 +1,114 @@ +import moment from 'moment'; +import JSEncrypt from 'jsencrypt'; +import CryptoJS from 'crypto-js'; + +// const key = +// 遥感地图网页应用 2021003154649392 私钥 +// 'MIIEpQIBAAKCAQEAmGPwXSi1MjuIvEh0Gl75d62tTQF/vzMkFDuLjx5RJ/DiSntXbmVV3ZJjICNOKLaWCemHvBerJfXtDQUAJWVo8FwJJQrla3oGHQp38vUNtRLGQQkozzWeSslaXZc/cEDLBfjogzk4jojEXuFpgbzY0BJZg+KHh6k7TK/Tf6Zrn19fxVojeAx8njguIjlDbZAtnaNYlq3fYIVzPX3nd/xTQmLwHKjeuJ626i+zdo57oNKHOOStX/0Isf6y4rj8cdPrmxfWDw86vV1Pd378sKL0vejOrS6TLoYG8sMGk8Fi//ecXnY1068vYl2tQOIqHiZb8XGCFIYoNWefvHPsufqkQwIDAQABAoIBAQCAnfDTn7T2tZqdVwVu8HPbF6Gp2bcJF8++p9cNLwhODpffRySuzyZegNva1xFzeU8/BHQEQ3G2805ka7EI3wNnwjYRppWlVXLtddVxIHS2PCdJ4sInyNhVxIXZcfsf8f+ohcEwZ84dNr+OWO+kiU/wpVwZ3MqIrEOZYNi/5yT0d8jdNNMsDGeGwGzULN/eIqgiF9l3vbn4w79WoUTOll6yxC/8ZYa9TX8yFWGKjElmr6K/c2x2NuRpToQgYv5iqN6m1biUNmkoqQ3cbysGAKP2Vb7S9GEjI6Kcp3TwfyrE65s7pS0aU6lNfuqzjNuulRDnxAXP2+fHSOcZBFQSu7TpAoGBAOPO+9jbezq6eQ9seruN8UMriTiFRU02E+HNihCbM2Vvwbb4wet25dJYL4TqRT+CawQA7XQ85/8QCl0mpUOFDJa6agYSby2Eai2IDZ5KxvdDNXDuQv+R4Wh2TV3xjK4tyrUZhYGZZ8g1MrxuilvR7/gG41pl0X28aDHxzjWgV4JtAoGBAKs/sccl4QbINq2AUB/rWKFv2SNVMTpq13/PtRCeVe49Gin9SpEuYm5XD/0n9hNRDiYul8Hwcq1ff5O+bEi+UJyqyVDjJs82onhCJOY+hWkTcluQCkjKNqKyTciys0gsZorY8/oxzkZ7aBQSkhZ4+ReR8tf2Ti46QTB1ft/55xNvAoGBAKINb6JIH1UbqVqLdJNO2b1Kjwah5zaRrXsHV5uQi/MwmMCsHGZ/4eTLzqHidPhEshPbBQ+W9AHBS14QS6fIUbg3S4yeOHBMratOCUH9N6RVLwLyur5K6+n/nfGiDs0ozfYd/Za/pdAJ59mbWNkQcoAhhkGcBHZJPGWq+WG0egvRAoGBAJnLPTS17w7xNjHBf7P634E0etTBiNGG7HyLpHgFSvUHiPzWzmXuO1YO+HwJrHSSodtmksII2GSd1GxyYrs9uBXLR7tOFSeZUHYiKRNiaNwCK/zRMntGp6Sb70FkQ6B4x6rAxvQWUMN5xvHn760g/cvONkL/oBziEnObwdMSkxUfAoGAQ2zEYHRAas8lichIbcrmfvtBUSfAKIEJO+rXeNoxjEKPHRERlCVnAs/O5OmxbB+oZzyrK16+LGM+3jnDEf0kdT49cqkMK1n8CJR2W9MrbK8jMFZOR0XW7vQ0J0vnc5R6vobf3U4jFq8nVK3ehOUicVIqre6LEiHKVQUqC3y+Vl4='; +// 遥感地图网页应用 2021003154694648 私钥 +// 'MIIEpQIBAAKCAQEA1N165ud87194oMhMT4oCsoF+DenzjhRMEo4WxlSbWsyGRExQh7MSZ+aZZS8RWDLSfy3VNpUhpYllDiGg/Ng2q6SE4inU2O5IBghBKWJoznld+0CiUCKFEFukRYtUszedHiN5rlfE4E/PsUF0RiV8VRCPMdsHsfQvwYJ54CAuFKKcD4FLHrBmHb7X7D569gGJYEyf4L5iBxLoFgoiMnUwoY2SZr4ge+kW94RvNuUCWHDDA8o5/Z8SMztotrwRE1utHgqbPSV1wIn1vppQs8tH2qp8m0s5lT11iEqoJ6NPNlglU6s/4p7CV4genTvXOPyGqVKxz1i29m2LebU0khSwzwIDAQABAoIBAQCyEOBp3kXV3HCFV2j2tIWTG93997JFLVeBwhjtKgOXjjXXVlubWMJR5kZ1rUz+Ee2idA3DDjfKSUge7STFvnzlUsfShZnHKnVXjnosC2WPK1nh/2yISogzaeXeQzLEhQZLGvQEUumfl0QvjIie0WbTpfmThB1I0PNOFj6rrV++482DNdOfIGPAjWb+Id32vbQxgzUtFNsSno85l4EFRZQ9hfXsljxRuDeA4VLUWo7ZpOztNVO95emhAWgWQ2S0/YNgVO04UVVfiCQSqa80HpNz4l+4WnCQEDKrOA4kY64h988g7MG1bN9uaV9zQ6u6wh/Ijb4vvIL/ShwaQHvWtE5RAoGBAPJFgPcyv7Eatg6WMM+bW5ihf6Q2x3KUvocAtnhjLb0DNGsewJGknCU0dE5BQN0TdbV3H1mncLaBOl7XFT2Rvgs0KdUzCBi60uyMtFSRnty/UarE5vdUH8pKWX+OniRcMr9nYD1k/CxWrBKfhOwi8rxgaIJkbIjzHWzwKbZoeEvXAoGBAODtZSKmBc83v5fRR4eSr0QPDzjvzEOZc/g5AOzKhJx+2d496t25bULuxWEsHonvZweLNZraM2wV/lM6wLbmEj1FYHvcuU9TvInceqCbKcXSCkZOpqyuUKJGQVHIAswno07cekp2SFB+1OABYSvEWqVeYg3rqzVjGqVrvuBae2PJAoGBAMTzJbVPhzAVk9zl0cZj+KFq4JYBhkAqlXywYqYZkkwut8VBWbDMjbddHhOjznQqZq1fqpe6m9Fx2p7Q4M6NlV4MSNmtw64+6kss00hQnUG9MknOCikUNUfBC2K78OmEHiklg8JFPw9YYkg9b9R7ULM8+JjPxL/MS6aM0owb/3c/AoGBAKXir2okY7h19xmywTxdlGFvcdyeDln0vLDe6a25lqAMdgYQSD2KWei5TFzkOwmjxKqtorU4JCCc/9rGRAcgG2eQ2R3ApfK5YR2Tu+TjSqWYyPcdXpOQY+uqQNZd2qJSwYCR3qc4IREs2Tb0DYRH5kp8F3kIzFYtZyOFGVtBoCrxAoGAdZnOWrUyXx6OJg98+TtV5HMkNIVbdGjjoJvmvxgXnABHKbyRjnP4WxARQiiBga/qh07+Ovo4EkbyWf5oqkogzY+F969A5zeSQCuJ7Gu6HzBdjcAIRzq8hDqBiFSskYBFz/Ohn8JL8Y757JXYgjur6AppOk4KElC0o/ZOXkPjg7k='; +// RSA 签名 +const encrypt = new JSEncrypt(); +// encrypt.setPrivateKey(key); + +const AK = { + appId: '2021003154694648', // 遥感地图网页应用 + key: + 'MIIEpQIBAAKCAQEA1N165ud87194oMhMT4oCsoF+DenzjhRMEo4WxlSbWsyGRExQh7MSZ+aZZS8RWDLSfy3VNpUhpYllDiGg/Ng2q6SE4inU2O5IBghBKWJoznld+0CiUCKFEFukRYtUszedHiN5rlfE4E/PsUF0RiV8VRCPMdsHsfQvwYJ54CAuFKKcD4FLHrBmHb7X7D569gGJYEyf4L5iBxLoFgoiMnUwoY2SZr4ge+kW94RvNuUCWHDDA8o5/Z8SMztotrwRE1utHgqbPSV1wIn1vppQs8tH2qp8m0s5lT11iEqoJ6NPNlglU6s/4p7CV4genTvXOPyGqVKxz1i29m2LebU0khSwzwIDAQABAoIBAQCyEOBp3kXV3HCFV2j2tIWTG93997JFLVeBwhjtKgOXjjXXVlubWMJR5kZ1rUz+Ee2idA3DDjfKSUge7STFvnzlUsfShZnHKnVXjnosC2WPK1nh/2yISogzaeXeQzLEhQZLGvQEUumfl0QvjIie0WbTpfmThB1I0PNOFj6rrV++482DNdOfIGPAjWb+Id32vbQxgzUtFNsSno85l4EFRZQ9hfXsljxRuDeA4VLUWo7ZpOztNVO95emhAWgWQ2S0/YNgVO04UVVfiCQSqa80HpNz4l+4WnCQEDKrOA4kY64h988g7MG1bN9uaV9zQ6u6wh/Ijb4vvIL/ShwaQHvWtE5RAoGBAPJFgPcyv7Eatg6WMM+bW5ihf6Q2x3KUvocAtnhjLb0DNGsewJGknCU0dE5BQN0TdbV3H1mncLaBOl7XFT2Rvgs0KdUzCBi60uyMtFSRnty/UarE5vdUH8pKWX+OniRcMr9nYD1k/CxWrBKfhOwi8rxgaIJkbIjzHWzwKbZoeEvXAoGBAODtZSKmBc83v5fRR4eSr0QPDzjvzEOZc/g5AOzKhJx+2d496t25bULuxWEsHonvZweLNZraM2wV/lM6wLbmEj1FYHvcuU9TvInceqCbKcXSCkZOpqyuUKJGQVHIAswno07cekp2SFB+1OABYSvEWqVeYg3rqzVjGqVrvuBae2PJAoGBAMTzJbVPhzAVk9zl0cZj+KFq4JYBhkAqlXywYqYZkkwut8VBWbDMjbddHhOjznQqZq1fqpe6m9Fx2p7Q4M6NlV4MSNmtw64+6kss00hQnUG9MknOCikUNUfBC2K78OmEHiklg8JFPw9YYkg9b9R7ULM8+JjPxL/MS6aM0owb/3c/AoGBAKXir2okY7h19xmywTxdlGFvcdyeDln0vLDe6a25lqAMdgYQSD2KWei5TFzkOwmjxKqtorU4JCCc/9rGRAcgG2eQ2R3ApfK5YR2Tu+TjSqWYyPcdXpOQY+uqQNZd2qJSwYCR3qc4IREs2Tb0DYRH5kp8F3kIzFYtZyOFGVtBoCrxAoGAdZnOWrUyXx6OJg98+TtV5HMkNIVbdGjjoJvmvxgXnABHKbyRjnP4WxARQiiBga/qh07+Ovo4EkbyWf5oqkogzY+F969A5zeSQCuJ7Gu6HzBdjcAIRzq8hDqBiFSskYBFz/Ohn8JL8Y757JXYgjur6AppOk4KElC0o/ZOXkPjg7k=', +}; + +const openAPIConfig: any = { + gateway: 'http://openapi.stable.dl.alipaydev.com/gateway.do', + timeout: 5000, + charset: 'utf-8', + version: '1.0', + appId: '2021003154694648', + camelcase: false, +}; + +export async function callByOpenAPI( + method: string, + // modelId: string, + // version: string, + // appId: string = '', + bizContent: Object, +) { + const params = sign(method, bizContent, openAPIConfig); + const encodedParams = encodeParams(params); + // console.log('encodedParams :>> ', encodedParams); + return encodedParams; +} + +/** + * 签名 + * @description https://opendocs.alipay.com/common/02kf5q + * @param {string} method 调用接口方法名,比如 alipay.ebpp.bill.add + * @param {object} bizContent 业务请求参数 + * @param {object} config sdk 配置 + */ +export function sign(method: string, bizContent: any = {}, config: any): any { + const signParams = Object.assign({ + method, + appId: config.appId || AK.appId, + charset: config.charset, + version: config.version, + signType: 'RSA2', + timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), + // appAuthToken: '202210BB64237396751c42aa9c225985256e2D92', + // ws_service_url: 'mysearchgw-36.gz00b.dev.alipay.net:12200', // 可选,开发环境需要传,预发环境不需要传 + }); + + encrypt.setPrivateKey(config.key || AK.key); + + if (bizContent) { + signParams.bizContent = JSON.stringify(toSnakeCases(bizContent)); + } + + // params key 驼峰转下划线 + const deCamelizeParams = toSnakeCases(signParams); + + // 排序 + const signStr = Object.keys(deCamelizeParams) + .sort() + .map((key) => { + let data = deCamelizeParams[key]; + if (Array.prototype.toString.call(data) !== '[object String]') { + data = JSON.stringify(data); + } + return `${key}=${data}`; + }) + .join('&'); + + // console.log('signStr :>> ', signStr); + + // 计算签名 + const sign = RSAEncrypt(signStr); + return Object.assign(deCamelizeParams, { sign }); +} + +function RSAEncrypt(signStr: string) { + const start = Date.now(); + const encrypted = encrypt.sign(signStr, CryptoJS.SHA256, 'sha256'); + // console.log('encrypted :>> ', encrypted, Date.now() - start); + return encrypted; +} + +function toSnakeCases(params: any) { + const out: { [key in string]: any } = {}; + Object.keys(params).forEach((key) => { + const newKey = key.replace( + /([A-Z])/g, + (match) => '_' + match.toLowerCase(), + ); + out[newKey] = params[key]; + }); + return out; +} + +export function encodeParams(params: any) { + const out: { [key in string]: any } = {}; + Object.keys(params).forEach((key) => { + out[key] = encodeURIComponent(params[key]); + }); + return out; +} diff --git a/dev-demos/features/tile/rasterImage.md b/dev-demos/features/tile/rasterImage.md index 5cf250bd80..7c2ba1b74e 100644 --- a/dev-demos/features/tile/rasterImage.md +++ b/dev-demos/features/tile/rasterImage.md @@ -3,6 +3,3 @@ raster 图片瓦片 #### 卫星图 - -#### 图片瓦片 - 颜色映射 - \ No newline at end of file diff --git a/package.json b/package.json index c36f698302..d32e80f948 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,9 @@ "webpack-merge": "^4.1.4", "wellknown": "^0.5.0", "worker-loader": "^2.0.0", - "yorkie": "^2.0.0" + "yorkie": "^2.0.0", + "crypto-js": "^4.1.1", + "jsencrypt": "^3.2.1" }, "scripts": { "dev": "npm run worker && dumi dev", diff --git a/packages/core/src/services/source/ISourceService.ts b/packages/core/src/services/source/ISourceService.ts index c0cc9da2b5..54cd2144d5 100644 --- a/packages/core/src/services/source/ISourceService.ts +++ b/packages/core/src/services/source/ISourceService.ts @@ -8,6 +8,8 @@ export enum RasterTileType { IMAGE = 'image', ARRAYBUFFER = 'arraybuffer', RGB = 'rgb', + CUSTOMRGB = 'customRGB', + CUSTOMARRAYBUFFER = 'customArrayBuffer', } export interface IGeojsonvtOptions { @@ -28,6 +30,7 @@ export interface ITileParserCFG { minZoom?: number; maxZoom?: number; zoomOffset?: number; + getCustomData: (tile: { x: number, y: number, z: number },cb:(err:any,data:any)=>void)=>void, extent?: [number, number, number, number]; requestParameters: Partial; updateStrategy?: 'overlap' | 'replace'; diff --git a/packages/layers/src/tile/tileFactory/index.ts b/packages/layers/src/tile/tileFactory/index.ts index d495ef5b7e..9a77b4ab2d 100644 --- a/packages/layers/src/tile/tileFactory/index.ts +++ b/packages/layers/src/tile/tileFactory/index.ts @@ -36,8 +36,10 @@ export function getTileFactory(layer: ILayer) { const { dataType } = layer.getSource().parser; switch(dataType) { case 'rgb': + case 'customRGB': return RasterRGBTile; case 'arraybuffer': + case 'customArrayBuffer': return RasterTile case "terrainRGB" : return RasterTerrainRGBTile diff --git a/packages/source/src/parser/raster-tile.ts b/packages/source/src/parser/raster-tile.ts index bbb4ff5d9a..4c9d9a8965 100644 --- a/packages/source/src/parser/raster-tile.ts +++ b/packages/source/src/parser/raster-tile.ts @@ -6,6 +6,7 @@ import { TilesetManagerOptions, } from '@antv/l7-utils'; import { IParserData } from '../interface'; +import { getCustomData } from '../utils/tile/getCustomData'; import { defaultFormat, getTileBuffer, @@ -61,6 +62,15 @@ export default function rasterTile( cfg?.format || defaultFormat, cfg?.operation, ); + case RasterTileType.CUSTOMARRAYBUFFER: + case RasterTileType.CUSTOMRGB: + return getCustomData( + tile, + // @ts-ignore + cfg?.getCustomData, + cfg?.format || defaultFormat, + cfg?.operation, + ); default: return getTileImage(data as string | string[], tileParams, tile, cfg); } diff --git a/packages/source/src/utils/tile/getCustomData.ts b/packages/source/src/utils/tile/getCustomData.ts new file mode 100644 index 0000000000..f09f78ed12 --- /dev/null +++ b/packages/source/src/utils/tile/getCustomData.ts @@ -0,0 +1,38 @@ +import { IRasterFormat, IBandsOperation } from '../../interface'; +// import { bindCancel } from './request'; +import { + SourceTile, +} from '@antv/l7-utils'; +import { processRasterData } from '../bandOperation/bands'; + +export const getCustomData = async ( + tile: SourceTile, + getCustomData: (tile: { x: number, y: number, z: number }, cb: (err: any, data: any) => void) => void, + rasterFormat: IRasterFormat, + operation?: IBandsOperation, +) => { + return new Promise((resolve, reject) => { + getCustomData({ + x: tile.x, + y: tile.y, + z: tile.z + }, (err, data) => { + if(err){ + reject(err) + } + if (data) { + processRasterData([{data,bands:[0]}], rasterFormat, operation, (err: any, img: any) => { + if (err) { + reject(err); + } else if (img) { + resolve(img); + } + },); + } + + }) + }) + +} + + diff --git a/packages/source/src/utils/tile/getRasterTile.ts b/packages/source/src/utils/tile/getRasterTile.ts index aaec7c3638..f2a75e7af8 100644 --- a/packages/source/src/utils/tile/getRasterTile.ts +++ b/packages/source/src/utils/tile/getRasterTile.ts @@ -36,7 +36,7 @@ export const getTileBuffer = async ( getRasterFile( tile, requestParameters, - (err, img) => { + (err:any, img:any) => { if (err) { reject(err); } else if (img) {