Skip to content
目录

常见问题

去掉地图中间的红色叉号

js
var map = new maptalks.Map("map", {
    zoom: 1,
    center: [0, 0],
    centerCross: false,
});

map.config({
    centerCross: true,
});
map.config({
    centerCross: false,
});

强制限制地图的边界

地图设置了最大边界后并开启limitExtentOnMaxExtent 即可

WARNING

该特性要求 maptalks 版本>1.0.0-rc.33

js
var map = new maptalks.Map("map", {
    center: [120, 31.498568],
    zoom: 4,
    limitExtentOnMaxExtent: true,
    zoomControl: true,
});

map.on("click", (e) => {
    // console.log(e);
});

const baseLayer = new maptalks.TileLayer("base", {
    repeatWorld: false,
    urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
    subdomains: ["a", "b", "c", "d"],
    attribution:
        '© <a href="http://osm.org">OpenStreetMap</a>  contributors, © <a href="https://carto.com/">CARTO</a> ',
}).addTo(map);

var bbox = [
    118.681640625, 30.929531859423406, 121.318359375, 32.06416211965538,
];
var bbox = [-180, -85, 180, 85];
map.setMaxExtent(bbox);

const layer = new maptalks.VectorLayer("layer").addTo(map);

const debugBBOX = bbox.map((v, index) => {
    const offset = 0.01;
    if (index < 2) {
        return v + offset;
    }
    return v - offset;
});

const line = new maptalks.LineString(new maptalks.Extent(debugBBOX).toArray(), {
    symbol: {
        lineDasharray: [5, 5],
    },
}).addTo(layer);

const polygon = new maptalks.Polygon([map.getMaxExtent().toArray()]);
baseLayer.setMask(polygon);

const point = new maptalks.Marker(map.getMaxExtent().getCenter()).addTo(layer);

多个地图之间进行同步

社区里有个插件 maptalks.mapsync 专门用来 控制多个地图之间的视角同步

计算两点之间的距离

map上提供了computeLength方法了

js
const c1 = new maptalks.Coordinate(0, 0);
const c2 = new maptalks.Coordinate(1, 0);
const len = map.computeLength(c1, c2);

地图容器默认隐藏导致地图初始不能完成

初始化地图时不要将地图容器(dom)设置为不显示display=none,因为地图初始化时需要读取地图容器的大小, 如果使用隐藏的dom容器会导致读取到的地图大小为0,因为地图内部要初始化canvas和webgl等, 如果大小为0可能导致webgl上下文初始化失败

WARNING

注意是地图初始化时,如果地图初始化完成了隐藏地图容器没有这种问题

要想隐藏容器可以通过其他方法:

  • css visibility
  • css zIndex
  • 或者把地图容器移出当前视野外(margin top bottom 等)

怎样修改地图的背景?

地图容器根节点一般是个DIV元素,直接用CSS设置其背景即可

css
.map {
    background: black;
}

高分屏上地图比较大导致地图非常卡?

  • 地图的容器进行CSS缩放(scale)
css
.container {
    width: 400px;
    height: 200px;
    /*https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin*/
    transform: scale(2, 2);
    transform-origin: top left;
}

WARNING

devicePixelRatio的值一般比CSS scale的倍数小,比如地图容器放大 4倍,devicePixelRatio可能设置为 2 倍,即在清晰图允许的情况下 devicePixelRatio值越小,性能越好,所以使用时不要盲目的设置 devicePixelRatio的值为很大的值,否则可能导致地图奔溃

扩大地图的缩放的最大级别

maptalks里地图默认最大到22级别,如果你需要扩大到更大的层级,需要自定义地图的空间投影,把切图的参数(resolutions)调整到你需要的级别即可

js
var MAX_ZOOM = 28;
var spatialReference = {
    projection: "EPSG:3857",
    resolutions: (function () {
        const resolutions = [];
        const d = 2 * 6378137 * Math.PI;
        for (let i = 0; i < MAX_ZOOM; i++) {
            resolutions[i] = d / (256 * Math.pow(2, i));
        }
        return resolutions;
    })(),
    fullExtent: {
        top: 6378137 * Math.PI,
        left: -6378137 * Math.PI,
        bottom: -6378137 * Math.PI,
        right: 6378137 * Math.PI,
    },
};

// const spatialReference4326 = {
//     projection: "EPSG:4326",
//     fullExtent: {
//         top: 90,
//         left: -180,
//         bottom: -90,
//         right: 180,
//     },
//     resolutions: (function () {
//         const resolutions = [];
//         for (let i = 0; i < MAX_ZOOM; i++) {
//             resolutions[i] = 180 / (Math.pow(2, i) * 128);
//         }
//         return resolutions;
//     })(),
// };

var map = new maptalks.Map("map", {
    center: [-0.113049, 51.498568],
    zoom: 14,
    spatialReference: spatialReference,
    baseLayer: new maptalks.TileLayer("base", {
        maxAvailableZoom: 20,
        urlTemplate:
            "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
        subdomains: ["a", "b", "c", "d"],
        attribution:
            '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>',
    }),
    layers: [new maptalks.VectorLayer("v")],
});

具体的例子Customize map's resolutions

地图添加了天空盒后,底图看不见了

maptalks里 地图的baseLayer是最底下的图层,在地图里会第一个绘制baseLayer,而天空盒是在baselayer之后绘制的, 从而导致baselayer被天空盒盖住了,解决方式就是把baseLayer放到GroupGLLayaer

js
const baseLayer = new maptalks.TileLayer("base", {
    urlTemplate:
        "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
    subdomains: ["a", "b", "c", "d"],

    spatialReference: {
        projection: "EPSG:3857",
    },
});

const groupLayer = new maptalks.GroupGLLayer("group", [baseLayer], {
    sceneConfig: {
        environment: {
            enable: true,
            mode: 1,
            level: 0,
            brightness: 0,
        },
        shadow: {
            type: "esm",
            enable: true,
            quality: "high",
            opacity: 0.11,
            color: [0, 0, 0],
            blurOffset: 1,
        },
        postProcess: {
            enable: true,
            antialias: {
                enable: true,
                taa: true,
                jitterRatio: 0.25,
            },
            ssr: {
                enable: true,
            },
            bloom: {
                enable: true,
                threshold: 0,
                factor: 0.2,
                radius: 0.105,
            },
            ssao: {
                enable: true,
                bias: 0.08,
                radius: 0.08,
                intensity: 1.5,
            },
            sharpen: {
                enable: false,
                factor: 0.2,
            },
        },
        ground: {
            enable: false,
            renderPlugin: {
                type: "fill",
            },
            symbol: {
                polygonFill: [0.517647, 0.517647, 0.517647, 1],
            },
        },
    },
});
groupLayer.addTo(map);

TIP

注意map里的baseLayer属性需要注释掉

js
var map = new maptalks.Map("map", {
    center: [-0.113049, 51.498568],
    zoom: 14,
    // baseLayer: new maptalks.TileLayer('base', {
    //   urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
    //   subdomains: ["a","b","c","d"],
    //   attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
    // })
});

关于地图的baseLayer

Markdown 官方教程

地图里的baseLayer比较特殊,在地图的所有图层集合里其是第一个被绘制的图层,其特点有:

  • baseLayer表示基础图层,一般用来作为底图参考
  • baseLayer可以是任何图层,TileLayer,VectorLayer,VectorTileLayer

WARNING

一般业务都是用TileLayer作为底图,但是这个不是绝对的,有业务决定,有的底图可能很简单,使用ImageLayer作为底图也是可能的 比如简单的一个地铁的应用,用ImageLayer来加载一个地图图片,上面叠加一些业务图层等

  • 在地图的整个绘制过程中,baseLayer永远是第一个被绘制的图层,即使你把baseLayer的zIndex值设置的很大也不行的,其仍然是第一个被绘制

  • 地图的baseLayer的设置主要方法有:

    • 初始化地图设置了地图的baseLayer属性

      js
      var map = new maptalks.Map("map", {
          center: [-0.113049, 51.498568],
          zoom: 14,
          baseLayer: new maptalks.TileLayer("base", {
              urlTemplate:
                  "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
              subdomains: ["a", "b", "c", "d"],
              attribution:
                  '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>',
          }),
      });
    • 通过地图的setBaseLayer方法设置

    js
    const baseLayer = new maptalks.TileLayer("base", {
        urlTemplate:
            "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
        subdomains: ["a", "b", "c", "d"],
        attribution:
            '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>',
    });
    map.setBaseLayer(layer);
  • 如果你想维持图层的层级关系(zIndex):

    • 不要将一个图层(一般是TileLayer)设置为baseLayer,直接把其加到地图上即可
js
var map = new maptalks.Map("map", {
    center: [-0.113049, 51.498568],
    zoom: 14,
});

const baseLayer = new maptalks.TileLayer("base", {
    urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
    subdomains: ["a", "b", "c", "d"],
    attribution:
        '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>',
});
baseLayer.addTo(map);
  • 如果你想维持地图上图层的三维关系,请把他们加入的GroupGLLayer里即可:
js
const baseLayer = new maptalks.TileLayer("base", {
    urlTemplate: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
    subdomains: ["a", "b", "c", "d"],
    attribution:
        '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>',
});
const groupLayer = new maptalks.GroupGLLayer("group", [baseLayer], {});
groupLayer.addTo(map);

TIP

如果你的业务是强三维的,GroupGLLayer是必须的,把你的所有图层往GroupGLLayer放就是了

WARNING

注意VectorLayer不能被加入到GroupGLLayer

鼠标进入地图后报跨域警告

允许图片和 canvas 跨源使用

maptalks的数据渲染是canvas或者webgl,因为浏览器限制的关系canvas/webgl等是不允许跨域的,例如如下方法等:

js
canvas.toDataURL();
canvas.getImageData();

一般都是因为你的图标,图片,纹理图片等是跨域导致的

解决方法:

  • 资源本地化
  • 服务端允许跨域
  • 服务代理等

导出地图为图片

地图自带了toDataURL方法了

js
map.toDataURL({ save: true });

WARNING

地图自带的方法只能导出地图canvas画布上的内容,地图上的dom元素时不能被导出的,像弹窗啊,比例尺控件啊等

导出地图上的所有内容

这时我们需要借助社区的一些库

  • html2canvas
  • html-to-image
  • 其他开源库等
js
const size = map.getSize();
const { width, height } = size;
htmlToImage
    .toBlob(map.getContainer(), { width, height: height + 100 })
    .then(function (blob) {
        saveFile(blob);
    });

WARNING

外联的css样式需要开启跨域

html
<link
    rel="stylesheet"
    href="./../assets/lib/maptalks/dist/maptalks.css"
    crossorigin="anonymous"
/>

将地图和其他dom元素一起导出

新建一个dom节点,然后把地图和你想要导出的dom一起放进来,然后直接导出这个节点

html
<div class="container" id="container">
    <div class="panel">
        <button>hello</button>
        <button>hello</button>
        <button>hello</button>
        <button>hello</button>
        <button>hello</button>
        <button>hello</button>
        <button>hello</button>
        <button>hello</button>
    </div>
    <div id="map"></div>
    <div>
        <table>
            <thead>
                <tr>
                    <th colspan="2">The table header</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>The table body</td>
                    <td>with two columns</td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
js
htmlToImage
    .toBlob(document.getElementById("container"), {})
    .then(function (blob) {
        saveFile(blob);
    });

VectorLayer渲染的图形远处悬浮

可以调节下地图的maxVisualPitch

js
// default map object
var map = new maptalks.Map("mapDiv", {
    maxVisualPitch: 65,
    center: [117.131072, 31.83786],
});

地图进行强制重绘

一般情况下地图的重绘和图层重绘是有引擎内部控制的,是不需要手动控制的,如果你真的有这个需求你可以:

  • 图层重绘:
js
const renderer = layer.getRenderer();
if (renderer && renderer.setToRedraw) {
    renderer.setToRedraw();
}
  • 地图重绘:
js
const renderer = map.getRenderer();
if (renderer && renderer.setToRedraw) {
    renderer.setToRedraw();
}

WARNING

注意在maptalks内绘制全部是异步的,其完全是游戏渲染的那一套流程,即每帧渲染一次,不是html那种改变html后立马 重绘的,是么意思:

当你设置了图层或者地图重绘后,是不能立马拿到绘制的结果的,必须等到下一帧绘制结束后才能拿到绘制的结果的

地图提供了帧绘制的事件的:

  • framestart
  • frameend
js
map.on("framestart frameend", (e) => {
    //do some things if need
});

This document is generated by mdpress