improvement: update l7-react

This commit is contained in:
thinkinggis 2020-02-20 14:18:15 +08:00
parent 8900aec8fc
commit cfdb0bae8a
21 changed files with 212 additions and 40 deletions

View File

@ -1,8 +1,14 @@
import { ILngLat, IMapService, IPoint, IPopup, TYPES } from '@antv/l7-core';
import { bindAll, DOM } from '@antv/l7-utils';
import {
anchorTranslate,
anchorType,
applyAnchorClass,
bindAll,
DOM,
} from '@antv/l7-utils';
import { EventEmitter } from 'eventemitter3';
import { Container } from 'inversify';
import { anchorTranslate, anchorType, applyAnchorClass } from './utils/anchor';
// marker 支持 dragger 未完成
export interface IMarkerOption {

View File

@ -1,19 +1,23 @@
import { ILngLat, IMapService, IPoint, IPopup, TYPES } from '@antv/l7-core';
import { bindAll, DOM } from '@antv/l7-utils';
import {
ILngLat,
IMapService,
IPoint,
IPopup,
IPopupOption,
TYPES,
} from '@antv/l7-core';
import {
anchorTranslate,
anchorType,
applyAnchorClass,
bindAll,
DOM,
} from '@antv/l7-utils';
import { EventEmitter } from 'eventemitter3';
import { Container } from 'inversify';
import { anchorTranslate, anchorType, applyAnchorClass } from './utils/anchor';
/** colse event */
export interface IPopupOption {
closeButton: boolean;
closeOnClick: boolean;
maxWidth: string;
anchor: anchorType;
className: string;
offsets: number[];
}
export default class Popup extends EventEmitter implements IPopup {
private popupOption: IPopupOption;
private mapsService: IMapService<unknown>;

View File

@ -1,6 +1,15 @@
import { anchorType } from '@antv/l7-utils';
import { Container } from 'inversify';
import { ILngLat, IMapService } from '../map/IMapService';
export interface IPopupOption {
closeButton: boolean;
closeOnClick: boolean;
maxWidth: string;
anchor: anchorType;
className: string;
offsets: number[];
}
export interface IPopup {
addTo(scene: Container): this;
remove(): void;

View File

@ -18,7 +18,7 @@ import { gl } from '../renderer/gl';
import { IFramebuffer } from '../renderer/IFramebuffer';
import { IPickingService } from './IPickingService';
const PICKSCALE = 10.0;
const PICKSCALE = 1.0;
@injectable()
export default class PickingService implements IPickingService {
@inject(TYPES.IRendererService)
@ -155,9 +155,9 @@ export default class PickingService implements IPickingService {
}
let pickedColors: Uint8Array | undefined;
pickedColors = readPixels({
x: Math.round(xInDevicePixel / PICKSCALE),
x: Math.floor(xInDevicePixel / PICKSCALE),
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
y: Math.round((height - (y + 1) * window.devicePixelRatio) / PICKSCALE),
y: Math.floor((height - (y + 1) * window.devicePixelRatio) / PICKSCALE),
width: 1,
height: 1,
data: new Uint8Array(1 * 1 * 4),

View File

@ -108,14 +108,14 @@ float project_pixel(float pixel) {
// P20 坐标系下,为了和 Web 墨卡托坐标系统一zoom 默认减1
return pixel * pow(2.0, (19.0 - u_Zoom));
}
return pixel;
return pixel * -1.;
}
vec2 project_pixel(vec2 pixel) {
if (u_CoordinateSystem == COORDINATE_SYSTEM_P20 || u_CoordinateSystem == COORDINATE_SYSTEM_P20_OFFSET) {
// P20 坐标系下,为了和 Web 墨卡托坐标系统一zoom 默认减1
return pixel * pow(2.0, (19.0 - u_Zoom));
}
return pixel;
return pixel * -1.;
}
vec4 project_common_position_to_clipspace(vec4 position, mat4 viewProjectionMatrix, vec4 center) {

View File

@ -24,7 +24,7 @@ void main() {
// radius(16-bit)
v_radius = a_Size;
vec2 offset = project_pixel(extrude * (a_Size + u_stroke_width)) * -1.;
vec2 offset = project_pixel(extrude * (a_Size + u_stroke_width));
vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0));
gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, 0.0, 1.0));

View File

@ -59,6 +59,25 @@ export default function BaseLayer(type: string, props: ILayerProps) {
mapScene.render();
}
});
useEffect(() => {
if (layer && layer.inited) {
layer.updateLayerConfig(options);
}
}, [options?.maxZoom, options?.maxZoom, options?.visible, options?.autoFit]);
useEffect(() => {
if (layer && layer.inited && options && options.zIndex) {
layer.setIndex(options.zIndex);
}
}, [options?.zIndex]);
useEffect(() => {
if (layer && layer.inited && options && options.blend) {
layer.setBlend(options.blend);
}
}, [options?.blend]);
return (
<LayerContext.Provider value={layer}>
<Source layer={layer} source={source} />

View File

@ -1,4 +1,10 @@
import { IActiveOption, IScale, IScaleOptions, ISourceCFG } from '@antv/l7';
import {
BlendType,
IActiveOption,
IScale,
IScaleOptions,
ISourceCFG,
} from '@antv/l7';
import Active from './Active';
import Color from './Color';
import Filter from './Filter';
@ -13,8 +19,9 @@ type CallBack = (...args: any[]) => any;
export interface IAttributeOptions {
field: string;
value: string | number;
values: string[] | number[] | string | number;
values: string[] | number[] | string | number | CallBack;
scale?: string;
blend: keyof typeof BlendType;
}
export interface IScaleAttributeOptions {
@ -22,7 +29,16 @@ export interface IScaleAttributeOptions {
value: IScale;
values: IScaleOptions | IScale;
}
export interface ILayerOption {
name?: string;
visible: boolean;
zIndex: number;
minZoom: number;
maxZoom: number;
autoFit: boolean;
blend: keyof typeof BlendType;
[key: string]: any;
}
export interface IScaleOption {
[key: string]: IScaleAttributeOptions;
}
@ -39,9 +55,7 @@ export interface IActiveOptions {
option: IActiveOption | boolean;
}
export interface ILayerProps {
options?: {
[key: string]: any;
};
options?: Partial<ILayerOption>;
source: ISourceOptions;
color: Partial<IAttributeOptions>;
shape: Partial<IAttributeOptions>;

View File

@ -13,6 +13,9 @@ export const LayerEvent = React.memo((props: ILayerProps) => {
useEffect(() => {
layer.on(type, handler);
return () => {
layer.off('type', handler);
};
}, [type]);
return null;
});

View File

@ -0,0 +1,17 @@
import { IActiveOption, IImage, ILayer, Scene } from '@antv/l7';
import * as React from 'react';
import { useSceneValue } from './SceneContext';
const { useEffect } = React;
interface ILoadImageProps {
name: string;
url: IImage;
}
export default React.memo(function LoadImage(props: ILoadImageProps) {
const { name, url } = props;
const mapScene = (useSceneValue() as unknown) as Scene;
useEffect(() => {
mapScene.addImage(name, url);
}, [name, url]);
return null;
});

View File

@ -1,4 +1,4 @@
import { IMapConfig, Scene } from '@antv/l7';
import { IMapConfig, Scene, Zoom } from '@antv/l7';
// @ts-ignore
// tslint:disable-next-line:no-submodule-imports
import Mapbox from '@antv/l7-maps/lib/mapbox';
@ -14,6 +14,8 @@ const MapboxScene = React.memo((props: IMapSceneConig) => {
const { style, className, map } = props;
const container = createRef();
const [scene, setScene] = useState();
// 地图初始
useEffect(() => {
const sceneInstance = new Scene({
id: container.current as HTMLDivElement,
@ -26,6 +28,8 @@ const MapboxScene = React.memo((props: IMapSceneConig) => {
sceneInstance.destroy();
};
}, []);
// 更新地图样式
useEffect(() => {
if (!scene) {
return;
@ -33,6 +37,32 @@ const MapboxScene = React.memo((props: IMapSceneConig) => {
scene.setMapStyle(map.style);
}, [map.style]);
useEffect(() => {
if (!scene) {
return;
}
scene.setZoom(map.zoom);
}, [map.zoom, map.center, map.pitch, map.rotation]);
useEffect(() => {
if (!scene) {
return;
}
scene.setCenter(map.center);
}, [map.center]);
useEffect(() => {
if (!scene) {
return;
}
scene.setPitch(map.pitch);
}, [map.pitch]);
useEffect(() => {
if (!scene) {
return;
}
scene.setRotation(map.rotation);
}, [map.rotation]);
return (
<SceneContext.Provider value={scene}>
{createElement(

View File

View File

@ -0,0 +1,44 @@
import {
IActiveOption,
IImage,
ILayer,
ILngLat,
IPopupOption,
Popup,
Scene,
} from '@antv/l7';
import * as React from 'react';
import { createPortal } from 'react-dom';
import { useSceneValue } from './SceneContext';
const { useEffect } = React;
interface IPopupProps {
option: IPopupOption;
lnglat: ILngLat;
text: string;
html: string;
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
}
export default React.memo(function LoadImage(props: IPopupProps) {
const mapScene = (useSceneValue() as unknown) as Scene;
const { lnglat, html, text, children } = props;
const [popup, setPopup] = React.useState();
const el = document.createElement('div');
useEffect(() => {
const p = new Popup(props.option);
if (lnglat) {
p.setLnglat(lnglat);
}
if (html) {
p.setHTML(html);
}
if (text) {
p.setText(text);
}
if (children) {
p.setDOMContent(el);
}
setPopup(p);
}, []);
return createPortal(children, el);
});

View File

@ -12,7 +12,7 @@ interface IMapSceneConig {
map: IMapWrapper;
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
}
const MapScene = React.memo((props: IMapSceneConig) => {
export default React.memo((props: IMapSceneConig) => {
const { style, className, map, options } = props;
const container = createRef();
const [scene, setScene] = useState();
@ -36,6 +36,8 @@ const MapScene = React.memo((props: IMapSceneConig) => {
sceneInstance.destroy();
};
}, []);
// 更新地图
useEffect(() => {
if (!scene) {
return;
@ -57,5 +59,3 @@ const MapScene = React.memo((props: IMapSceneConig) => {
</SceneContext.Provider>
);
});
export { MapScene };

View File

@ -0,0 +1,21 @@
import { ILayer, Scene } from '@antv/l7';
import * as React from 'react';
import { useSceneValue } from './SceneContext';
const { useEffect } = React;
interface ILayerProps {
type: string;
handler: (...args: any[]) => void;
}
export const SceneEvent = React.memo((props: ILayerProps) => {
const { type, handler } = props;
const mapScene = (useSceneValue() as unknown) as Scene;
useEffect(() => {
mapScene.on(type, handler);
return () => {
mapScene.off('type', handler);
};
}, [type]);
return null;
});

View File

@ -1,11 +1,10 @@
export * from './component/SceneContext';
export { default as Scene } from './component/Scene';
export { default as AMapScene } from './component/AMapScene';
export { default as MapboxScene } from './component/MapboxScene';
export { default as Scene } from './component/Scene';
export * from './component/Layer';
export { default as Control } from './component/Control';
export { default as CustomControl } from './component/CustomControl';
export { MapScene } from './component/Scene';
export { PolygonLayer, LineLayer, PointLayer } from './component/Layer';
export { LayerEvent } from './component/LayerEvent';
export { useSceneValue, SceneContext } from './component/SceneContext';

View File

@ -5,5 +5,6 @@ export * from './geo';
export * from './lru_cache';
export * from './event';
export * from './color';
export * from './anchor';
import * as Satistics from './statistics';
export { DOM, Satistics };

View File

@ -46,10 +46,14 @@ export default class PointImage extends React.Component {
y: 'latitude',
},
})
.shape('triangle')
// .shape('name', ['00', '01', '02'])
.shape('name', 'text')
.color('red')
.active(true)
.active(false)
.size(20);
// imageLayer.on('click', (e) => {
// console.log(e);
// });
scene.addLayer(imageLayer);
i++;
}

View File

@ -27,6 +27,7 @@ export default class DashLineDemo extends React.Component {
.source(await response.json())
.size(1)
.shape('line')
.active({ color: 'red' })
.color(
'ELEV',
[
@ -44,7 +45,7 @@ export default class DashLineDemo extends React.Component {
)
.style({
// lineType: 'dash',
opacity: 0.5,
opacity: 1.0,
});
scene.addLayer(lineLayer);

View File

@ -1,5 +1,5 @@
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { LineLayer, MapScene } from '@antv/l7-react';
import { LineLayer, Scene } from '@antv/l7-react';
import * as React from 'react';
export default React.memo(function Map() {
@ -23,7 +23,7 @@ export default React.memo(function Map() {
}, []);
return (
<>
<MapScene
<Scene
map={amap}
style={{
position: 'absolute',
@ -40,20 +40,20 @@ export default React.memo(function Map() {
data,
}}
size={{
value: 1,
values: 1,
}}
color={{
value: '#fff',
values: '#fff',
}}
shape={{
value: 'line',
values: 'line',
}}
style={{
opacity: 1,
}}
/>
)}
</MapScene>
</Scene>
</>
);
});