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 { FunctionComponent, useEffect } from 'react';
import React, { FunctionComponent, useEffect, useState } from 'react';
class SelectDemo extends SelectControl {
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 [control, setControl] = useState<SelectDemo | null>(null);
useEffect(() => {
const scene = new Scene({
id: 'map',
@ -36,32 +65,7 @@ const Demo: FunctionComponent = () => {
const newControl = new SelectDemo({
position: 'topcenter',
popperTrigger: 'hover',
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',
},
],
options,
// .map((item) => {
// const { img, ...option } = item;
// return option;
@ -73,17 +77,33 @@ const Demo: FunctionComponent = () => {
console.log(e);
});
setControl(newControl);
scene.addControl(newControl);
});
}, []);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
<>
<div>
<button
onClick={() => {
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();
DOM.addClass(this.container, 'l7-control');
const { className, style } = this.controlOption;
if (className) {
this.setClassName(className);
}
if (style) {
this.setStyle(style);
}
// 将 container 插入容器中
this.insertContainer();
this.setOptions(this.controlOption);
this.emit('add', this);
return this;
}

View File

@ -49,14 +49,24 @@ export default abstract class PopperControl<
}
public onAdd(): HTMLElement {
const button = super.onAdd();
this.initPopper();
return button;
}
public onRemove() {
this.popper.destroy();
}
public initPopper() {
const {
popperClassName,
popperPlacement,
popperTrigger,
} = this.controlOption;
const popperContainer = this.mapsService.getMapContainer()!;
const button = super.onAdd();
this.popper = new Popper(button, {
this.popper = new Popper(this.button!, {
className: popperClassName,
placement: popperPlacement,
trigger: popperTrigger,
@ -70,6 +80,21 @@ export default abstract class PopperControl<
.on('hide', () => {
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() {
const button = super.onAdd();
this.popper.setContent(this.getPopperContent());
this.popper.setContent(this.getPopperContent(this.controlOption.options));
return button;
}
@ -96,8 +104,7 @@ export default abstract class SelectControl<
this.emit('selectChange', this.isMultiple ? finalValue : finalValue[0]);
}
protected getPopperContent(): HTMLElement {
const options = this.controlOption.options;
protected getPopperContent(options: OptionItem[]): HTMLElement {
const isImageOptions = this.isImageOptions();
const content = DOM.create(
'div',
@ -155,6 +162,7 @@ export default abstract class SelectControl<
) as HTMLElement;
const imgDOM = DOM.create('img') as HTMLElement;
imgDOM.setAttribute('src', option.img);
DOM.setUnDraggable(imgDOM);
optionDOM.appendChild(imgDOM);
const rowDOM = DOM.create(
'div',

View File

@ -1,30 +1,62 @@
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 {
public getDefault() {
export interface ILogoControlOption extends IControlOption {
// Logo 展示的图片 url
img: string;
// 点击 Logo 跳转的超链接,不传或传 '' | null 则纯展示 Logo点击不跳转
href?: string | null;
}
export { Logo };
export default class Logo extends Control<ILogoControlOption> {
public getDefault(): ILogoControlOption {
return {
position: PositionType.BOTTOMLEFT,
name: 'logo',
href: 'https://l7.antv.vision/',
img: AntvImg,
};
}
public onAdd() {
const className = 'l7-control-logo';
const container = DOM.create('div', className);
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);
const container = DOM.create('div', 'l7-control-logo');
this.setLogoContent(container);
return container;
}
public onRemove() {
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 'popper';
@import 'select';
@import 'logo';
@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 Layers from './control/layer';
import Logo from './control/logo';
import Scale from './control/scale';
import Zoom from './control/zoom';
import Marker from './marker';
@ -13,9 +12,9 @@ import { createL7Icon } from './utils/icon';
import './css/index.less';
export * from './control/baseControl';
export * from './control/logo';
export {
Logo,
Scale,
Zoom,
Layers,

View File

@ -60,11 +60,17 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
*/
protected isShow: boolean = false;
/**
*
* @protected
*/
protected content: PopperContent;
// 气泡容器 DOM
protected popper!: HTMLElement;
protected popperDOM!: HTMLElement;
// 气泡中展示的内容容器 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) {
if (typeof content === 'string') {
this.content.innerHTML = content;
this.contentDOM.innerHTML = content;
} else if (content instanceof HTMLElement) {
this.content.innerHTML = '';
this.content.appendChild(content);
DOM.clearChildren(this.contentDOM);
this.contentDOM.appendChild(content);
}
this.content = content;
}
public show() {
if (this.isShow || !this.content.innerHTML) {
if (this.isShow || !this.contentDOM.innerHTML) {
return;
}
this.setPopperPosition();
DOM.removeClass(this.popper, 'l7-popper-hide');
DOM.removeClass(this.popperDOM, 'l7-popper-hide');
this.isShow = true;
if (this.option.unique) {
@ -113,7 +124,7 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
if (!this.isShow) {
return;
}
DOM.addClass(this.popper, 'l7-popper-hide');
DOM.addClass(this.popperDOM, 'l7-popper-hide');
this.isShow = false;
this.emit('hide');
}
@ -144,26 +155,26 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
}
};
protected init() {
public init() {
const { trigger } = this.option;
this.popper = this.createPopper();
this.popperDOM = this.createPopper();
if (trigger === 'click') {
this.button.addEventListener('click', this.onBtnClick);
} else {
this.button.addEventListener('mousemove', this.onBtnMouseMove);
this.button.addEventListener('mouseleave', this.onBtnMouseLeave);
this.popper.addEventListener('mousemove', this.onBtnMouseMove);
this.popper.addEventListener('mouseleave', this.onBtnMouseLeave);
this.popperDOM.addEventListener('mousemove', this.onBtnMouseMove);
this.popperDOM.addEventListener('mouseleave', this.onBtnMouseLeave);
}
}
protected destroy() {
public destroy() {
this.button.removeEventListener('click', this.onBtnClick);
this.button.removeEventListener('mousemove', this.onBtnMouseMove);
this.button.removeEventListener('mousemove', this.onBtnMouseLeave);
this.popper.removeEventListener('mousemove', this.onBtnMouseMove);
this.popper.removeEventListener('mouseleave', this.onBtnMouseLeave);
DOM.remove(this.popper);
this.popperDOM.removeEventListener('mousemove', this.onBtnMouseMove);
this.popperDOM.removeEventListener('mouseleave', this.onBtnMouseLeave);
DOM.remove(this.popperDOM);
}
protected createPopper(): HTMLElement {
@ -177,8 +188,8 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
popper.appendChild(popperContent);
popper.appendChild(popperArrow);
container.appendChild(popper);
this.popper = popper;
this.content = popperContent;
this.popperDOM = popper;
this.contentDOM = popperContent;
if (content) {
this.setContent(content);
}
@ -255,10 +266,10 @@ export class Popper extends EventEmitter<'show' | 'hide'> {
const posList = placement.split('-');
if (posList.length) {
DOM.addClass(
this.popper,
this.popperDOM,
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,
) {
const el = $window.document.createElement(tagName);
el.className = className || '';
if (className) {
el.className = className || '';
}
if (container) {
container.appendChild(el);
@ -214,3 +216,11 @@ export function setChecked(el: ELType, value: boolean) {
el.removeAttribute('checked');
}
}
export function clearChildren(el: ELType) {
el.innerHTML = '';
}
export function setUnDraggable(el: ELType) {
el.setAttribute('draggable', 'false');
}