feat: 1.新增 PopperControl 和 ButtonControl 的 setOptions 方法 2.完成 Logo 组件的升级开发

This commit is contained in:
yanxiong 2022-08-17 12:59:34 +08:00
parent a5cf7469d3
commit 53e038bdb8
14 changed files with 290 additions and 94 deletions

View File

@ -0,0 +1,6 @@
---
title: Logo
order: 10
---
<code src="./logo.tsx" compact defaultShowCode></code>

View File

@ -0,0 +1,73 @@
import { GaodeMap, Scene, Logo } from '@antv/l7';
import React from 'react';
// tslint:disable-next-line:no-duplicate-imports
import { FunctionComponent, useEffect } from 'react';
const Demo: FunctionComponent = () => {
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new GaodeMap({
style: 'dark',
center: [120, 30],
pitch: 0,
zoom: 6.45,
}),
logoVisible: false,
});
scene.on('loaded', () => {
const logo1 = new Logo({
position: 'leftbottom',
});
scene.addControl(logo1);
setTimeout(() => {
logo1.setOptions({
img:
'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
href: '',
style: 'height: 40px; width: 40px;',
});
}, 1000);
const logo2 = new Logo({
position: 'rightbottom',
href: undefined,
});
scene.addControl(logo2);
const logo3 = new Logo({
position: 'topright',
style: 'height: 40px; width: 40px;',
img:
'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
href: '',
});
scene.addControl(logo3);
const logo4 = new Logo({
position: 'topleft',
style: 'height: 40px; width: 40px;',
img:
'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
href: 'https://ant.design/index-cn',
});
scene.addControl(logo4);
});
}, []);
return (
<>
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
</>
);
};
export default Demo;

View File

@ -1,11 +1,40 @@
import { GaodeMap, Scene, SelectControl } from '@antv/l7'; import { GaodeMap, Scene, SelectControl } from '@antv/l7';
import { FunctionComponent, useEffect } from 'react'; import React, { FunctionComponent, useEffect, useState } from 'react';
class SelectDemo extends SelectControl { class SelectDemo extends SelectControl {
protected isMultiple = false; protected isMultiple = false;
} }
const options = [
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*vky9QKrWjlwAAAAAAAAAAAAAARQnAQ',
value: 'normal',
text: 'normal',
},
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*UlP0Qp9Zwx0AAAAAAAAAAAAAARQnAQ',
value: 'light',
text: 'light',
},
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*UitzS5mxpSwAAAAAAAAAAAAAARQnAQ',
value: 'dark',
text: 'dark',
},
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*UitzS5mxpSwAAAAAAAAAAAAAARQnAQ',
value: 'dark1',
text: 'dark1',
},
];
const Demo: FunctionComponent = () => { const Demo: FunctionComponent = () => {
const [control, setControl] = useState<SelectDemo | null>(null);
useEffect(() => { useEffect(() => {
const scene = new Scene({ const scene = new Scene({
id: 'map', id: 'map',
@ -36,32 +65,7 @@ const Demo: FunctionComponent = () => {
const newControl = new SelectDemo({ const newControl = new SelectDemo({
position: 'topcenter', position: 'topcenter',
popperTrigger: 'hover', popperTrigger: 'hover',
options: [ options,
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*vky9QKrWjlwAAAAAAAAAAAAAARQnAQ',
value: 'normal',
text: 'normal',
},
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*UlP0Qp9Zwx0AAAAAAAAAAAAAARQnAQ',
value: 'light',
text: 'light',
},
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*UitzS5mxpSwAAAAAAAAAAAAAARQnAQ',
value: 'dark',
text: 'dark',
},
{
img:
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*UitzS5mxpSwAAAAAAAAAAAAAARQnAQ',
value: 'dark1',
text: 'dark1',
},
],
// .map((item) => { // .map((item) => {
// const { img, ...option } = item; // const { img, ...option } = item;
// return option; // return option;
@ -73,17 +77,33 @@ const Demo: FunctionComponent = () => {
console.log(e); console.log(e);
}); });
setControl(newControl);
scene.addControl(newControl); scene.addControl(newControl);
}); });
}, []); }, []);
return ( return (
<div <>
id="map" <div>
style={{ <button
height: '500px', onClick={() => {
position: 'relative', control?.setOptions({
}} popperPlacement: 'right-start',
/> options: options.slice(0, 3),
options: options.slice(0, 3),
});
}}
>
</button>
</div>
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
</>
); );
}; };

View File

@ -109,9 +109,15 @@ export default abstract class Control<O extends IControlOption = IControlOption>
this.container = this.onAdd(); this.container = this.onAdd();
DOM.addClass(this.container, 'l7-control'); DOM.addClass(this.container, 'l7-control');
const { className, style } = this.controlOption;
if (className) {
this.setClassName(className);
}
if (style) {
this.setStyle(style);
}
// 将 container 插入容器中 // 将 container 插入容器中
this.insertContainer(); this.insertContainer();
this.setOptions(this.controlOption);
this.emit('add', this); this.emit('add', this);
return this; return this;
} }

View File

@ -49,14 +49,24 @@ export default abstract class PopperControl<
} }
public onAdd(): HTMLElement { public onAdd(): HTMLElement {
const button = super.onAdd();
this.initPopper();
return button;
}
public onRemove() {
this.popper.destroy();
}
public initPopper() {
const { const {
popperClassName, popperClassName,
popperPlacement, popperPlacement,
popperTrigger, popperTrigger,
} = this.controlOption; } = this.controlOption;
const popperContainer = this.mapsService.getMapContainer()!; const popperContainer = this.mapsService.getMapContainer()!;
const button = super.onAdd();
this.popper = new Popper(button, { this.popper = new Popper(this.button!, {
className: popperClassName, className: popperClassName,
placement: popperPlacement, placement: popperPlacement,
trigger: popperTrigger, trigger: popperTrigger,
@ -70,6 +80,21 @@ export default abstract class PopperControl<
.on('hide', () => { .on('hide', () => {
this.emit('popperHide'); this.emit('popperHide');
}); });
return button; return this.popper;
}
public setOptions(option: Partial<O>) {
super.setOptions(option);
if (
'popperPlacement' in option ||
'popperClassName' in option ||
'popperTrigger' in option
) {
const content = this.popper.getContent();
this.popper.destroy();
this.initPopper();
this.popper.setContent(content);
}
} }
} }

View File

@ -59,9 +59,17 @@ export default abstract class SelectControl<
} }
} }
public setOptions(option: Partial<O>) {
super.setOptions(option);
const { options } = option;
if (options) {
this.popper.setContent(this.getPopperContent(options));
}
}
public onAdd() { public onAdd() {
const button = super.onAdd(); const button = super.onAdd();
this.popper.setContent(this.getPopperContent()); this.popper.setContent(this.getPopperContent(this.controlOption.options));
return button; return button;
} }
@ -96,8 +104,7 @@ export default abstract class SelectControl<
this.emit('selectChange', this.isMultiple ? finalValue : finalValue[0]); this.emit('selectChange', this.isMultiple ? finalValue : finalValue[0]);
} }
protected getPopperContent(): HTMLElement { protected getPopperContent(options: OptionItem[]): HTMLElement {
const options = this.controlOption.options;
const isImageOptions = this.isImageOptions(); const isImageOptions = this.isImageOptions();
const content = DOM.create( const content = DOM.create(
'div', 'div',
@ -155,6 +162,7 @@ export default abstract class SelectControl<
) as HTMLElement; ) as HTMLElement;
const imgDOM = DOM.create('img') as HTMLElement; const imgDOM = DOM.create('img') as HTMLElement;
imgDOM.setAttribute('src', option.img); imgDOM.setAttribute('src', option.img);
DOM.setUnDraggable(imgDOM);
optionDOM.appendChild(imgDOM); optionDOM.appendChild(imgDOM);
const rowDOM = DOM.create( const rowDOM = DOM.create(
'div', 'div',

View File

@ -1,30 +1,62 @@
import { DOM } from '@antv/l7-utils'; import { DOM } from '@antv/l7-utils';
import { Control, PositionType } from './baseControl'; // @ts-ignore
import AntvImg from '../images/logo.png';
import { Control, IControlOption, PositionType } from './baseControl';
export default class Logo extends Control { export interface ILogoControlOption extends IControlOption {
public getDefault() { // Logo 展示的图片 url
img: string;
// 点击 Logo 跳转的超链接,不传或传 '' | null 则纯展示 Logo点击不跳转
href?: string | null;
}
export { Logo };
export default class Logo extends Control<ILogoControlOption> {
public getDefault(): ILogoControlOption {
return { return {
position: PositionType.BOTTOMLEFT, position: PositionType.BOTTOMLEFT,
name: 'logo', name: 'logo',
href: 'https://l7.antv.vision/',
img: AntvImg,
}; };
} }
public onAdd() { public onAdd() {
const className = 'l7-control-logo'; const container = DOM.create('div', 'l7-control-logo');
const container = DOM.create('div', className); this.setLogoContent(container);
const anchor: HTMLLinkElement = DOM.create(
'a',
'l7-ctrl-logo',
) as HTMLLinkElement;
anchor.target = '_blank';
anchor.rel = 'noopener nofollow';
anchor.href = 'https://antv.alipay.com/l7';
anchor.setAttribute('aria-label', 'AntV logo');
anchor.setAttribute('rel', 'noopener nofollow');
container.appendChild(anchor);
return container; return container;
} }
public onRemove() { public onRemove() {
return null; return null;
} }
public setOptions(option: Partial<ILogoControlOption>) {
super.setOptions(option);
DOM.clearChildren(this.container);
this.setLogoContent(this.container);
}
protected setLogoContent(container: HTMLElement) {
const { href, img } = this.controlOption;
const imgDOM = DOM.create('img') as HTMLElement;
imgDOM.setAttribute('src', img);
imgDOM.setAttribute('aria-label', 'AntV logo');
DOM.setUnDraggable(imgDOM);
if (href) {
const anchorDOM = DOM.create(
'a',
'l7-control-logo-link',
) as HTMLLinkElement;
anchorDOM.target = '_blank';
anchorDOM.href = href;
anchorDOM.rel = 'noopener nofollow';
anchorDOM.setAttribute('rel', 'noopener nofollow');
anchorDOM.appendChild(imgDOM);
container.appendChild(anchorDOM);
} else {
container.appendChild(imgDOM);
}
}
} }

View File

@ -4,4 +4,5 @@
@import 'button'; @import 'button';
@import 'popper'; @import 'popper';
@import 'select'; @import 'select';
@import 'logo';
@import '../assets/iconfont.css'; @import '../assets/iconfont.css';

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
@import 'variables';
.l7-control-logo {
width: 89px;
height: 16px;
img {
height: 100%;
width: 100%;
}
.l7-control-logo-link {
display: block;
cursor: pointer;
img {
cursor: pointer;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -1,6 +1,5 @@
import Fullscreen from './control/fullscreen'; import Fullscreen from './control/fullscreen';
import Layers from './control/layer'; import Layers from './control/layer';
import Logo from './control/logo';
import Scale from './control/scale'; import Scale from './control/scale';
import Zoom from './control/zoom'; import Zoom from './control/zoom';
import Marker from './marker'; import Marker from './marker';
@ -13,9 +12,9 @@ import { createL7Icon } from './utils/icon';
import './css/index.less'; import './css/index.less';
export * from './control/baseControl'; export * from './control/baseControl';
export * from './control/logo';
export { export {
Logo,
Scale, Scale,
Zoom, Zoom,
Layers, Layers,

View File

@ -60,11 +60,17 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
*/ */
protected isShow: boolean = false; protected isShow: boolean = false;
/**
*
* @protected
*/
protected content: PopperContent;
// 气泡容器 DOM // 气泡容器 DOM
protected popper!: HTMLElement; protected popperDOM!: HTMLElement;
// 气泡中展示的内容容器 DOM // 气泡中展示的内容容器 DOM
protected content!: HTMLElement; protected contentDOM!: HTMLElement;
/** /**
* *
@ -82,21 +88,26 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
} }
} }
public getContent() {
return this.content;
}
public setContent(content: PopperContent) { public setContent(content: PopperContent) {
if (typeof content === 'string') { if (typeof content === 'string') {
this.content.innerHTML = content; this.contentDOM.innerHTML = content;
} else if (content instanceof HTMLElement) { } else if (content instanceof HTMLElement) {
this.content.innerHTML = ''; DOM.clearChildren(this.contentDOM);
this.content.appendChild(content); this.contentDOM.appendChild(content);
} }
this.content = content;
} }
public show() { public show() {
if (this.isShow || !this.content.innerHTML) { if (this.isShow || !this.contentDOM.innerHTML) {
return; return;
} }
this.setPopperPosition(); this.setPopperPosition();
DOM.removeClass(this.popper, 'l7-popper-hide'); DOM.removeClass(this.popperDOM, 'l7-popper-hide');
this.isShow = true; this.isShow = true;
if (this.option.unique) { if (this.option.unique) {
@ -113,7 +124,7 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
if (!this.isShow) { if (!this.isShow) {
return; return;
} }
DOM.addClass(this.popper, 'l7-popper-hide'); DOM.addClass(this.popperDOM, 'l7-popper-hide');
this.isShow = false; this.isShow = false;
this.emit('hide'); this.emit('hide');
} }
@ -144,26 +155,26 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
} }
}; };
protected init() { public init() {
const { trigger } = this.option; const { trigger } = this.option;
this.popper = this.createPopper(); this.popperDOM = this.createPopper();
if (trigger === 'click') { if (trigger === 'click') {
this.button.addEventListener('click', this.onBtnClick); this.button.addEventListener('click', this.onBtnClick);
} else { } else {
this.button.addEventListener('mousemove', this.onBtnMouseMove); this.button.addEventListener('mousemove', this.onBtnMouseMove);
this.button.addEventListener('mouseleave', this.onBtnMouseLeave); this.button.addEventListener('mouseleave', this.onBtnMouseLeave);
this.popper.addEventListener('mousemove', this.onBtnMouseMove); this.popperDOM.addEventListener('mousemove', this.onBtnMouseMove);
this.popper.addEventListener('mouseleave', this.onBtnMouseLeave); this.popperDOM.addEventListener('mouseleave', this.onBtnMouseLeave);
} }
} }
protected destroy() { public destroy() {
this.button.removeEventListener('click', this.onBtnClick); this.button.removeEventListener('click', this.onBtnClick);
this.button.removeEventListener('mousemove', this.onBtnMouseMove); this.button.removeEventListener('mousemove', this.onBtnMouseMove);
this.button.removeEventListener('mousemove', this.onBtnMouseLeave); this.button.removeEventListener('mousemove', this.onBtnMouseLeave);
this.popper.removeEventListener('mousemove', this.onBtnMouseMove); this.popperDOM.removeEventListener('mousemove', this.onBtnMouseMove);
this.popper.removeEventListener('mouseleave', this.onBtnMouseLeave); this.popperDOM.removeEventListener('mouseleave', this.onBtnMouseLeave);
DOM.remove(this.popper); DOM.remove(this.popperDOM);
} }
protected createPopper(): HTMLElement { protected createPopper(): HTMLElement {
@ -177,8 +188,8 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
popper.appendChild(popperContent); popper.appendChild(popperContent);
popper.appendChild(popperArrow); popper.appendChild(popperArrow);
container.appendChild(popper); container.appendChild(popper);
this.popper = popper; this.popperDOM = popper;
this.content = popperContent; this.contentDOM = popperContent;
if (content) { if (content) {
this.setContent(content); this.setContent(content);
} }
@ -255,10 +266,10 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
const posList = placement.split('-'); const posList = placement.split('-');
if (posList.length) { if (posList.length) {
DOM.addClass( DOM.addClass(
this.popper, this.popperDOM,
posList.map((pos) => `l7-popper-${pos}`).join(' '), posList.map((pos) => `l7-popper-${pos}`).join(' '),
); );
} }
DOM.addStyle(this.popper, DOM.css2Style(popperStyleObj)); DOM.addStyle(this.popperDOM, DOM.css2Style(popperStyleObj));
} }
} }

View File

@ -39,7 +39,9 @@ export function create(
container?: HTMLElement, container?: HTMLElement,
) { ) {
const el = $window.document.createElement(tagName); const el = $window.document.createElement(tagName);
el.className = className || ''; if (className) {
el.className = className || '';
}
if (container) { if (container) {
container.appendChild(el); container.appendChild(el);
@ -214,3 +216,11 @@ export function setChecked(el: ELType, value: boolean) {
el.removeAttribute('checked'); el.removeAttribute('checked');
} }
} }
export function clearChildren(el: ELType) {
el.innerHTML = '';
}
export function setUnDraggable(el: ELType) {
el.setAttribute('draggable', 'false');
}