常用的插件集合
官方维护的常见插件如下:
插件 | 描述 | 仓库地址 | 作者 |
---|---|---|---|
maptalks.three | threejs插件包 | github | maptalks |
maptalks.snap | 绘制编辑吸附包 | github | maptalks |
maptalks.esri | arcgis服务加载插件包 | github | maptalks |
maptalks.mapboxgl | mapbox底图插件包 | github | maptalks |
maptalks.routeplayer | 轨迹播放插件 | github | maptalks |
maptalks.mapsync | 地图视角同步控件 | github | maptalks |
maptalks.query | maptalks 图层数据查询插件 | github | maptalks |
maptalks.tileclip | maptalks 瓦片剪裁工具 | github | maptalks |
maptalks.tileclusterlayer | 点的瓦片聚合包 | github | deyihu |
maptalks.modelcontrol | 模型拖拽缩放插件包 | github | deyihu |
maptalks.tiflayer | 加载tif文件 | github | deyihu |
maptalks.heatlayer | 热区图插件 | github | deyihu |
gifloop | gif解析工具,可以和maptalks配和使用来加载gif | github | deyihu |
TIP
这些包的umd
包导出的命名空间都是maptalks
,会和核心库自动合并的,以three插件为例, 导出的ThreeLayer
会自动挂载到window.maptalks
下
如果你是以ESM
的方式使用,那就是
import { Map } from "maptalks";
import { ThreeLayer } from "maptalks.three";
import { HeatLayer } from "maptalks.heatlayer";
// .....
tileclip插件
maptalks.tileclip 是个瓦片处理工具小插件,主要提供瓦片请求,瓦片剪裁,瓦片合并,瓦片重投影等功能。
插件特点:
- 体积小巧
- 所有逻辑在worker里,不会卡主线程的
- 数据交互是ImageBitMap,性能更好
- safari兼容性很差,注意兼容性判断和控制
这里特地来介绍下其用法
瓦片请求代理
tileActor
.getTile({
url: maptalks.Util.getAbsoluteURL(url),
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
- 支持批量请求和合并(可以避免多个TileLayer,可以提供更好的性能,比如常见的影像图和路网合并)
WARNING
批量的瓦片要求投影相同,一般都是同一批次的瓦片集合,比如天地图的影像图和天地图的路网图层
tileActor
.getTile({
url: [ur1, url2],
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
- 支持超时设置
tileActor
.getTile({
url: maptalks.Util.getAbsoluteURL(url),
timeout: 2000,
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
- 支持取消
const promise = tileActor.getTile({
url: maptalks.Util.getAbsoluteURL(url),
timeout: 2000,
});
//mock cancel fetch task
setTimeout(() => {
promise.cancel();
}, 2000);
promise
.then((image) => {})
.catch((error) => {
console.error(error);
});
- 支持配置fetch请求配置(token验证啥的)
tileActor
.getTile({
url: maptalks.Util.getAbsoluteURL(url),
timeout: 2000,
fetchOptions: {
headers: {
//if need
token: "xxx",
},
},
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
瓦片切割
当瓦片层级溢出时会自动切割瓦片,比如瓦片最大瓦片层级18,当zoom=19时会自动的切割18的瓦片生成新的小瓦片
const { x, y, z } = tile;
const urlTemplate = baseLayer.options.urlTemplate;
const maxAvailableZoom = 18;
tileActor
.getTileWithMaxZoom({
x,
y,
z,
urlTemplate,
maxAvailableZoom,
// filter: 'sepia(100%) invert(90%)'
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
其同样支持:
- 批量请求
- 超时
- 取消
- fetchOptions等
瓦片剪裁
目前maptalks的TileLayer的webgl剪裁还没有实现,如果我们需要剪裁TileLayer可以用其来替代
tileActor
.getTile({ url: maptalks.Util.getAbsoluteURL(url) })
.then((imagebitmap) => {
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);
});
- 支持任意投影。非常规的投影,我们只需要把投影后的数据作为mask注入即可
- 支持剪裁反转,可以用来挖洞,搞地下等业务场景
tileActor
.getTile({ url: maptalks.Util.getAbsoluteURL(url) })
.then((imagebitmap) => {
tileActor
.clipTile({
tile: imagebitmap,
tileBBOX: baseLayer._getTileBBox(tile),
projection: baseLayer.getProjection().code,
tileSize: baseLayer.getTileSize().width,
maskId,
reverse: true,
})
.then((image) => {
callback(image);
})
.catch((error) => {
//do some things
console.error(error);
});
})
.catch((error) => {
//do some things
console.error(error);
});
瓦片重投影
支持标准的全球金字塔的切图规则,支持:
- EPSG:4326=>EPSG:3857
- EPSG:3857=>EPSG:4326
- 支持火星坐标的瓦片转成WGS84(比如高德的瓦片服务和天地图叠加)
e.renderer.loadTileBitmap = function (url, tile, callback) {
const { x, y, z } = tile;
tileActor
.transformTile({
x,
y,
z,
urlTemplate,
projection: "EPSG:4326",
maxAvailableZoom: 18,
isGCJ02: true,
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
};
这样我们就可以加载不同的投影的瓦片了,比如地图是EPSG:3857, 我这时我们就可以以EPSG:3857的方式加载EPSG:4326,反之亦然
地形瓦片编码
目前maptalks内置了mapbox,天地图,ceisum的数据解码,但是用户侧仍然希望加载一些其他格式的地形数据 (例如mapzen/arcgis等的地形瓦片),针对这个需求我们将会:
- 地形支持用户自定义加载瓦片和地形解码
- 针对用户自定义返回的数据格式将支持mapbox rgb tile(这个将是内部支持自定义的唯一格式)
- 任何其他任何格式的地形数据需要用户侧把数据转换成mapbox rgb tile
maptalks.tileclip插件提供了一些常见地形服务的编码:
- mapzen
- cesium
- 天地图
- arcgis
- qgis灰度图
其主要价值和意义是方便用户自定义地形服务,这个插件把用户常见的工作做了而已
所谓的编码本质就是:将其他格式的地形服务解码出来,根据解码出来的高度值在编码成mapbox terrain rgb tile而已
e.renderer.loadTileBitmap = function (url, tile, callback) {
tileActor
.encodeTerrainTile({
url: maptalks.Util.getAbsoluteURL(url),
terrainType: "mapzen",
// timeout: 5000
})
.then((imagebitmap) => {
callback(imagebitmap);
})
.catch((error) => {
//do some things
console.error(error);
});
};
如果你有其他格式的地形服务编码可以给插件提issue,或者自己自行实现返回给地形图层即可
大图片切割
一般业务里在前端我们是不会加载大的图片的(几十甚至百兆的),如果你一定要加载
由于浏览器底层限制(canvas/webgl等)的原因加载大尺寸的图片会报错的
这时我们需要将大图片进行切割的
const bbox = [120, 31, 121, 32];
const layer = new maptalks.VectorLayer("layer").addTo(map);
const extent = new maptalks.Extent(bbox);
const polygon = new maptalks.Polygon(extent.toArray()).addTo(layer);
const imagelayer = new maptalks.ImageLayer("imagelayer", {}).addTo(map);
const prefix = `temp_${imagelayer.getId()}_`;
//清除每次的临时图片资源
function clearCache() {
const caches = maptalks.ResourceProxy.allResource();
const keys = Object.keys(caches).filter((key) => {
return key.includes(prefix);
});
keys.forEach((key) => {
const image = maptalks.ResourceProxy.getResource(key);
if (image && image.close) {
image.close();
}
maptalks.ResourceProxy.removeResource(key);
});
}
//图片加入资源管理工具
function addCache(key, image) {
// const { row, col } = item;
maptalks.ResourceProxy.addResource(key, image);
}
function setImages(result) {
clearCache();
const { width, height, items } = result;
const [minx, miny, maxx, maxy] = bbox;
const ax = (maxx - minx) / width;
const ay = (maxy - miny) / height;
items.forEach((item) => {
const { x, y, width, height, image } = item;
const x1 = minx + x * ax;
const x2 = x1 + width * ax;
const y2 = maxy - y * ay;
const y1 = y2 - ay * height;
//计算每个小图片的包围盒范围
item.bbox = [x1, y1, x2, y2];
});
const images = items.map((item) => {
// console.log(item.image);
const id = maptalks.Util.GUID();
const key = `${prefix}${id}`;
addCache(key, item.image);
return {
//表示从资源池里取资源
url: `$${key}`,
extent: item.bbox,
};
});
imagelayer.setImages(images);
}
let fileUrl;
function readImage() {
if (!fileUrl) {
return;
}
console.log("readimage ing");
tileActor
.imageSlicing({
url: fileUrl,
// returnBlobURL: true,
debug: true,
// filter: 'sepia(100%) invert(90%)'
})
.then((result) => {
console.log(result);
setImages(result);
URL.revokeObjectURL(fileUrl);
console.log("readimage end");
})
.catch((error) => {
console.error(error);
URL.revokeObjectURL(fileUrl);
});
}