mirror of https://gitee.com/antv-l7/antv-l7
commit
50a7a1cb2f
File diff suppressed because one or more lines are too long
|
@ -2,6 +2,7 @@ import Ajv from 'ajv';
|
|||
import { injectable, postConstruct } from 'inversify';
|
||||
import { merge } from 'lodash';
|
||||
import { ILayerConfig } from '../layer/ILayerService';
|
||||
import { IRenderConfig } from '../renderer/IRendererService';
|
||||
import { IGlobalConfigService, ISceneConfig } from './IConfigService';
|
||||
import mapConfigSchema from './mapConfigSchema';
|
||||
import sceneConfigSchema from './sceneConfigSchema';
|
||||
|
@ -10,10 +11,12 @@ import WarnInfo, { IWarnInfo } from './warnInfo';
|
|||
/**
|
||||
* 场景默认配置项
|
||||
*/
|
||||
const defaultSceneConfig: Partial<ISceneConfig> = {
|
||||
const defaultSceneConfig: Partial<ISceneConfig & IRenderConfig> = {
|
||||
id: 'map',
|
||||
logoPosition: 'bottomleft',
|
||||
logoVisible: true,
|
||||
antialias: true,
|
||||
preserveDrawingBuffer: false,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -62,6 +62,7 @@ export interface IMapService<RawMap = {}> {
|
|||
lngLatToPixel(lnglat: Point): IPoint;
|
||||
containerToLngLat(pixel: Point): ILngLat;
|
||||
lngLatToContainer(lnglat: Point): IPoint;
|
||||
exportMap(type: 'jpg' | 'png'): string;
|
||||
}
|
||||
|
||||
export const MapServiceEvent = ['mapload'];
|
||||
|
|
|
@ -16,6 +16,8 @@ export interface IRenderConfig {
|
|||
*/
|
||||
enableMultiPassRenderer?: boolean;
|
||||
passes?: Array<IPass<unknown>>;
|
||||
antialias?: boolean;
|
||||
preserveDrawingBuffer?: boolean;
|
||||
}
|
||||
|
||||
export interface IClearOptions {
|
||||
|
@ -40,7 +42,7 @@ export interface IReadPixelsOptions {
|
|||
}
|
||||
|
||||
export interface IRendererService {
|
||||
init($container: HTMLDivElement): Promise<void>;
|
||||
init($container: HTMLDivElement, cfg: IRenderConfig): Promise<void>;
|
||||
clear(options: IClearOptions): void;
|
||||
createModel(options: IModelInitializationOptions): IModel;
|
||||
createAttribute(options: IAttributeInitializationOptions): IAttribute;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { ISceneConfig } from '../config/IConfigService';
|
||||
import { ILayer } from '../layer/ILayerService';
|
||||
import { IMapConfig } from '../map/IMapService';
|
||||
import { IRenderConfig } from '../renderer/IRendererService';
|
||||
|
@ -8,9 +9,10 @@ export interface ISceneService {
|
|||
removeAllListeners(event?: string): this;
|
||||
init(config: IMapConfig & IRenderConfig): void;
|
||||
addLayer(layer: ILayer): void;
|
||||
getSceneConfig(): Partial<ISceneConfig>;
|
||||
render(): void;
|
||||
getSceneContainer(): HTMLDivElement;
|
||||
exportPng(): string;
|
||||
exportPng(type?: 'png' | 'jpg'): string;
|
||||
destroy(): void;
|
||||
}
|
||||
// scene 事件
|
||||
|
|
|
@ -18,8 +18,8 @@ import { IInteractionService } from '../interaction/IInteractionService';
|
|||
import { IPickingService } from '../interaction/IPickingService';
|
||||
import { ILayer, ILayerService } from '../layer/ILayerService';
|
||||
import { ILogService } from '../log/ILogService';
|
||||
import { IMapCamera, IMapService } from '../map/IMapService';
|
||||
import { IRendererService } from '../renderer/IRendererService';
|
||||
import { IMapCamera, IMapConfig, IMapService } from '../map/IMapService';
|
||||
import { IRenderConfig, IRendererService } from '../renderer/IRendererService';
|
||||
import { IShaderModuleService } from '../shader/IShaderModuleService';
|
||||
import { ISceneService } from './ISceneService';
|
||||
|
||||
|
@ -169,7 +169,10 @@ export default class Scene extends EventEmitter implements ISceneService {
|
|||
);
|
||||
this.$container = $container;
|
||||
if ($container) {
|
||||
await this.rendererService.init($container);
|
||||
await this.rendererService.init(
|
||||
$container,
|
||||
this.configService.getSceneConfig(this.id) as IRenderConfig,
|
||||
);
|
||||
elementResizeEvent(
|
||||
this.$container as HTMLDivElement,
|
||||
this.handleWindowResized,
|
||||
|
@ -231,13 +234,20 @@ export default class Scene extends EventEmitter implements ISceneService {
|
|||
return this.$container as HTMLDivElement;
|
||||
}
|
||||
|
||||
public exportPng(): string {
|
||||
public exportPng(type?: 'png' | 'jpg'): string {
|
||||
const renderCanvas = this.$container?.getElementsByTagName('canvas')[0];
|
||||
this.render();
|
||||
const layersPng = renderCanvas?.toDataURL('image/png') as string;
|
||||
const layersPng =
|
||||
type === 'jpg'
|
||||
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
||||
: (renderCanvas?.toDataURL('image/png') as string);
|
||||
return layersPng;
|
||||
}
|
||||
|
||||
public getSceneConfig(): Partial<ISceneConfig> {
|
||||
return this.configService.getSceneConfig(this.id as string);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.emit('destroy');
|
||||
this.inited = false;
|
||||
|
|
|
@ -875,6 +875,11 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
|
||||
private sourceEvent = () => {
|
||||
this.dataState.dataSourceNeedUpdate = true;
|
||||
const { autoFit } = this.getLayerConfig();
|
||||
if (autoFit) {
|
||||
this.fitBounds();
|
||||
}
|
||||
|
||||
this.emit('dataUpdate');
|
||||
this.reRender();
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ export default class UpdateStyleAttributePlugin implements ILayerPlugin {
|
|||
}: { styleAttributeService: IStyleAttributeService },
|
||||
) {
|
||||
layer.hooks.init.tap('UpdateStyleAttributePlugin', () => {
|
||||
this.updateStyleAtrribute(layer, { styleAttributeService });
|
||||
this.initStyleAttribute(layer, { styleAttributeService });
|
||||
});
|
||||
|
||||
layer.hooks.beforeRenderData.tap('styleAttributeService', () => {
|
||||
|
@ -70,4 +70,26 @@ export default class UpdateStyleAttributePlugin implements ILayerPlugin {
|
|||
);
|
||||
});
|
||||
}
|
||||
|
||||
private initStyleAttribute(
|
||||
layer: ILayer,
|
||||
{
|
||||
styleAttributeService,
|
||||
}: { styleAttributeService: IStyleAttributeService },
|
||||
) {
|
||||
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
|
||||
attributes
|
||||
.filter((attribute) => attribute.needRegenerateVertices)
|
||||
.forEach((attribute) => {
|
||||
// 精确更新某个/某些 feature(s),需要传入 featureIdx d
|
||||
styleAttributeService.updateAttributeByFeatureRange(
|
||||
attribute.name,
|
||||
layer.getEncodedData(), // 获取经过 mapping 最新的数据
|
||||
attribute.featureRange.startIndex,
|
||||
attribute.featureRange.endIndex,
|
||||
);
|
||||
attribute.needRegenerateVertices = false;
|
||||
this.logger.debug(`init vertex attributes: ${attribute.name} finished`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ export default class TextModel extends BaseModel {
|
|||
private currentZoom: number = -1;
|
||||
private extent: [[number, number], [number, number]];
|
||||
private textureHeight: number = 0;
|
||||
private textCount: number = 0;
|
||||
private preTextStyle: Partial<IPointTextLayerStyleOptions> = {};
|
||||
private glyphInfoMap: {
|
||||
[key: string]: {
|
||||
|
@ -101,10 +102,10 @@ export default class TextModel extends BaseModel {
|
|||
strokeWidth = 0,
|
||||
strokeOpacity = 1,
|
||||
textAnchor = 'center',
|
||||
textAllowOverlap = true,
|
||||
textAllowOverlap = false,
|
||||
} = this.layer.getLayerConfig() as IPointTextLayerStyleOptions;
|
||||
const { canvas } = this.fontService;
|
||||
if (canvas.height !== this.textureHeight) {
|
||||
const { canvas, mapping } = this.fontService;
|
||||
if (Object.keys(mapping).length !== this.textCount) {
|
||||
this.updateTexture();
|
||||
}
|
||||
this.preTextStyle = {
|
||||
|
|
|
@ -63,6 +63,7 @@ export default function(
|
|||
points: number[][],
|
||||
closed: boolean,
|
||||
indexOffset: number,
|
||||
isDash: boolean = true,
|
||||
) {
|
||||
const lineA = vec2.fromValues(0, 0);
|
||||
const lineB = vec2.fromValues(0, 0);
|
||||
|
@ -108,8 +109,11 @@ export default function(
|
|||
: null;
|
||||
}
|
||||
}
|
||||
const lineDistance = lineSegmentDistance(cur, last);
|
||||
const d = lineDistance + attrDistance[attrDistance.length - 1];
|
||||
let d = 0;
|
||||
if (isDash) {
|
||||
const lineDistance = lineSegmentDistance(cur, last);
|
||||
d = lineDistance + attrDistance[attrDistance.length - 1];
|
||||
}
|
||||
direction(lineA, cur, last);
|
||||
if (!lineNormal) {
|
||||
lineNormal = vec2.create();
|
||||
|
@ -218,15 +222,15 @@ export default function(
|
|||
attrPos[i * 3],
|
||||
attrPos[i * 3 + 1],
|
||||
attrPos[i * 3 + 2],
|
||||
attrDistance[i],
|
||||
attrDistance[i], // dash
|
||||
miters[i],
|
||||
totalDistance,
|
||||
totalDistance, // dash
|
||||
);
|
||||
}
|
||||
return {
|
||||
normals: out,
|
||||
attrIndex,
|
||||
attrPos: pickData, // [x,y,z, distance, miter ]
|
||||
attrPos: pickData, // [x,y,z, distance, miter ,tatal ]
|
||||
};
|
||||
}
|
||||
// [x,y,z, distance, miter ]
|
||||
|
|
|
@ -305,6 +305,18 @@ export default class AMapService
|
|||
|
||||
this.viewport = new Viewport();
|
||||
}
|
||||
|
||||
public exportMap(type: 'jpg' | 'png'): string {
|
||||
const renderCanvas = this.getContainer()?.getElementsByClassName(
|
||||
'amap-layer',
|
||||
)[0] as HTMLCanvasElement;
|
||||
const layersPng =
|
||||
type === 'jpg'
|
||||
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
||||
: (renderCanvas?.toDataURL('image/png') as string);
|
||||
return layersPng;
|
||||
}
|
||||
|
||||
public emit(name: string, ...args: any[]) {
|
||||
this.eventEmitter.emit(name, ...args);
|
||||
}
|
||||
|
|
|
@ -274,6 +274,14 @@ export default class MapboxService
|
|||
return this.$mapContainer;
|
||||
}
|
||||
|
||||
public exportMap(type: 'jpg' | 'png'): string {
|
||||
const renderCanvas = this.map.getCanvas();
|
||||
const layersPng =
|
||||
type === 'jpg'
|
||||
? (renderCanvas?.toDataURL('image/jpeg') as string)
|
||||
: (renderCanvas?.toDataURL('image/png') as string);
|
||||
return layersPng;
|
||||
}
|
||||
public onCameraChanged(callback: (viewport: IViewport) => void): void {
|
||||
this.cameraChangedCallback = callback;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,14 @@ export const MapTheme: {
|
|||
glyphs:
|
||||
'https://gw.alipayobjects.com/os/antvdemo/assets/mapbox/glyphs/{fontstack}/{range}.pbf',
|
||||
sources: {},
|
||||
layers: [],
|
||||
layers: [
|
||||
{
|
||||
id: 'background',
|
||||
type: 'background',
|
||||
layout: {
|
||||
visibility: 'none',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IMapConfig, Scene } from '@antv/l7';
|
||||
import { IMapConfig, ISceneConfig, Scene } from '@antv/l7';
|
||||
// @ts-ignore
|
||||
// tslint:disable-next-line:no-submodule-imports
|
||||
import GaodeMap from '@antv/l7-maps/lib/amap';
|
||||
|
@ -7,20 +7,26 @@ import { SceneContext } from './SceneContext';
|
|||
interface IMapSceneConig {
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
map: IMapConfig;
|
||||
map: Partial<IMapConfig>;
|
||||
option?: Partial<ISceneConfig>;
|
||||
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
|
||||
onSceneLoaded?: (scene: Scene) => void;
|
||||
}
|
||||
const AMapScene = React.memo((props: IMapSceneConig) => {
|
||||
const { style, className, map } = props;
|
||||
const { style, className, map, option, onSceneLoaded } = props;
|
||||
const container = createRef();
|
||||
const [scene, setScene] = useState<Scene>();
|
||||
useEffect(() => {
|
||||
const sceneInstance = new Scene({
|
||||
id: container.current as HTMLDivElement,
|
||||
...option,
|
||||
map: new GaodeMap(map),
|
||||
});
|
||||
sceneInstance.on('loaded', () => {
|
||||
setScene(sceneInstance);
|
||||
if (onSceneLoaded) {
|
||||
onSceneLoaded(sceneInstance);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
sceneInstance.destroy();
|
||||
|
|
|
@ -9,7 +9,7 @@ const PolygonLayer = React.memo(function Layer(
|
|||
});
|
||||
|
||||
const LineLayer = React.memo(function Layer(props: ILayerProps) {
|
||||
return BaseLayer('polygonLayer', props);
|
||||
return BaseLayer('lineLayer', props);
|
||||
});
|
||||
|
||||
const PointLayer = React.memo(function Layer(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IMapConfig, Scene, Zoom } from '@antv/l7';
|
||||
import { IMapConfig, ISceneConfig, Scene, Zoom } from '@antv/l7';
|
||||
// @ts-ignore
|
||||
// tslint:disable-next-line:no-submodule-imports
|
||||
import Mapbox from '@antv/l7-maps/lib/mapbox';
|
||||
|
@ -7,11 +7,13 @@ import { SceneContext } from './SceneContext';
|
|||
interface IMapSceneConig {
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
map: IMapConfig;
|
||||
map: Partial<IMapConfig>;
|
||||
option?: Partial<ISceneConfig>;
|
||||
children?: JSX.Element | JSX.Element[] | Array<JSX.Element | undefined>;
|
||||
onSceneLoaded?: (scene: Scene) => void;
|
||||
}
|
||||
const MapboxScene = React.memo((props: IMapSceneConig) => {
|
||||
const { style, className, map } = props;
|
||||
const { style, className, map, option, onSceneLoaded } = props;
|
||||
const container = createRef();
|
||||
const [scene, setScene] = useState<Scene>();
|
||||
|
||||
|
@ -19,10 +21,14 @@ const MapboxScene = React.memo((props: IMapSceneConig) => {
|
|||
useEffect(() => {
|
||||
const sceneInstance = new Scene({
|
||||
id: container.current as HTMLDivElement,
|
||||
...option,
|
||||
map: new Mapbox(map),
|
||||
});
|
||||
sceneInstance.on('loaded', () => {
|
||||
setScene(sceneInstance);
|
||||
if (onSceneLoaded) {
|
||||
onSceneLoaded(sceneInstance);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
sceneInstance.destroy();
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
IModel,
|
||||
IModelInitializationOptions,
|
||||
IReadPixelsOptions,
|
||||
IRenderConfig,
|
||||
IRendererService,
|
||||
ITexture2D,
|
||||
ITexture2DInitializationOptions,
|
||||
|
@ -36,7 +37,10 @@ export default class ReglRendererService implements IRendererService {
|
|||
private gl: regl.Regl;
|
||||
private $container: HTMLDivElement | null;
|
||||
|
||||
public async init($container: HTMLDivElement): Promise<void> {
|
||||
public async init(
|
||||
$container: HTMLDivElement,
|
||||
cfg: IRenderConfig,
|
||||
): Promise<void> {
|
||||
this.$container = $container;
|
||||
// tslint:disable-next-line:typedef
|
||||
this.gl = await new Promise((resolve, reject) => {
|
||||
|
@ -46,9 +50,9 @@ export default class ReglRendererService implements IRendererService {
|
|||
alpha: true,
|
||||
// use TAA instead of MSAA
|
||||
// @see https://www.khronos.org/registry/webgl/specs/1.0/#5.2.1
|
||||
antialias: true,
|
||||
antialias: cfg.antialias,
|
||||
premultipliedAlpha: true,
|
||||
preserveDrawingBuffer: false,
|
||||
preserveDrawingBuffer: cfg.preserveDrawingBuffer,
|
||||
},
|
||||
// TODO: use extensions
|
||||
extensions: [
|
||||
|
|
|
@ -57,7 +57,7 @@ class Scene
|
|||
private container: Container;
|
||||
|
||||
public constructor(config: ISceneConfig) {
|
||||
const { id, map, logoPosition, logoVisible } = config;
|
||||
const { id, map, logoPosition, logoVisible = true } = config;
|
||||
// 创建场景容器
|
||||
const sceneContainer = createSceneContainer();
|
||||
this.container = sceneContainer;
|
||||
|
@ -92,16 +92,15 @@ class Scene
|
|||
// 初始化 scene
|
||||
this.sceneService.init(config);
|
||||
// TODO: 初始化组件
|
||||
if (logoVisible) {
|
||||
this.addControl(new Logo({ position: logoPosition }));
|
||||
}
|
||||
|
||||
this.initControl();
|
||||
}
|
||||
|
||||
public getMapService(): IMapService<unknown> {
|
||||
return this.mapService;
|
||||
}
|
||||
public exportPng(): string {
|
||||
return this.sceneService.exportPng();
|
||||
public exportPng(type?: 'png' | 'jpg'): string {
|
||||
return this.sceneService.exportPng(type);
|
||||
}
|
||||
|
||||
public get map() {
|
||||
|
@ -306,6 +305,13 @@ class Scene
|
|||
this.markerService.init(this.container);
|
||||
this.popupService.init(this.container);
|
||||
}
|
||||
|
||||
private initControl() {
|
||||
const { logoVisible, logoPosition } = this.sceneService.getSceneConfig();
|
||||
if (logoVisible) {
|
||||
this.addControl(new Logo({ position: logoPosition }));
|
||||
}
|
||||
}
|
||||
// 资源管理
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @ts-ignore
|
||||
import { Layers, PointLayer, PolygonLayer, Scale, Scene } from '@antv/l7';
|
||||
import { Layers, PointLayer, PolygonLayer, Scale, Scene, Zoom } from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
|
@ -21,6 +21,7 @@ export default class ScaleComponent extends React.Component {
|
|||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
logoVisible: false,
|
||||
map: new Mapbox({
|
||||
style: 'dark',
|
||||
center: [110.19382669582967, 30.258134],
|
||||
|
@ -79,10 +80,15 @@ export default class ScaleComponent extends React.Component {
|
|||
};
|
||||
const layerControl = new Layers({
|
||||
overlayers: layers,
|
||||
position: 'bottomright',
|
||||
});
|
||||
|
||||
scene.addControl(scaleControl);
|
||||
scene.addControl(layerControl);
|
||||
const zoomControl = new Zoom({
|
||||
position: 'bottomright',
|
||||
});
|
||||
scene.addControl(zoomControl);
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
|
@ -16,6 +16,7 @@ import Point3D from './components/Point3D';
|
|||
import PointImage from './components/PointImage';
|
||||
import PolygonDemo from './components/polygon';
|
||||
import Polygon3D from './components/Polygon3D';
|
||||
import WorldDemo from './components/polygon_line';
|
||||
import ImageLayerDemo from './components/RasterImage';
|
||||
import RasterLayerDemo from './components/RasterLayer';
|
||||
import TextLayerDemo from './components/Text';
|
||||
|
@ -40,4 +41,5 @@ storiesOf('图层', module)
|
|||
.add('热力图', () => <HeatMapDemo />)
|
||||
.add('网格热力图', () => <HexagonLayerDemo />)
|
||||
.add('栅格', () => <RasterLayerDemo />)
|
||||
.add('图片', () => <ImageLayerDemo />);
|
||||
.add('图片', () => <ImageLayerDemo />)
|
||||
.add('世界地图', () => <WorldDemo />);
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
// @ts-ignore
|
||||
import {
|
||||
Layers,
|
||||
LineLayer,
|
||||
PointLayer,
|
||||
PolygonLayer,
|
||||
Scale,
|
||||
Scene,
|
||||
Zoom,
|
||||
} from '@antv/l7';
|
||||
import { Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class World extends React.Component {
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/68dc6756-627b-4e9e-a5ba-e834f6ba48f8.json',
|
||||
);
|
||||
const response2 = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/13b3aa35-f7a1-4d21-acad-805a4553edb4.json',
|
||||
);
|
||||
const pointsData = await response2.json();
|
||||
const data = await response.json();
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
logoVisible: false,
|
||||
map: new Mapbox({
|
||||
style: 'dark',
|
||||
center: [110.19382669582967, 30.258134],
|
||||
pitch: 0,
|
||||
zoom: 0,
|
||||
}),
|
||||
});
|
||||
this.scene = scene;
|
||||
const layer = new PolygonLayer({
|
||||
name: '01',
|
||||
});
|
||||
|
||||
layer
|
||||
.source(data)
|
||||
.color('name', [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
])
|
||||
.shape('fill')
|
||||
.select(true)
|
||||
.style({
|
||||
opacity: 1.0,
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
|
||||
const linelayer = new LineLayer({
|
||||
name: '01',
|
||||
});
|
||||
|
||||
linelayer
|
||||
.source(data)
|
||||
.color('#fff')
|
||||
.size(1)
|
||||
.shape('line')
|
||||
.select(true)
|
||||
.style({
|
||||
opacity: 1.0,
|
||||
});
|
||||
scene.addLayer(linelayer);
|
||||
const pointLayer = new PointLayer({
|
||||
name: '02',
|
||||
})
|
||||
.source(pointsData, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
coordinates: 'center',
|
||||
},
|
||||
})
|
||||
.shape('name', 'text')
|
||||
.size(12)
|
||||
.active(true)
|
||||
.color('#fff')
|
||||
.style({
|
||||
opacity: 1,
|
||||
sttoke: '#FFF',
|
||||
strokeWidth: 0,
|
||||
});
|
||||
scene.addLayer(pointLayer);
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { storiesOf } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
import GaodeMapScene from './components/Scene';
|
||||
import WorldMap from './components/world';
|
||||
|
||||
// @ts-ignore
|
||||
storiesOf('React', module).add('高德地图', () => <GaodeMapScene />);
|
||||
storiesOf('React', module).add('世界地图', () => <WorldMap />);
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import { LineLayer, MapboxScene, PolygonLayer } from '@antv/l7-react';
|
||||
import * as React from 'react';
|
||||
|
||||
export default React.memo(function Map() {
|
||||
const [data, setData] = React.useState();
|
||||
React.useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const response = await fetch(
|
||||
'https://gw.alipayobjects.com/os/basement_prod/68dc6756-627b-4e9e-a5ba-e834f6ba48f8.json',
|
||||
);
|
||||
const data = await response.json();
|
||||
setData(data);
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<MapboxScene
|
||||
map={{
|
||||
center: [110.19382669582967, 50.258134],
|
||||
pitch: 0,
|
||||
style: 'blank',
|
||||
zoom: 1,
|
||||
}}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
>
|
||||
{data && [
|
||||
<PolygonLayer
|
||||
key={'2'}
|
||||
source={{
|
||||
data,
|
||||
}}
|
||||
color={{
|
||||
field: 'name',
|
||||
values: [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
],
|
||||
}}
|
||||
shape={{
|
||||
values: 'fill',
|
||||
}}
|
||||
style={{
|
||||
opacity: 1,
|
||||
}}
|
||||
/>,
|
||||
<LineLayer
|
||||
key={'21'}
|
||||
source={{
|
||||
data,
|
||||
}}
|
||||
color={{
|
||||
values: '#fff',
|
||||
}}
|
||||
shape={{
|
||||
values: 'line',
|
||||
}}
|
||||
style={{
|
||||
opacity: 1,
|
||||
}}
|
||||
/>,
|
||||
]}
|
||||
</MapboxScene>
|
||||
</>
|
||||
);
|
||||
});
|
Loading…
Reference in New Issue