mirror of https://gitee.com/antv-l7/antv-l7
fix: 还原旧版图层选择控件 Layers
This commit is contained in:
parent
2980c38d77
commit
f706753866
|
@ -1,11 +1,4 @@
|
||||||
import {
|
import { GaodeMap, IControlOption, Logo, Scale, Scene, Zoom } from '@antv/l7';
|
||||||
GaodeMap,
|
|
||||||
IControlOption,
|
|
||||||
Logo,
|
|
||||||
Scale,
|
|
||||||
Scene,
|
|
||||||
Zoom,
|
|
||||||
} from '@antv/l7';
|
|
||||||
import React, { FunctionComponent, useEffect, useRef } from 'react';
|
import React, { FunctionComponent, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
const Demo: FunctionComponent = () => {
|
const Demo: FunctionComponent = () => {
|
||||||
|
|
|
@ -0,0 +1,325 @@
|
||||||
|
import { PositionType } from '@antv/l7-core';
|
||||||
|
import { bindAll, DOM } from '@antv/l7-utils';
|
||||||
|
import Control, { IControlOption } from './baseControl/control';
|
||||||
|
|
||||||
|
interface IInputItem extends HTMLInputElement {
|
||||||
|
layerId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ILayerControlOption extends IControlOption {
|
||||||
|
collapsed: boolean;
|
||||||
|
autoZIndex: boolean;
|
||||||
|
hideSingleBase: boolean;
|
||||||
|
sortLayers: boolean;
|
||||||
|
|
||||||
|
sortFunction: (...args: any[]) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Layers extends Control {
|
||||||
|
private layerControlInputs: any[];
|
||||||
|
private layers: any[];
|
||||||
|
private lastZIndex: number;
|
||||||
|
private handlingClick: boolean;
|
||||||
|
private layersLink: HTMLElement;
|
||||||
|
private baseLayersList: HTMLElement;
|
||||||
|
private separator: HTMLElement;
|
||||||
|
private overlaysList: HTMLElement;
|
||||||
|
private form: HTMLElement;
|
||||||
|
|
||||||
|
constructor(cfg: Partial<ILayerControlOption>) {
|
||||||
|
super(cfg);
|
||||||
|
this.layerControlInputs = [];
|
||||||
|
this.layers = [];
|
||||||
|
this.lastZIndex = 0;
|
||||||
|
this.handlingClick = false;
|
||||||
|
this.initLayers();
|
||||||
|
|
||||||
|
bindAll(
|
||||||
|
[
|
||||||
|
'checkDisabledLayers',
|
||||||
|
'onLayerChange',
|
||||||
|
'collapse',
|
||||||
|
'extend',
|
||||||
|
'expand',
|
||||||
|
'onInputClick',
|
||||||
|
],
|
||||||
|
this,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDefault() {
|
||||||
|
return {
|
||||||
|
collapsed: true,
|
||||||
|
position: PositionType.TOPRIGHT,
|
||||||
|
autoZIndex: true,
|
||||||
|
hideSingleBase: false,
|
||||||
|
sortLayers: false,
|
||||||
|
name: 'layers',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public onAdd() {
|
||||||
|
this.initLayout();
|
||||||
|
this.update();
|
||||||
|
this.mapsService.on('zoomend', this.checkDisabledLayers);
|
||||||
|
this.layers.forEach((layerItem) => {
|
||||||
|
layerItem.layer.on('remove', this.onLayerChange);
|
||||||
|
layerItem.layer.on('add', this.onLayerChange);
|
||||||
|
});
|
||||||
|
return this.container;
|
||||||
|
}
|
||||||
|
|
||||||
|
public addVisualLayer(layer: any, name: string | number) {
|
||||||
|
this.addLayer(layer, name, true);
|
||||||
|
return this.mapsService ? this.update() : this;
|
||||||
|
}
|
||||||
|
public expand() {
|
||||||
|
const { height } = this.renderService.getViewportSize();
|
||||||
|
DOM.addClass(this.container, 'l7-control-layers-expanded');
|
||||||
|
this.form.style.height = 'null';
|
||||||
|
const acceptableHeight = height - (this.container.offsetTop + 50);
|
||||||
|
if (acceptableHeight < this.form.clientHeight) {
|
||||||
|
DOM.addClass(this.form, 'l7-control-layers-scrollbar');
|
||||||
|
this.form.style.height = acceptableHeight + 'px';
|
||||||
|
} else {
|
||||||
|
DOM.removeClass(this.form, 'l7-control-layers-scrollbar');
|
||||||
|
}
|
||||||
|
this.checkDisabledLayers();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public collapse() {
|
||||||
|
DOM.removeClass(this.container, 'l7-control-layers-expanded');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onRemove() {
|
||||||
|
if (!this.mapsService) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.mapsService.off('click', this.collapse);
|
||||||
|
this.layers.forEach((layerItem) => {
|
||||||
|
layerItem.layer.off('remove', this.onLayerChange);
|
||||||
|
layerItem.layer.off('add', this.onLayerChange);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private initLayout() {
|
||||||
|
const className = 'l7-control-layers';
|
||||||
|
const container = (this.container = DOM.create('div', className));
|
||||||
|
const { collapsed } = this.controlOption;
|
||||||
|
// makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released
|
||||||
|
container.setAttribute('aria-haspopup', 'true');
|
||||||
|
const form = (this.form = DOM.create(
|
||||||
|
'form',
|
||||||
|
className + '-list',
|
||||||
|
) as HTMLElement);
|
||||||
|
|
||||||
|
if (collapsed) {
|
||||||
|
this.mapsService.on('click', this.collapse);
|
||||||
|
container.addEventListener('mouseenter', this.expand);
|
||||||
|
container.addEventListener('mouseleave', this.collapse);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.layersLink = DOM.create('a', className + '-toggle', container);
|
||||||
|
const link = this.layersLink;
|
||||||
|
// link.href = '#';
|
||||||
|
link.title = 'Layers';
|
||||||
|
if (!collapsed) {
|
||||||
|
this.expand();
|
||||||
|
}
|
||||||
|
this.baseLayersList = DOM.create('div', className + '-base', form);
|
||||||
|
this.separator = DOM.create('div', className + '-separator', form);
|
||||||
|
this.overlaysList = DOM.create('div', className + '-overlays', form);
|
||||||
|
container.appendChild(form);
|
||||||
|
}
|
||||||
|
private initLayers() {
|
||||||
|
const { baseLayers = {}, overlayers = {} } = this.controlOption;
|
||||||
|
Object.keys(baseLayers).forEach((name: string) => {
|
||||||
|
// baseLayers[name].once('inited', this.update);
|
||||||
|
this.addLayer(baseLayers[name], name, false);
|
||||||
|
});
|
||||||
|
Object.keys(overlayers).forEach((name: any) => {
|
||||||
|
// overlayers[name].once('inited', this.update);
|
||||||
|
this.addLayer(overlayers[name], name, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private update() {
|
||||||
|
if (!this.container) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOM.empty(this.baseLayersList);
|
||||||
|
DOM.empty(this.overlaysList);
|
||||||
|
|
||||||
|
this.layerControlInputs = [];
|
||||||
|
let baseLayersPresent;
|
||||||
|
let overlaysPresent;
|
||||||
|
let i;
|
||||||
|
let obj;
|
||||||
|
let baseLayersCount = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < this.layers.length; i++) {
|
||||||
|
obj = this.layers[i];
|
||||||
|
this.addItem(obj);
|
||||||
|
overlaysPresent = overlaysPresent || obj.overlay;
|
||||||
|
baseLayersPresent = baseLayersPresent || !obj.overlay;
|
||||||
|
baseLayersCount += !obj.overlay ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide base layers section if there's only one layer.
|
||||||
|
if (this.controlOption.hideSingleBase) {
|
||||||
|
baseLayersPresent = baseLayersPresent && baseLayersCount > 1;
|
||||||
|
this.baseLayersList.style.display = baseLayersPresent ? '' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.separator.style.display =
|
||||||
|
overlaysPresent && baseLayersPresent ? '' : 'none';
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private checkDisabledLayers() {
|
||||||
|
const inputs = this.layerControlInputs;
|
||||||
|
let input: IInputItem;
|
||||||
|
let layer;
|
||||||
|
const zoom = this.mapsService.getZoom();
|
||||||
|
|
||||||
|
for (let i = inputs.length - 1; i >= 0; i--) {
|
||||||
|
input = inputs[i];
|
||||||
|
layer = this.layerService.getLayer(input.layerId);
|
||||||
|
|
||||||
|
if (layer && layer.inited) {
|
||||||
|
const minZoom = layer.getMinZoom();
|
||||||
|
const maxZoom = layer.getMaxZoom();
|
||||||
|
|
||||||
|
input.disabled = zoom < minZoom || zoom > maxZoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addLayer(layer: any, name: string | number, overlay: boolean) {
|
||||||
|
if (this.mapsService) {
|
||||||
|
layer.on('add', this.onLayerChange);
|
||||||
|
layer.on('remove', this.onLayerChange);
|
||||||
|
}
|
||||||
|
this.layers.push({
|
||||||
|
layer,
|
||||||
|
name,
|
||||||
|
overlay,
|
||||||
|
});
|
||||||
|
const { sortLayers, sortFunction, autoZIndex } = this.controlOption;
|
||||||
|
if (sortLayers) {
|
||||||
|
this.layers.sort((a, b) => {
|
||||||
|
return sortFunction(a.layer, b.layer, a.name, b.name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoZIndex && layer.setZIndex) {
|
||||||
|
this.lastZIndex++;
|
||||||
|
layer.setZIndex(this.lastZIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.expandIfNotCollapsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private expandIfNotCollapsed() {
|
||||||
|
if (this.mapsService && !this.controlOption.collapsed) {
|
||||||
|
this.expand();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onLayerChange(e: any) {
|
||||||
|
if (!this.handlingClick) {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
const obj = this.layerService.getLayer(e.target.layerId);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const type = obj?.overlay
|
||||||
|
? e.type === 'add'
|
||||||
|
? 'overlayadd'
|
||||||
|
: 'overlayremove'
|
||||||
|
: e.type === 'add'
|
||||||
|
? 'baselayerchange'
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (type) {
|
||||||
|
this.emit(type, obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private createRadioElement(name: string, checked: boolean): ChildNode {
|
||||||
|
const radioHtml =
|
||||||
|
'<input type="radio" class="l7-control-layers-selector" name="' +
|
||||||
|
name +
|
||||||
|
'"' +
|
||||||
|
(checked ? ' checked="checked"' : '') +
|
||||||
|
'/>';
|
||||||
|
|
||||||
|
const radioFragment = document.createElement('div');
|
||||||
|
radioFragment.innerHTML = radioHtml;
|
||||||
|
|
||||||
|
return radioFragment.firstChild as ChildNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private addItem(obj: any) {
|
||||||
|
const label = document.createElement('label');
|
||||||
|
const layer = this.layerService.getLayer(obj.layer.id);
|
||||||
|
const checked = layer && layer.inited && obj.layer.isVisible();
|
||||||
|
let input: IInputItem;
|
||||||
|
if (obj.overlay) {
|
||||||
|
input = document.createElement('input') as IInputItem;
|
||||||
|
input.type = 'checkbox';
|
||||||
|
input.className = 'l7-control-layers-selector';
|
||||||
|
input.defaultChecked = checked;
|
||||||
|
} else {
|
||||||
|
input = this.createRadioElement('l7-base-layers', checked) as IInputItem;
|
||||||
|
}
|
||||||
|
this.layerControlInputs.push(input);
|
||||||
|
input.layerId = obj.layer.id;
|
||||||
|
input.addEventListener('click', this.onInputClick);
|
||||||
|
|
||||||
|
const name = document.createElement('span');
|
||||||
|
name.innerHTML = ' ' + obj.name;
|
||||||
|
|
||||||
|
const holder = document.createElement('div');
|
||||||
|
|
||||||
|
label.appendChild(holder);
|
||||||
|
holder.appendChild(input);
|
||||||
|
holder.appendChild(name);
|
||||||
|
|
||||||
|
const container = obj.overlay ? this.overlaysList : this.baseLayersList;
|
||||||
|
container.appendChild(label);
|
||||||
|
|
||||||
|
this.checkDisabledLayers();
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onInputClick() {
|
||||||
|
const inputs = this.layerControlInputs;
|
||||||
|
let input;
|
||||||
|
let layer;
|
||||||
|
const addedLayers = [];
|
||||||
|
const removedLayers = [];
|
||||||
|
this.handlingClick = true;
|
||||||
|
for (let i = inputs.length - 1; i >= 0; i--) {
|
||||||
|
input = inputs[i];
|
||||||
|
layer = this.layerService.getLayer(input.layerId);
|
||||||
|
if (input.checked) {
|
||||||
|
addedLayers.push(layer);
|
||||||
|
} else if (!input.checked) {
|
||||||
|
removedLayers.push(layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removedLayers.forEach((l: any) => {
|
||||||
|
l.hide();
|
||||||
|
});
|
||||||
|
addedLayers.forEach((l: any) => {
|
||||||
|
l.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.handlingClick = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,9 @@ export * from './control/scale';
|
||||||
export * from './popup/popup';
|
export * from './popup/popup';
|
||||||
export * from './popup/layerPopup';
|
export * from './popup/layerPopup';
|
||||||
|
|
||||||
|
// 为了兼容老版 LayerSwitch
|
||||||
|
export * from './control/layer';
|
||||||
|
|
||||||
export { Marker, MarkerLayer };
|
export { Marker, MarkerLayer };
|
||||||
|
|
||||||
export * from './interface';
|
export * from './interface';
|
||||||
|
|
Loading…
Reference in New Issue