mirror of https://gitee.com/antv-l7/antv-l7
feat: scale 支持根据字段和颜色指定
This commit is contained in:
parent
5936f9aa47
commit
c19df8344f
|
@ -22,6 +22,7 @@ import {
|
|||
IScale,
|
||||
IScaleOptions,
|
||||
IStyleAttributeService,
|
||||
ScaleAttributeType,
|
||||
StyleAttrField,
|
||||
StyleAttributeOption,
|
||||
Triangulation,
|
||||
|
@ -118,7 +119,7 @@ export interface ILayer {
|
|||
Partial<IModelInitializationOptions>,
|
||||
): IModel;
|
||||
init(): ILayer;
|
||||
scale(field: string | IScaleOptions, cfg?: IScale): ILayer;
|
||||
scale(field: string | number | IScaleOptions, cfg?: IScale): ILayer;
|
||||
size(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
color(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
shape(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
|
@ -139,6 +140,7 @@ export interface ILayer {
|
|||
style(options: unknown): ILayer;
|
||||
hide(): ILayer;
|
||||
show(): ILayer;
|
||||
getLegendItems(name: string): any;
|
||||
setIndex(index: number): ILayer;
|
||||
isVisible(): boolean;
|
||||
setMaxZoom(min: number): ILayer;
|
||||
|
|
|
@ -35,8 +35,11 @@ export type ScaleTypeName =
|
|||
| 'quantize'
|
||||
| 'threshold'
|
||||
| 'cat';
|
||||
|
||||
export type ScaleAttributeType = 'color' | 'size' | 'shape';
|
||||
export interface IScale {
|
||||
type: ScaleTypeName;
|
||||
field?: string;
|
||||
ticks?: any[];
|
||||
nice?: boolean;
|
||||
format?: () => any;
|
||||
|
@ -49,6 +52,7 @@ export enum StyleScaleType {
|
|||
}
|
||||
export interface IScaleOption {
|
||||
field?: string;
|
||||
attr?: ScaleAttributeType;
|
||||
type: ScaleTypeName;
|
||||
ticks?: any[];
|
||||
nice?: boolean;
|
||||
|
@ -115,6 +119,11 @@ type CallBack = (...args: any[]) => any;
|
|||
export type StyleAttributeField = string | string[] | number[];
|
||||
export type StyleAttributeOption = string | number | boolean | any[] | CallBack;
|
||||
export type StyleAttrField = string | string[] | number | number[];
|
||||
export interface IAttributeScale {
|
||||
field: string | number;
|
||||
func: unknown;
|
||||
option: IScaleOption | undefined;
|
||||
}
|
||||
|
||||
export interface IStyleAttributeInitializationOptions {
|
||||
name: string;
|
||||
|
@ -125,10 +134,7 @@ export interface IStyleAttributeInitializationOptions {
|
|||
names: string[] | number[];
|
||||
type: StyleScaleType;
|
||||
callback?: (...args: any[]) => [];
|
||||
scalers?: Array<{
|
||||
field: string | number;
|
||||
func: unknown;
|
||||
}>;
|
||||
scalers?: IAttributeScale[];
|
||||
};
|
||||
descriptor: IVertexAttributeDescriptor;
|
||||
}
|
||||
|
@ -186,6 +192,7 @@ export interface IStyleAttributeService {
|
|||
): void;
|
||||
getLayerStyleAttributes(): IStyleAttribute[] | undefined;
|
||||
getLayerStyleAttribute(attributeName: string): IStyleAttribute | undefined;
|
||||
getLayerAttributeScale(attributeName: string): any;
|
||||
createAttributesAndIndices(
|
||||
encodedFeatures: IEncodeFeature[],
|
||||
triangulation?: Triangulation,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { isNil } from 'lodash';
|
||||
import {
|
||||
IAttributeScale,
|
||||
IScaleOption,
|
||||
IStyleAttribute,
|
||||
StyleScaleType,
|
||||
} from '../layer/IStyleAttributeService';
|
||||
|
@ -22,10 +24,7 @@ export default class StyleAttribute implements IStyleAttribute {
|
|||
field: string | string[];
|
||||
values: unknown[];
|
||||
callback?: (...args: any[]) => [];
|
||||
scalers?: Array<{
|
||||
field: string;
|
||||
func: unknown;
|
||||
}>;
|
||||
scalers?: IAttributeScale[];
|
||||
};
|
||||
public descriptor: IVertexAttributeDescriptor;
|
||||
public featureBufferLayout: Array<{
|
||||
|
|
|
@ -7,6 +7,7 @@ import { IRendererService } from '../renderer/IRendererService';
|
|||
import { IParseDataItem } from '../source/ISourceService';
|
||||
import { ILayer } from './ILayerService';
|
||||
import {
|
||||
IAttributeScale,
|
||||
IEncodeFeature,
|
||||
IStyleAttribute,
|
||||
IStyleAttributeInitializationOptions,
|
||||
|
@ -108,6 +109,15 @@ export default class StyleAttributeService implements IStyleAttributeService {
|
|||
);
|
||||
}
|
||||
|
||||
public getLayerAttributeScale(name: string) {
|
||||
const attribute = this.getLayerStyleAttribute(name);
|
||||
const scale = attribute?.scale?.scalers as IAttributeScale[];
|
||||
if (scale && scale[0]) {
|
||||
return scale[0].func;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public updateAttributeByFeatureRange(
|
||||
attributeName: string,
|
||||
features: IEncodeFeature[],
|
||||
|
|
|
@ -31,6 +31,7 @@ import {
|
|||
IStyleAttributeService,
|
||||
IStyleAttributeUpdateOptions,
|
||||
lazyInject,
|
||||
ScaleAttributeType,
|
||||
ScaleTypeName,
|
||||
ScaleTypes,
|
||||
StyleAttributeField,
|
||||
|
@ -461,7 +462,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
}
|
||||
return this;
|
||||
}
|
||||
public scale(field: ScaleTypeName | IScaleOptions, cfg: IScale) {
|
||||
public scale(field: string | IScaleOptions, cfg: IScale) {
|
||||
if (isObject(field)) {
|
||||
this.scaleOptions = {
|
||||
...this.scaleOptions,
|
||||
|
@ -748,6 +749,30 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
}
|
||||
return this.configSchema;
|
||||
}
|
||||
public getLegendItems(name: string) {
|
||||
const scale = this.styleAttributeService.getLayerAttributeScale(name);
|
||||
if (scale) {
|
||||
if (scale.ticks) {
|
||||
const items = scale.ticks().map((item: any) => {
|
||||
return {
|
||||
value: item,
|
||||
[name]: scale(item),
|
||||
};
|
||||
});
|
||||
return items;
|
||||
} else if (scale.invertExtent) {
|
||||
const items = scale.range().map((item: any) => {
|
||||
return {
|
||||
value: scale.invertExtent(item),
|
||||
[name]: item,
|
||||
};
|
||||
});
|
||||
return items;
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public pick({ x, y }: { x: number; y: number }) {
|
||||
this.interactionService.triggerHover({ x, y });
|
||||
|
|
|
@ -64,7 +64,7 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
this.caculateScalesForAttributes(attributes || [], dataArray);
|
||||
});
|
||||
|
||||
// 检测数据是不否需要更新
|
||||
// 检测数据是否需要更新
|
||||
layer.hooks.beforeRenderData.tap('FeatureScalePlugin', (flag) => {
|
||||
if (flag) {
|
||||
this.scaleOptions = layer.getScaleOptions();
|
||||
|
@ -146,6 +146,7 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
return {
|
||||
field: scale.field,
|
||||
func: scale.scale,
|
||||
option: scale.option,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -160,13 +161,17 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
) {
|
||||
const scalekey = [field, attribute.name].join('_');
|
||||
const values = attribute.scale?.values;
|
||||
if (this.scaleCache[scalekey]) {
|
||||
return this.scaleCache[scalekey];
|
||||
}
|
||||
const styleScale = this.createScale(field, values, dataArray);
|
||||
this.scaleCache[scalekey] = styleScale;
|
||||
|
||||
return this.scaleCache[scalekey];
|
||||
// if (this.scaleCache[scalekey]) {
|
||||
// return this.scaleCache[scalekey];
|
||||
// }
|
||||
const styleScale = this.createScale(
|
||||
field,
|
||||
attribute.name,
|
||||
values,
|
||||
dataArray,
|
||||
);
|
||||
// this.scaleCache[scalekey] = styleScale;
|
||||
return styleScale;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,11 +193,15 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
|
||||
private createScale(
|
||||
field: string | number,
|
||||
name: string,
|
||||
values: unknown[] | string | undefined,
|
||||
data?: IParseDataItem[],
|
||||
): IStyleScale {
|
||||
// 首先查找全局默认配置例如 color
|
||||
const scaleOption: IScale | undefined = this.scaleOptions[field];
|
||||
// scale 支持根据视觉通道和字段
|
||||
const scaleOption: IScale | undefined =
|
||||
this.scaleOptions[name] && this.scaleOptions[name].field === field
|
||||
? this.scaleOptions[name]
|
||||
: this.scaleOptions[field];
|
||||
const styleScale: IStyleScale = {
|
||||
field,
|
||||
scale: undefined,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { IMapConfig, Scene } from '@antv/l7';
|
||||
|
||||
// @ts-ignore
|
||||
// tslint:disable-next-line:no-submodule-imports
|
||||
import GaodeMap from '@antv/l7-maps/lib/amap';
|
||||
import React, { createElement, createRef, useEffect, useState } from 'react';
|
||||
|
|
|
@ -11,8 +11,9 @@ export default React.memo(function Chart(props: ILayerProps) {
|
|||
const { layer, color } = props;
|
||||
useEffect(() => {
|
||||
color.field
|
||||
? layer.color(color.field as StyleAttrField, color.values)
|
||||
? layer.color(color.field as StyleAttrField, color.value)
|
||||
: layer.color(color.value as StyleAttrField);
|
||||
}, [color.value, color.field, JSON.stringify(color.values)]);
|
||||
}, [color.field, color.scale, JSON.stringify(color.value)]);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { ILayer, LineLayer, PointLayer, PolygonLayer, Scene } from '@antv/l7';
|
||||
import * as React from 'react';
|
||||
import { useSceneValue } from '../SceneContext';
|
||||
import { Color, ILayerProps, Scales, Shape, Size, Source, Style } from './';
|
||||
import { Color, ILayerProps, Scale, Shape, Size, Source, Style } from './';
|
||||
|
||||
const { useEffect, useState } = React;
|
||||
|
||||
export default function BaseLayer(type: string, props: ILayerProps) {
|
||||
const { source, color, shape, style, size, scales, options } = props;
|
||||
const { source, color, shape, style, size, scale, options } = props;
|
||||
const mapScene = (useSceneValue() as unknown) as Scene;
|
||||
const [layer, setLayer] = useState();
|
||||
if (!layer) {
|
||||
|
@ -41,7 +41,7 @@ export default function BaseLayer(type: string, props: ILayerProps) {
|
|||
return (
|
||||
<>
|
||||
<Source layer={layer} source={source} />
|
||||
{scales && <Scales layer={layer} scales={scales} />}
|
||||
{scale && <Scale layer={layer} scale={scale} />}
|
||||
<Color layer={layer} color={color} />
|
||||
{size && <Size layer={layer} size={size} />}
|
||||
<Shape layer={layer} shape={shape} />
|
||||
|
|
|
@ -5,14 +5,14 @@ import { IScaleAttributeOptions } from './';
|
|||
const { useEffect } = React;
|
||||
interface ILayerProps {
|
||||
layer: ILayer;
|
||||
scales: Partial<IScaleAttributeOptions>;
|
||||
scale: Partial<IScaleAttributeOptions>;
|
||||
}
|
||||
export default React.memo(function Chart(props: ILayerProps) {
|
||||
const { layer, scales } = props;
|
||||
const { layer, scale } = props;
|
||||
useEffect(() => {
|
||||
scales.field
|
||||
? layer.scale(scales.field as string, scales.value as IScale)
|
||||
: layer.scale(scales.values as IScaleOptions);
|
||||
}, [scales.value, scales.field, JSON.stringify(scales.values)]);
|
||||
scale.value
|
||||
? layer.scale(scale.field as string, scale.value as IScale)
|
||||
: layer.scale(scale.field as IScaleOptions);
|
||||
}, [scale.value, scale.field]);
|
||||
return null;
|
||||
});
|
|
@ -13,6 +13,6 @@ export default React.memo(function Chart(props: ILayerProps) {
|
|||
size.field
|
||||
? layer.size(size.field, size.values)
|
||||
: layer.size(size.value as StyleAttrField);
|
||||
}, [size.field, size.value, JSON.stringify(size.values)]);
|
||||
}, [size.field, size.value, size.scale, size.values]);
|
||||
return null;
|
||||
});
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { IScale, IScaleOptions, ISourceCFG } from '@antv/l7';
|
||||
import {
|
||||
IScale,
|
||||
IScaleOptions,
|
||||
ISourceCFG,
|
||||
ScaleAttributeType,
|
||||
} from '@antv/l7';
|
||||
import Color from './Color';
|
||||
import Scales from './Scales';
|
||||
import Scale from './Scale';
|
||||
import Shape from './Shape';
|
||||
import Size from './Size';
|
||||
import Source from './Source';
|
||||
|
@ -9,13 +14,18 @@ export interface IAttributeOptions {
|
|||
field: string;
|
||||
value: string | number;
|
||||
values: string[] | number[] | string;
|
||||
scale?: string;
|
||||
}
|
||||
|
||||
export interface IScaleAttributeOptions {
|
||||
field: string;
|
||||
field: string | IScaleOptions;
|
||||
value: IScale;
|
||||
values: IScaleOptions;
|
||||
}
|
||||
|
||||
export interface IScaleOption {
|
||||
[key: string]: IScaleAttributeOptions;
|
||||
}
|
||||
export interface IStyleOptions {
|
||||
opacity: number;
|
||||
[key: string]: any;
|
||||
|
@ -30,9 +40,9 @@ export interface ILayerProps {
|
|||
source: ISourceOptions;
|
||||
color: Partial<IAttributeOptions>;
|
||||
shape: Partial<IAttributeOptions>;
|
||||
scales?: Partial<IScaleAttributeOptions>;
|
||||
scale?: Partial<IScaleAttributeOptions>;
|
||||
size?: Partial<IAttributeOptions>;
|
||||
style?: Partial<IStyleOptions>;
|
||||
}
|
||||
|
||||
export { Source, Size, Color, Shape, Style, Scales };
|
||||
export { Source, Size, Color, Shape, Style, Scale };
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { IMapConfig, Scene } from '@antv/l7';
|
||||
|
||||
// @ts-ignore
|
||||
// tslint:disable-next-line:no-submodule-imports
|
||||
import Mapbox from '@antv/l7-maps/lib/mapbox';
|
||||
import React, { createElement, createRef, useEffect, useState } from 'react';
|
||||
|
|
|
@ -19,40 +19,50 @@ export default class Point3D extends React.Component {
|
|||
|
||||
const scene = new Scene({
|
||||
id: document.getElementById('map') as HTMLDivElement,
|
||||
map: new Mapbox({
|
||||
map: new GaodeMap({
|
||||
center: [120.19382669582967, 30.258134],
|
||||
pitch: 0,
|
||||
style: 'dark',
|
||||
zoom: 0,
|
||||
}),
|
||||
});
|
||||
// scene.on('loaded', () => {
|
||||
scene.on('loaded', () => {
|
||||
const pointLayer = new PointLayer({})
|
||||
.source(pointsData, {
|
||||
cluster: false,
|
||||
})
|
||||
.scale({
|
||||
size: {
|
||||
type: 'power',
|
||||
field: 'mag',
|
||||
},
|
||||
color: {
|
||||
type: 'linear',
|
||||
field: 'mag',
|
||||
},
|
||||
})
|
||||
.shape('circle')
|
||||
// .scale('point_count', {
|
||||
// type: 'quantile',
|
||||
// })
|
||||
.size('mag', [5, 10, 15, 20, 25])
|
||||
.size('mag', [2, 8, 14, 20, 26, 32, 40])
|
||||
.animate(false)
|
||||
.active(true)
|
||||
.color('yellow')
|
||||
.color('mag', ['red', 'blue', 'yellow', 'green'])
|
||||
.style({
|
||||
opacity: 0.5,
|
||||
strokeWidth: 1,
|
||||
});
|
||||
scene.addLayer(pointLayer);
|
||||
scene.on('loaded', () => {
|
||||
const newData = {
|
||||
type: 'FeatureCollection',
|
||||
features: pointsData.features.slice(0, 100),
|
||||
};
|
||||
pointLayer.setData(newData);
|
||||
});
|
||||
this.scene = scene;
|
||||
const items = pointLayer.getLegendItems('color');
|
||||
console.log(items);
|
||||
console.log(pointLayer.getLegendItems('size'));
|
||||
// scene.on('loaded', () => {
|
||||
// const newData = {
|
||||
// type: 'FeatureCollection',
|
||||
// features: pointsData.features.slice(0, 100),
|
||||
// };
|
||||
// pointLayer.setData(newData);
|
||||
// });
|
||||
this.scene = scene;
|
||||
});
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
Loading…
Reference in New Issue