From cfdb0bae8a1e71042466801661589ea33ffd2624 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Thu, 20 Feb 2020 14:18:15 +0800 Subject: [PATCH] improvement: update l7-react --- packages/component/src/marker.ts | 10 ++++- packages/component/src/popup.ts | 26 ++++++----- .../src/services/component/IPopupService.ts | 9 ++++ .../services/interaction/PickingService.ts | 6 +-- packages/core/src/shaders/projection.glsl | 4 +- .../layers/src/point/shaders/fill_vert.glsl | 2 +- .../src/component/LayerAttribute/Layer.tsx | 19 ++++++++ .../src/component/LayerAttribute/index.ts | 26 ++++++++--- packages/react/src/component/LayerEvent.tsx | 3 ++ packages/react/src/component/LoadImage.tsx | 17 +++++++ packages/react/src/component/MapboxScene.tsx | 32 +++++++++++++- packages/react/src/component/Marker.tsx | 0 packages/react/src/component/Popup.tsx | 44 +++++++++++++++++++ packages/react/src/component/Scene.tsx | 6 +-- packages/react/src/component/SceneEvent.tsx | 21 +++++++++ packages/react/src/index.ts | 3 +- .../src/utils => utils/src}/anchor.ts | 0 packages/utils/src/index.ts | 1 + stories/Layers/components/PointImage.tsx | 8 +++- stories/Layers/components/dash.tsx | 3 +- stories/React/components/Scene.tsx | 12 ++--- 21 files changed, 212 insertions(+), 40 deletions(-) create mode 100644 packages/react/src/component/LoadImage.tsx create mode 100644 packages/react/src/component/Marker.tsx create mode 100644 packages/react/src/component/Popup.tsx create mode 100644 packages/react/src/component/SceneEvent.tsx rename packages/{component/src/utils => utils/src}/anchor.ts (100%) diff --git a/packages/component/src/marker.ts b/packages/component/src/marker.ts index bcf15c05db..d8927b6277 100644 --- a/packages/component/src/marker.ts +++ b/packages/component/src/marker.ts @@ -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 { diff --git a/packages/component/src/popup.ts b/packages/component/src/popup.ts index e0f6a07939..0a8eebcfdd 100644 --- a/packages/component/src/popup.ts +++ b/packages/component/src/popup.ts @@ -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; diff --git a/packages/core/src/services/component/IPopupService.ts b/packages/core/src/services/component/IPopupService.ts index a5521ae8ed..460a380c9e 100644 --- a/packages/core/src/services/component/IPopupService.ts +++ b/packages/core/src/services/component/IPopupService.ts @@ -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; diff --git a/packages/core/src/services/interaction/PickingService.ts b/packages/core/src/services/interaction/PickingService.ts index cc27a7eb6d..4e3a2794e2 100644 --- a/packages/core/src/services/interaction/PickingService.ts +++ b/packages/core/src/services/interaction/PickingService.ts @@ -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), diff --git a/packages/core/src/shaders/projection.glsl b/packages/core/src/shaders/projection.glsl index 05bd91cc54..c86a7859a7 100644 --- a/packages/core/src/shaders/projection.glsl +++ b/packages/core/src/shaders/projection.glsl @@ -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) { diff --git a/packages/layers/src/point/shaders/fill_vert.glsl b/packages/layers/src/point/shaders/fill_vert.glsl index 6482ae442c..cf0e996ea2 100644 --- a/packages/layers/src/point/shaders/fill_vert.glsl +++ b/packages/layers/src/point/shaders/fill_vert.glsl @@ -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)); diff --git a/packages/react/src/component/LayerAttribute/Layer.tsx b/packages/react/src/component/LayerAttribute/Layer.tsx index c64ef9ee80..82bf6db5cc 100644 --- a/packages/react/src/component/LayerAttribute/Layer.tsx +++ b/packages/react/src/component/LayerAttribute/Layer.tsx @@ -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 ( diff --git a/packages/react/src/component/LayerAttribute/index.ts b/packages/react/src/component/LayerAttribute/index.ts index 8756ebef60..9e9fdbd42e 100644 --- a/packages/react/src/component/LayerAttribute/index.ts +++ b/packages/react/src/component/LayerAttribute/index.ts @@ -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; source: ISourceOptions; color: Partial; shape: Partial; diff --git a/packages/react/src/component/LayerEvent.tsx b/packages/react/src/component/LayerEvent.tsx index 04e82bedd8..db290fa300 100644 --- a/packages/react/src/component/LayerEvent.tsx +++ b/packages/react/src/component/LayerEvent.tsx @@ -13,6 +13,9 @@ export const LayerEvent = React.memo((props: ILayerProps) => { useEffect(() => { layer.on(type, handler); + return () => { + layer.off('type', handler); + }; }, [type]); return null; }); diff --git a/packages/react/src/component/LoadImage.tsx b/packages/react/src/component/LoadImage.tsx new file mode 100644 index 0000000000..8ee545c029 --- /dev/null +++ b/packages/react/src/component/LoadImage.tsx @@ -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; +}); diff --git a/packages/react/src/component/MapboxScene.tsx b/packages/react/src/component/MapboxScene.tsx index de11fdfe9b..29285d9604 100644 --- a/packages/react/src/component/MapboxScene.tsx +++ b/packages/react/src/component/MapboxScene.tsx @@ -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 ( {createElement( diff --git a/packages/react/src/component/Marker.tsx b/packages/react/src/component/Marker.tsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/react/src/component/Popup.tsx b/packages/react/src/component/Popup.tsx new file mode 100644 index 0000000000..b133e809c7 --- /dev/null +++ b/packages/react/src/component/Popup.tsx @@ -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; +} +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); +}); diff --git a/packages/react/src/component/Scene.tsx b/packages/react/src/component/Scene.tsx index 134d5c6f1b..2dd72e741e 100644 --- a/packages/react/src/component/Scene.tsx +++ b/packages/react/src/component/Scene.tsx @@ -12,7 +12,7 @@ interface IMapSceneConig { map: IMapWrapper; children?: JSX.Element | JSX.Element[] | Array; } -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) => { ); }); - -export { MapScene }; diff --git a/packages/react/src/component/SceneEvent.tsx b/packages/react/src/component/SceneEvent.tsx new file mode 100644 index 0000000000..96e23347b5 --- /dev/null +++ b/packages/react/src/component/SceneEvent.tsx @@ -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; +}); diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index a8cb197e42..223fdde162 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -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'; diff --git a/packages/component/src/utils/anchor.ts b/packages/utils/src/anchor.ts similarity index 100% rename from packages/component/src/utils/anchor.ts rename to packages/utils/src/anchor.ts diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index ab5afe955e..89d0818f84 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -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 }; diff --git a/stories/Layers/components/PointImage.tsx b/stories/Layers/components/PointImage.tsx index 35c9222604..1db177d9e3 100644 --- a/stories/Layers/components/PointImage.tsx +++ b/stories/Layers/components/PointImage.tsx @@ -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++; } diff --git a/stories/Layers/components/dash.tsx b/stories/Layers/components/dash.tsx index 5229ec36b2..59eef3025e 100644 --- a/stories/Layers/components/dash.tsx +++ b/stories/Layers/components/dash.tsx @@ -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); diff --git a/stories/React/components/Scene.tsx b/stories/React/components/Scene.tsx index 4f2595e02b..d4d39e32bc 100644 --- a/stories/React/components/Scene.tsx +++ b/stories/React/components/Scene.tsx @@ -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 ( <> - )} - + ); });