---
title: 图层操作
source: https://vjmap.com/guide/layerop.html
---

# 图层操作

## 增加图层



先增加数据源，再根据数据源增加相应的图层。如增加`wms`栅格图层

```js
map.addSource('wms-test-source', {
    'type': 'raster',
    'tiles': [
        wmsurl
    ],
    'tileSize': 256
});
map.addLayer({
        'id': 'wms-test-layer',
        'type': 'raster',
        'source': 'wms-test-source',
        'paint': { "raster-opacity": 1 }
    }
);
```

[在线示例天地图与CAD图叠加](https://vjmap.com/demo/#/demo/map/web/04webWms)


```js
// 创建为"ids"的geojson数据源
map.addGeoJSONSource('ids');
// 创建关联"ids"的图层id为 'ids-circle'的圆图层
map.addCircleLayer('ids-circle', 'ids', {
    // 根据hover不同的状态设置不同的颜色值
    circleColor: ['case', ['to-boolean', ['feature-state', 'hover']], 'red', '#FFA0FD'],
    // 根据hover不同的状态设置不同的宽度值
    circleStrokeWidth: ['case', ['to-boolean', ['feature-state', 'hover']], 2, 1],
});
// 设置图层的圆的半径
map.setCircleRadius(['ids-circle'], 12);
// 设置鼠标位于此图层上时，鼠标改变为 'pointer‘ 形状
map.hoverPointer(['ids-circle']);
// 设置可以改变此图层的 hover state,用于根据hover不同的状态设置不同的值
map.hoverFeatureState('ids-circle');

// 随机生成一些geojson的点
let data = mapBounds.randomGeoJsonPointCollection(1000);
// 设置数据源数据
map.setData('ids', map.toLngLat(data))
```


<mapFrameEx>
<pre>
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// 打开地图
let res = await svc.openMap({
    mapid: "sys_hello", // 地图ID
    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
    style: vjmap.openMapLightStyle() // div为深色背景颜色时，这里也传深色背景样式
})
if (res.error) {
    // 如果打开出错
    showError(res.error)
    return;
}
// 获取地图范围
let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
// 根据地图范围建立几何投影坐标系
let prj = new vjmap.GeoProjection(mapBounds);
//
// 地图对象
let map = new vjmap.Map({
    container: 'map', // DIV容器ID
    style: svc.rasterStyle(), // 样式，这里是栅格样式
    center: prj.toLngLat(mapBounds.center()), // 设置地图中心点
    zoom: 1, // 设置地图缩放级别
    pitch: 0,
    renderWorldCopies: false // 不显示多屏地图
});
// 关联服务对象和投影对象
map.attach(svc, prj);
await map.onLoad();
// 创建为"ids"的geojson数据源
map.addGeoJSONSource('ids');
// 创建关联"ids"的图层id为 'ids-circle'的圆图层
map.addCircleLayer('ids-circle', 'ids', {
    // 根据hover不同的状态设置不同的颜色值
    circleColor: ['case', ['to-boolean', ['feature-state', 'hover']], 'red', '#FFA0FD'],
    // 根据hover不同的状态设置不同的宽度值
    circleStrokeWidth: ['case', ['to-boolean', ['feature-state', 'hover']], 2, 1],
});
// 设置图层的圆的半径
map.setCircleRadius(['ids-circle'], 12);
// 设置鼠标位于此图层上时，鼠标改变为 'pointer‘ 形状
map.hoverPointer(['ids-circle']);
// 设置可以改变此图层的 hover state,用于根据hover不同的状态设置不同的值
map.hoverFeatureState('ids-circle');
// 随机生成一些geojson的点
let data = mapBounds.randomGeoJsonPointCollection(1000);
// 设置数据源数据
map.setData('ids', map.toLngLat(data))
setInterval(() => {
    data = mapBounds.randomGeoJsonPointCollection(Math.floor(Math.random() * 1000));
    // 模拟更新数据
    map.setData('ids', map.toLngLat(data))
}, 5000)
</pre>
</mapFrameEx>
<br/>
<br/>

其他增加图层方法
```ts
 /** 添加一个图层，给定 id、来源、类型和属性。
    * @param id
    * @param source
    * @param type
    * @param props
    * @param before
    */
addLayerEx(
    id: string,
    source: string,
    type: string,
    props: {},
    before: string | null | undefined
): SourceBoundUtils;

/** 在某个图层之前添加一个图层，给定 id、来源、类型和属性。
    * @param id
    * @param source
    * @param type
    * @param props
    * @param before
    */
addLayerBefore(
    id: string,
    source: SourceOrData,
    type: string,
    props: {},
    before?: string
): SourceBoundUtils | null | undefined;

/** 添加一个类型为“line”的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addLineLayer(id: string, source: string, props: LineLayerStyleProp, before?: string): void;

/** 添加一个类型为“fill”的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addFillLayer(id: string, source: string, props: FillLayerStyleProp, before?: string): void;

/** 添加一个类型为“circle”的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addCircleLayer(
    id: string,
    source: string,
    props: CircleLayerStyleProp,
    before?: string
): void;

/** 添加一个类型为“符号”的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addSymbolLayer(
    id: string,
    source: string,
    props: SymbolLayerStyleProp,
    before?: string
): void;

/** 添加一个类型为`video`的层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addVideoLayer(id: string, source: string, props: object, before?: string): void;

/**添加一个类型为 `raster` 的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addRasterLayer(
    id: string,
    source: string,
    props: RasterLayerStyleProp,
    before?: string
): void;

/** 添加一个类型为“FillExtrusion”的层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addFillExtrusionLayer(
    id: string,
    source: string,
    props: FillExtrusionLayerStyleProp,
    before?: string
): void;

/** 添加一个类型为“Heatmap”的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addHeatmapLayer(
    id: string,
    source: string,
    props: HeatmapLayerStyleProp,
    before?: string
): void;

/** 添加一个类型为“hillshade”的图层。
 * @param id
 * @param props
 * @param before
 * @param source
 */
addHillshadeLayer(
    id: string,
    source: string,
    props: HillshadeLayerStyleProp,
    before?: string
): void;

/** 添加一个 `raster` 源
 @param sourceId ID of the new source.
    @param {object} props Properties defining the source, per the style spec.
    */
addRasterSource(sourceId: string, props: RasterSourceSpecification): SourceBoundUtils;

/** 添加一个 `raster-dem` 源
 @param sourceId ID of the new source.
    @param {object} props Properties defining the source, per the style spec.
    */
addRasterDemSource(sourceId: string, props: RasterDEMSourceSpecification): SourceBoundUtils;

/** 添加一个 `image` 源
 @param sourceId ID of the new source.
    @param {object} props Properties defining the source, per the style spec.
    */
addImageSource(sourceId: string, props: ImageSourceSpecification): SourceBoundUtils;

/** 添加“Video”源
 @param sourceId ID of the new source.
    @param {object} props Properties defining the source, per the style spec.
    */
addVideoSource(sourceId: string, props: VideoSourceSpecification): SourceBoundUtils;
```

## 删除图层

`removeLayer` 从地图的样式中删除具有给定 ID 的图层。如果不存在这样的层，error则会触发一个事件。
```js
if (map.getLayer('state-data')) map.removeLayer('state-data');
```

`removeLayerEx` 移除一个或多个图层，如果不存在，不会报错
```js
map.removeLayerEx('state-data');
map.removeLayerEx(['state-data', "layer2"]);
```

`removeSourceEx` 移除一个或多个源，首先移除所有依赖于它们的层。如果源不存在，则不会提示错误
```js
map.removeSourceEx('ids');
map.removeLayerEx(['source1', "source2"]);
```


## 显示图层

通过设置布局`visibility`属性`显示图层`
```js
map.setLayoutProperty(layerid, "visibility", "visible");
```

或通过图层id显示
```js
map.show(layerid);
```
或
```js
map.toggle(layerid, true)
```

或使数据源相关的图层都可见
```js
map.showSource(sourceid);
```
或
```js
map.toggleSource(sourceid, true)
```

## 隐藏图层

通过设置布局`visibility`属性`隐藏图层`
```js
map.setLayoutProperty(layerid, "visibility", "none");
```

或通过图层id隐藏
```js
map.hide(layerid);
```
或
```js
map.toggle(layerid, false)
```


或使数据源相关的图层都隐藏
```js
map.hideSource(sourceid);
```
或
```js
map.toggleSource(sourceid, false)
```


## 设置图层属性

```js
// 它们都同时作用于多个层： 
map.setLineWidth([ 'mylayer' , 'mylayer-highlight' ], 4 );
map.setLineOpacity( /^ border- / , 0 );
map.setFillColor( layer => layer.source === 'farms' , 'green' );

// 还有一个更熟悉的 setProperty() 形式。
map.setProperty( 'mylayer' , 'line-width' , 3 );
// 更新源数据的更简单方法： 
map.setData( 'mysource' , data);

// 您可以省略 data 参数以清除 GeoJSON 源： 
map.setData( 'mysource' );

// 一次更新多个过滤器。
map.setFilter([ 'buildings-fill' , 'buildings-outline' , 'buildings-label' ], [...]);
```

## 图层事件

通过`map`事件监听，如
```js
map.on("click", layerid, e => {
    console.log(e)
})
```

或

```js
// clickLayer() 类似于 .on('click)'，但可以接受一个数组并向事件中添加一个 'features' 成员用于点击的内容。
map.clickLayer([ 'towns' , 'town-labels' ], e => panel.selectedId = e.features[ 0 ].id);
```

```js
// 悬停在此图层上时使用鼠标“手指”光标。
map.hoverPointer( 'mylayer' );

// 如果您传递多个图层，它会正确处理从一个图层移动到另一个图层
// 悬停在该图层上时使用鼠标“手指”光标。
map.hoverPointer([ 'regions-border' , 'regions-fill' ]);

// 当鼠标移动到该层的特征上时，将“悬停”特征状态设置为真或假。
// 要求特性有一个 `id`。
map.hoverFeatureState( 'mylayer' );

// 想要将悬停功能状态应用于不同的源？
// 例如，您将鼠标悬停在标签上，但想要突出显示周围的边界。
map.hoverFeatureState( 'town-labels' , 'boundaries' , 'town-boundaries' );

// 您还可以添加其他事件处理程序： 
map.hoverFeatureState( 'mylayer' , 'mysource' , 'mysourcelayer' ,
    e => console.log(`Entered ${e.features[0].id}`),
    e => console.log(`Left ${e.oldFeatureid}`);

// 当一个功能悬停或点击时显示一个弹出窗口。
// 第三个参数是一个选项对象，传递给 Popup 构造函数。
// 回调被调用为： (feature, popup) => htmlString 
map.hoverPopup( 'mylayer' , f =>  `<h3> ${f.properties.Name} </h3> ${f.properties.Description} ` , { anchor : 'left' });
map.clickPopup( 'mylayer' , f =>  `<h3> ${f.properties.Name} </h3> ${f.properties.Description} ` , { maxWidth : 500 });

// clickOneLayer 按顺序测试多个层，在第一个命中的 上触发回调。回调被传递 { 功能，功能，层，事件 }。
map.clickOneLayer([ 'town-labels' , 'state-boundaries' ], e => {
    if (e.layer === 'town-labels') {
        setView('town');
        panel.selectedId = e.features[0].id;
    } else if (e.layer === 'state-boundaries') {
        setView('state');
        panel.selectedId = e.features[0].id;
    }
});

// 可选地传入一个额外的回调，该回调为错过所有图层的点击而触发： 
map.clickOneLayer(['town-labels', 'state-boundaries'], e => {...}, e => {
    console.log('Missed everything');
});


// 所有这些函数都返回一个“撤消”函数，删除添加的处理程序：
const remove = map.hoverPopup( 'mylayer' , showPopupFunc);
//...
remove(); // 不再有悬停弹出
```