Skip to content
目录

常用的插件集合

官方维护的常见插件如下:

插件描述仓库地址作者
maptalks.threethreejs插件包githubmaptalks
maptalks.snap绘制编辑吸附包githubmaptalks
maptalks.esriarcgis服务加载插件包githubmaptalks
maptalks.mapboxglmapbox底图插件包githubmaptalks
maptalks.routeplayer轨迹播放插件githubmaptalks
maptalks.mapsync地图视角同步控件githubmaptalks
maptalks.querymaptalks 图层数据查询插件githubmaptalks
maptalks.tileclipmaptalks 瓦片剪裁工具githubmaptalks
maptalks.tileclusterlayer点的瓦片聚合包githubdeyihu
maptalks.modelcontrol模型拖拽缩放插件包githubdeyihu
maptalks.tiflayer加载tif文件githubdeyihu
maptalks.heatlayer热区图插件githubdeyihu
gifloopgif解析工具,可以和maptalks配和使用来加载gifgithubdeyihu

TIP

这些包的umd包导出的命名空间都是maptalks,会和核心库自动合并的,以three插件为例, 导出的ThreeLayer会自动挂载到window.maptalks
如果你是以ESM的方式使用,那就是

js
import { Map } from "maptalks";
import { ThreeLayer } from "maptalks.three";
import { HeatLayer } from "maptalks.heatlayer";
// .....

tileclip插件

maptalks.tileclip 是个瓦片处理工具小插件,主要提供瓦片请求,瓦片剪裁,瓦片合并,瓦片重投影等功能。

插件特点:

  • 体积小巧
  • 所有逻辑在worker里,不会卡主线程的
  • 数据交互是ImageBitMap,性能更好
  • safari兼容性很差,注意兼容性判断和控制

这里特地来介绍下其用法

瓦片请求代理

js
tileActor
    .getTile({
        url: maptalks.Util.getAbsoluteURL(url),
    })
    .then((imagebitmap) => {
        callback(imagebitmap);
    })
    .catch((error) => {
        //do some things
        console.error(error);
    });
  • 支持批量请求和合并(可以避免多个TileLayer,可以提供更好的性能,比如常见的影像图和路网合并)

merge tiles demo

7FHGC7%7DLS~%7D%7B%40~6BABUQ2MB.png

WARNING

批量的瓦片要求投影相同,一般都是同一批次的瓦片集合,比如天地图的影像图和天地图的路网图层

js
tileActor
    .getTile({
        url: [ur1, url2],
    })
    .then((imagebitmap) => {
        callback(imagebitmap);
    })
    .catch((error) => {
        //do some things
        console.error(error);
    });
  • 支持超时设置
js
tileActor
    .getTile({
        url: maptalks.Util.getAbsoluteURL(url),
        timeout: 2000,
    })
    .then((imagebitmap) => {
        callback(imagebitmap);
    })
    .catch((error) => {
        //do some things
        console.error(error);
    });
  • 支持取消
js
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验证啥的)
js
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);
    });

瓦片切割

images.jfif

当瓦片层级溢出时会自动切割瓦片,比如瓦片最大瓦片层级18,当zoom=19时会自动的切割18的瓦片生成新的小瓦片

getTileWithMaxZoom demo

js
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可以用其来替代

IIK((M2Q)NJ_%5D%40Z%24~XM0OOC.png

js
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注入即可

EPSG:9807 Clip Demo

  • 支持剪裁反转,可以用来挖洞,搞地下等业务场景

%7DPAZT_F1(0NTHK6WWLZF%40(D.png

4Z2F1CR~_RN(%24%5DITEU%60VKM4.png

js
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(比如高德的瓦片服务和天地图叠加)
js
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,反之亦然

4326-transform-3857

3857-transform-4326

地形瓦片编码

目前maptalks内置了mapbox,天地图,ceisum的数据解码,但是用户侧仍然希望加载一些其他格式的地形数据 (例如mapzen/arcgis等的地形瓦片),针对这个需求我们将会:

  • 地形支持用户自定义加载瓦片和地形解码
  • 针对用户自定义返回的数据格式将支持mapbox rgb tile(这个将是内部支持自定义的唯一格式)
  • 任何其他任何格式的地形数据需要用户侧把数据转换成mapbox rgb tile

maptalks.tileclip插件提供了一些常见地形服务的编码:

  • mapzen
  • cesium
  • 天地图
  • arcgis
  • qgis灰度图

其主要价值和意义是方便用户自定义地形服务,这个插件把用户常见的工作做了而已

所谓的编码本质就是:将其他格式的地形服务解码出来,根据解码出来的高度值在编码成mapbox terrain rgb tile而已

mapzen terrain encode demo

arcgis terrain encode demo

qgis gray terrain encode demo

js
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等)的原因加载大尺寸的图片会报错的

REHPJtnQSAXINOPBiS6hh.png

这时我们需要将大图片进行切割的

imageslicing demo

js
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);
        });
}

maptalks教程 document auto generated by mdpress