fix: 还原旧版图层选择控件 Layers

This commit is contained in:
yanxiong 2022-10-31 15:44:46 +08:00
parent 2980c38d77
commit f706753866
3 changed files with 329 additions and 8 deletions

View File

@ -1,11 +1,4 @@
import {
GaodeMap,
IControlOption,
Logo,
Scale,
Scene,
Zoom,
} from '@antv/l7';
import { GaodeMap, IControlOption, Logo, Scale, Scene, Zoom } from '@antv/l7';
import React, { FunctionComponent, useEffect, useRef } from 'react';
const Demo: FunctionComponent = () => {

View File

@ -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;
}
}

View File

@ -18,6 +18,9 @@ export * from './control/scale';
export * from './popup/popup';
export * from './popup/layerPopup';
// 为了兼容老版 LayerSwitch
export * from './control/layer';
export { Marker, MarkerLayer };
export * from './interface';