mirror of https://gitee.com/antv-l7/antv-l7
feat(layer): add setSelect setActive 方法 & refactor color util
This commit is contained in:
parent
4da5798d7c
commit
c9ffc3b7c0
|
@ -165,7 +165,10 @@ export default class Popup extends EventEmitter implements IPopup {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private onClickClose() {
|
private onClickClose(e: Event) {
|
||||||
|
if (e.stopPropagation) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
this.remove();
|
this.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +196,9 @@ export default class Popup extends EventEmitter implements IPopup {
|
||||||
this.container.addEventListener('mousedown', (e) => {
|
this.container.addEventListener('mousedown', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
|
this.container.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (maxWidth && this.container.style.maxWidth !== maxWidth) {
|
if (maxWidth && this.container.style.maxWidth !== maxWidth) {
|
||||||
this.container.style.maxWidth = maxWidth;
|
this.container.style.maxWidth = maxWidth;
|
||||||
|
|
|
@ -17,7 +17,9 @@ export default class PopupService implements IPopupService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public addPopup(popup: IPopup) {
|
public addPopup(popup: IPopup) {
|
||||||
this.popup.remove();
|
if (this.popup) {
|
||||||
|
this.popup.remove();
|
||||||
|
}
|
||||||
popup.addTo(this.scene);
|
popup.addTo(this.scene);
|
||||||
this.popup = popup;
|
this.popup = popup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,9 @@ const defaultLayerConfig: Partial<ILayerConfig> = {
|
||||||
active: false,
|
active: false,
|
||||||
activeColor: 'red',
|
activeColor: 'red',
|
||||||
enableHighlight: false,
|
enableHighlight: false,
|
||||||
|
enableSelect: false,
|
||||||
highlightColor: 'red',
|
highlightColor: 'red',
|
||||||
|
selectColor: 'blue',
|
||||||
enableTAA: false,
|
enableTAA: false,
|
||||||
jitterScale: 1,
|
jitterScale: 1,
|
||||||
enableLighting: false,
|
enableLighting: false,
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
|
import { ILngLat } from '../map/IMapService';
|
||||||
export enum InteractionEvent {
|
export enum InteractionEvent {
|
||||||
Hover = 'hover',
|
Hover = 'hover',
|
||||||
Click = 'click',
|
Click = 'click',
|
||||||
|
Select = 'select',
|
||||||
|
Active = 'active',
|
||||||
|
}
|
||||||
|
export interface IInteractionTarget {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
lngLat: ILngLat;
|
||||||
|
type: string;
|
||||||
|
featureId?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IInteractionService {
|
export interface IInteractionService {
|
||||||
|
@ -8,7 +18,9 @@ export interface IInteractionService {
|
||||||
destroy(): void;
|
destroy(): void;
|
||||||
on(
|
on(
|
||||||
eventName: InteractionEvent,
|
eventName: InteractionEvent,
|
||||||
callback: (params: { x: number; y: number; type: string }) => void,
|
callback: (params: IInteractionTarget) => void,
|
||||||
): void;
|
): void;
|
||||||
triggerHover({ x, y, type }: { x: number; y: number; type?: string }): void;
|
triggerHover({ x, y, type }: Partial<IInteractionTarget>): void;
|
||||||
|
triggerSelect(id: number): void;
|
||||||
|
triggerActive(id: number): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,13 @@ export default class InteractionService extends EventEmitter
|
||||||
public triggerHover({ x, y }: { x: number; y: number }) {
|
public triggerHover({ x, y }: { x: number; y: number }) {
|
||||||
this.emit(InteractionEvent.Hover, { x, y });
|
this.emit(InteractionEvent.Hover, { x, y });
|
||||||
}
|
}
|
||||||
|
public triggerSelect(id: number): void {
|
||||||
|
this.emit(InteractionEvent.Select, { featureId: id });
|
||||||
|
}
|
||||||
|
|
||||||
|
public triggerActive(id: number): void {
|
||||||
|
this.emit(InteractionEvent.Active, { featureId: id });
|
||||||
|
}
|
||||||
|
|
||||||
private addEventListenerOnMap() {
|
private addEventListenerOnMap() {
|
||||||
const $containter = this.mapService.getMapContainer();
|
const $containter = this.mapService.getMapContainer();
|
||||||
|
@ -81,6 +88,7 @@ export default class InteractionService extends EventEmitter
|
||||||
x -= left;
|
x -= left;
|
||||||
y -= top;
|
y -= top;
|
||||||
}
|
}
|
||||||
this.emit(InteractionEvent.Hover, { x, y, type });
|
const lngLat = this.mapService.containerToLngLat([x, y]);
|
||||||
|
this.emit(InteractionEvent.Hover, { x, y, lngLat, type });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ export interface ILayer {
|
||||||
beforePickingEncode: SyncHook<void>;
|
beforePickingEncode: SyncHook<void>;
|
||||||
afterPickingEncode: SyncHook<void>;
|
afterPickingEncode: SyncHook<void>;
|
||||||
beforeHighlight: SyncHook<[number[]]>;
|
beforeHighlight: SyncHook<[number[]]>;
|
||||||
|
beforeSelect: SyncHook<[number[]]>;
|
||||||
|
afterSelect: SyncHook<void>;
|
||||||
afterHighlight: SyncHook<void>;
|
afterHighlight: SyncHook<void>;
|
||||||
beforeDestroy: SyncHook<void>;
|
beforeDestroy: SyncHook<void>;
|
||||||
afterDestroy: SyncHook<void>;
|
afterDestroy: SyncHook<void>;
|
||||||
|
@ -86,6 +88,8 @@ export interface ILayer {
|
||||||
getLayerConfig(): Partial<ILayerConfig & ISceneConfig>;
|
getLayerConfig(): Partial<ILayerConfig & ISceneConfig>;
|
||||||
getContainer(): Container;
|
getContainer(): Container;
|
||||||
setContainer(container: Container): void;
|
setContainer(container: Container): void;
|
||||||
|
setCurrentPickId(id: number | null): void;
|
||||||
|
getCurrentPickId(): number | null;
|
||||||
buildLayerModel(
|
buildLayerModel(
|
||||||
options: ILayerModelInitializationOptions &
|
options: ILayerModelInitializationOptions &
|
||||||
Partial<IModelInitializationOptions>,
|
Partial<IModelInitializationOptions>,
|
||||||
|
@ -198,10 +202,13 @@ export interface ILayerConfig {
|
||||||
* 开启高亮
|
* 开启高亮
|
||||||
*/
|
*/
|
||||||
enableHighlight: boolean;
|
enableHighlight: boolean;
|
||||||
|
|
||||||
|
enableSelect: boolean;
|
||||||
/**
|
/**
|
||||||
* 高亮颜色
|
* 高亮颜色
|
||||||
*/
|
*/
|
||||||
highlightColor: string | number[];
|
highlightColor: string | number[];
|
||||||
|
selectColor: string | number[];
|
||||||
active: boolean;
|
active: boolean;
|
||||||
activeColor: string | number[];
|
activeColor: string | number[];
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { IRendererService, IShaderModuleService } from '../../../index';
|
import {
|
||||||
|
IMapService,
|
||||||
|
IRendererService,
|
||||||
|
IShaderModuleService,
|
||||||
|
} from '../../../index';
|
||||||
import { TYPES } from '../../../types';
|
import { TYPES } from '../../../types';
|
||||||
import { ICameraService } from '../../camera/ICameraService';
|
import { ICameraService } from '../../camera/ICameraService';
|
||||||
import { IInteractionService } from '../../interaction/IInteractionService';
|
import { IInteractionService } from '../../interaction/IInteractionService';
|
||||||
|
@ -17,6 +21,7 @@ export default class BaseNormalPass<InitializationOptions = {}>
|
||||||
|
|
||||||
protected rendererService: IRendererService;
|
protected rendererService: IRendererService;
|
||||||
protected cameraService: ICameraService;
|
protected cameraService: ICameraService;
|
||||||
|
protected mapService: IMapService;
|
||||||
protected interactionService: IInteractionService;
|
protected interactionService: IInteractionService;
|
||||||
protected layerService: ILayerService;
|
protected layerService: ILayerService;
|
||||||
|
|
||||||
|
@ -38,6 +43,7 @@ export default class BaseNormalPass<InitializationOptions = {}>
|
||||||
this.cameraService = layer
|
this.cameraService = layer
|
||||||
.getContainer()
|
.getContainer()
|
||||||
.get<ICameraService>(TYPES.ICameraService);
|
.get<ICameraService>(TYPES.ICameraService);
|
||||||
|
this.mapService = layer.getContainer().get<IMapService>(TYPES.IMapService);
|
||||||
this.interactionService = layer
|
this.interactionService = layer
|
||||||
.getContainer()
|
.getContainer()
|
||||||
.get<IInteractionService>(TYPES.IInteractionService);
|
.get<IInteractionService>(TYPES.IInteractionService);
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
|
import { decodePickingColor, encodePickingColor } from '@antv/l7-utils';
|
||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { TYPES } from '../../../types';
|
import { TYPES } from '../../../types';
|
||||||
import { InteractionEvent } from '../../interaction/IInteractionService';
|
import {
|
||||||
|
IInteractionTarget,
|
||||||
|
InteractionEvent,
|
||||||
|
} from '../../interaction/IInteractionService';
|
||||||
import { ILayer } from '../../layer/ILayerService';
|
import { ILayer } from '../../layer/ILayerService';
|
||||||
import { ILogService } from '../../log/ILogService';
|
import { ILogService } from '../../log/ILogService';
|
||||||
|
import { ILngLat } from '../../map/IMapService';
|
||||||
import { gl } from '../gl';
|
import { gl } from '../gl';
|
||||||
import { IFramebuffer } from '../IFramebuffer';
|
import { IFramebuffer } from '../IFramebuffer';
|
||||||
import { PassType } from '../IMultiPassRenderer';
|
import { PassType } from '../IMultiPassRenderer';
|
||||||
import BaseNormalPass from './BaseNormalPass';
|
import BaseNormalPass from './BaseNormalPass';
|
||||||
|
|
||||||
function decodePickingColor(color: Uint8Array): number {
|
|
||||||
const [i1, i2, i3] = color;
|
|
||||||
// 1 was added to seperate from no selection
|
|
||||||
const index = i1 + i2 * 256 + i3 * 65536 - 1;
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* color-based PixelPickingPass
|
* color-based PixelPickingPass
|
||||||
* @see https://github.com/antvis/L7/blob/next/dev-docs/PixelPickingEngine.md
|
* @see https://github.com/antvis/L7/blob/next/dev-docs/PixelPickingEngine.md
|
||||||
|
@ -66,6 +64,14 @@ export default class PixelPickingPass<
|
||||||
|
|
||||||
// 监听 hover 事件
|
// 监听 hover 事件
|
||||||
this.interactionService.on(InteractionEvent.Hover, this.pickFromPickingFBO);
|
this.interactionService.on(InteractionEvent.Hover, this.pickFromPickingFBO);
|
||||||
|
this.interactionService.on(
|
||||||
|
InteractionEvent.Select,
|
||||||
|
this.selectFeatureHander.bind(this),
|
||||||
|
);
|
||||||
|
this.interactionService.on(
|
||||||
|
InteractionEvent.Active,
|
||||||
|
this.highlightFeatureHander.bind(this),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public render(layer: ILayer) {
|
public render(layer: ILayer) {
|
||||||
|
@ -112,15 +118,7 @@ export default class PixelPickingPass<
|
||||||
* 拾取视口指定坐标属于的要素
|
* 拾取视口指定坐标属于的要素
|
||||||
* TODO:支持区域拾取
|
* TODO:支持区域拾取
|
||||||
*/
|
*/
|
||||||
private pickFromPickingFBO = ({
|
private pickFromPickingFBO = ({ x, y, lngLat, type }: IInteractionTarget) => {
|
||||||
x,
|
|
||||||
y,
|
|
||||||
type,
|
|
||||||
}: {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
type: string;
|
|
||||||
}) => {
|
|
||||||
if (!this.layer.isVisible()) {
|
if (!this.layer.isVisible()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +128,7 @@ export default class PixelPickingPass<
|
||||||
useFramebuffer,
|
useFramebuffer,
|
||||||
} = this.rendererService;
|
} = this.rendererService;
|
||||||
const { width, height } = getViewportSize();
|
const { width, height } = getViewportSize();
|
||||||
const { enableHighlight } = this.layer.getLayerConfig();
|
const { enableHighlight, enableSelect } = this.layer.getLayerConfig();
|
||||||
|
|
||||||
const xInDevicePixel = x * window.devicePixelRatio;
|
const xInDevicePixel = x * window.devicePixelRatio;
|
||||||
const yInDevicePixel = y * window.devicePixelRatio;
|
const yInDevicePixel = y * window.devicePixelRatio;
|
||||||
|
@ -142,7 +140,6 @@ export default class PixelPickingPass<
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pickedColors: Uint8Array | undefined;
|
let pickedColors: Uint8Array | undefined;
|
||||||
useFramebuffer(this.pickingFBO, () => {
|
useFramebuffer(this.pickingFBO, () => {
|
||||||
// avoid realloc
|
// avoid realloc
|
||||||
|
@ -166,54 +163,58 @@ export default class PixelPickingPass<
|
||||||
const rawFeature = this.layer
|
const rawFeature = this.layer
|
||||||
.getSource()
|
.getSource()
|
||||||
.getFeatureById(pickedFeatureIdx);
|
.getFeatureById(pickedFeatureIdx);
|
||||||
|
const target = {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
type,
|
||||||
|
lngLat,
|
||||||
|
featureId: pickedFeatureIdx,
|
||||||
|
feature: rawFeature,
|
||||||
|
};
|
||||||
if (!rawFeature) {
|
if (!rawFeature) {
|
||||||
// this.logger.error(
|
// this.logger.error(
|
||||||
// '未找到颜色编码解码后的原始 feature,请检查 fragment shader 中末尾是否添加了 `gl_FragColor = filterColor(gl_FragColor);`',
|
// '未找到颜色编码解码后的原始 feature,请检查 fragment shader 中末尾是否添加了 `gl_FragColor = filterColor(gl_FragColor);`',
|
||||||
// );
|
// );
|
||||||
} else {
|
} else {
|
||||||
// trigger onHover/Click callback on layer
|
// trigger onHover/Click callback on layer
|
||||||
this.triggerHoverOnLayer({ x, y, type, feature: rawFeature });
|
this.layer.setCurrentPickId(pickedFeatureIdx);
|
||||||
|
this.triggerHoverOnLayer(target);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
const target = {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
lngLat,
|
||||||
|
type: this.layer.getCurrentPickId() === null ? 'unpick' : 'mouseout',
|
||||||
|
featureId: null,
|
||||||
|
feature: null,
|
||||||
|
};
|
||||||
|
this.triggerHoverOnLayer(target);
|
||||||
|
this.layer.setCurrentPickId(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (enableHighlight) {
|
if (enableHighlight) {
|
||||||
this.highlightPickedFeature(pickedColors);
|
this.highlightPickedFeature(pickedColors);
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
enableSelect &&
|
||||||
|
type === 'click' &&
|
||||||
|
pickedColors?.toString() !== [0, 0, 0, 0].toString()
|
||||||
|
) {
|
||||||
|
this.selectFeature(pickedColors);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private triggerHoverOnLayer({
|
private triggerHoverOnLayer(target: {
|
||||||
x,
|
|
||||||
y,
|
|
||||||
type,
|
|
||||||
feature,
|
|
||||||
}: {
|
|
||||||
x: number;
|
x: number;
|
||||||
y: number;
|
y: number;
|
||||||
type: string;
|
type: string;
|
||||||
|
lngLat: ILngLat;
|
||||||
feature: unknown;
|
feature: unknown;
|
||||||
|
featureId: number | null;
|
||||||
}) {
|
}) {
|
||||||
const { onHover, onClick } = this.layer.getLayerConfig();
|
this.layer.emit(target.type, target);
|
||||||
// if (onHover) {
|
|
||||||
// onHover({
|
|
||||||
// x,
|
|
||||||
// y,
|
|
||||||
// feature,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// if (onClick) {
|
|
||||||
// onClick({
|
|
||||||
// x,
|
|
||||||
// y,
|
|
||||||
// feature,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
this.layer.emit(type, {
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
feature,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,7 +233,6 @@ export default class PixelPickingPass<
|
||||||
private highlightPickedFeature(pickedColors: Uint8Array | undefined) {
|
private highlightPickedFeature(pickedColors: Uint8Array | undefined) {
|
||||||
const [r, g, b] = pickedColors;
|
const [r, g, b] = pickedColors;
|
||||||
const { clear, useFramebuffer } = this.rendererService;
|
const { clear, useFramebuffer } = this.rendererService;
|
||||||
|
|
||||||
// 先输出到 PostProcessor
|
// 先输出到 PostProcessor
|
||||||
const readFBO = this.layer.multiPassRenderer
|
const readFBO = this.layer.multiPassRenderer
|
||||||
.getPostProcessor()
|
.getPostProcessor()
|
||||||
|
@ -257,4 +257,43 @@ export default class PixelPickingPass<
|
||||||
});
|
});
|
||||||
this.layer.multiPassRenderer.getPostProcessor().render(this.layer);
|
this.layer.multiPassRenderer.getPostProcessor().render(this.layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private selectFeature(pickedColors: Uint8Array | undefined) {
|
||||||
|
const [r, g, b] = pickedColors;
|
||||||
|
const { clear, useFramebuffer } = this.rendererService;
|
||||||
|
|
||||||
|
// 先输出到 PostProcessor
|
||||||
|
const readFBO = this.layer.multiPassRenderer
|
||||||
|
.getPostProcessor()
|
||||||
|
.getReadFBO();
|
||||||
|
this.layer.hooks.beforeRender.call();
|
||||||
|
useFramebuffer(readFBO, () => {
|
||||||
|
clear({
|
||||||
|
color: [0, 0, 0, 0],
|
||||||
|
depth: 1,
|
||||||
|
stencil: 0,
|
||||||
|
framebuffer: readFBO,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: highlight pass 需要 multipass
|
||||||
|
const originRenderFlag = this.layer.multiPassRenderer.getRenderFlag();
|
||||||
|
this.layer.multiPassRenderer.setRenderFlag(false);
|
||||||
|
this.layer.hooks.beforeSelect.call([r, g, b]);
|
||||||
|
this.layer.render();
|
||||||
|
this.layer.hooks.afterSelect.call();
|
||||||
|
this.layer.hooks.afterRender.call();
|
||||||
|
this.layer.multiPassRenderer.setRenderFlag(originRenderFlag);
|
||||||
|
});
|
||||||
|
this.layer.multiPassRenderer.getPostProcessor().render(this.layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private selectFeatureHander({ featureId }: Partial<IInteractionTarget>) {
|
||||||
|
const pickedColors = encodePickingColor(featureId as number);
|
||||||
|
this.selectFeature(new Uint8Array(pickedColors));
|
||||||
|
}
|
||||||
|
|
||||||
|
private highlightFeatureHander({ featureId }: Partial<IInteractionTarget>) {
|
||||||
|
const pickedColors = encodePickingColor(featureId as number);
|
||||||
|
this.highlightPickedFeature(new Uint8Array(pickedColors));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,8 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
||||||
afterPickingEncode: new SyncHook<void>(),
|
afterPickingEncode: new SyncHook<void>(),
|
||||||
beforeHighlight: new SyncHook<[number[]]>(['pickedColor']),
|
beforeHighlight: new SyncHook<[number[]]>(['pickedColor']),
|
||||||
afterHighlight: new SyncHook<void>(),
|
afterHighlight: new SyncHook<void>(),
|
||||||
|
beforeSelect: new SyncHook<[number[]]>(['pickedColor']),
|
||||||
|
afterSelect: new SyncHook<void>(),
|
||||||
beforeDestroy: new SyncHook<void>(),
|
beforeDestroy: new SyncHook<void>(),
|
||||||
afterDestroy: new SyncHook<void>(),
|
afterDestroy: new SyncHook<void>(),
|
||||||
};
|
};
|
||||||
|
@ -142,6 +144,8 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
||||||
|
|
||||||
private configSchema: object;
|
private configSchema: object;
|
||||||
|
|
||||||
|
private currentPickId: number | null = null;
|
||||||
|
|
||||||
private rawConfig: Partial<ILayerConfig & ChildLayerStyleOptions>;
|
private rawConfig: Partial<ILayerConfig & ChildLayerStyleOptions>;
|
||||||
|
|
||||||
private needUpdateConfig: Partial<ILayerConfig & ChildLayerStyleOptions>;
|
private needUpdateConfig: Partial<ILayerConfig & ChildLayerStyleOptions>;
|
||||||
|
@ -159,7 +163,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
||||||
|
|
||||||
private scaleOptions: IScaleOptions = {};
|
private scaleOptions: IScaleOptions = {};
|
||||||
|
|
||||||
constructor(config: Partial<ILayerConfig & ChildLayerStyleOptions>) {
|
constructor(config: Partial<ILayerConfig & ChildLayerStyleOptions> = {}) {
|
||||||
super();
|
super();
|
||||||
this.rawConfig = config;
|
this.rawConfig = config;
|
||||||
}
|
}
|
||||||
|
@ -469,10 +473,22 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
||||||
? options.color
|
? options.color
|
||||||
: this.getLayerConfig().highlightColor,
|
: this.getLayerConfig().highlightColor,
|
||||||
});
|
});
|
||||||
|
this.interactionService.triggerActive(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public select(option: IActiveOption | false): ILayer {
|
public select(option: IActiveOption | false): ILayer {
|
||||||
|
const activeOption: Partial<ILayerConfig> = {};
|
||||||
|
activeOption.enableSelect = isObject(option) ? true : option;
|
||||||
|
if (isObject(option)) {
|
||||||
|
activeOption.enableSelect = true;
|
||||||
|
if (option.color) {
|
||||||
|
activeOption.selectColor = option.color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
activeOption.enableHighlight = !!option;
|
||||||
|
}
|
||||||
|
this.updateLayerConfig(activeOption);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +496,23 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
||||||
id: number | { x: number; y: number },
|
id: number | { x: number; y: number },
|
||||||
options?: IActiveOption,
|
options?: IActiveOption,
|
||||||
): void {
|
): void {
|
||||||
throw new Error('Method not implemented.');
|
if (isObject(id)) {
|
||||||
|
const { x = 0, y = 0 } = id;
|
||||||
|
this.updateLayerConfig({
|
||||||
|
selectColor: isObject(options)
|
||||||
|
? options.color
|
||||||
|
: this.getLayerConfig().selectColor,
|
||||||
|
});
|
||||||
|
this.pick({ x, y });
|
||||||
|
} else {
|
||||||
|
this.updateLayerConfig({
|
||||||
|
pickedFeatureID: id,
|
||||||
|
selectColor: isObject(options)
|
||||||
|
? options.color
|
||||||
|
: this.getLayerConfig().selectColor,
|
||||||
|
});
|
||||||
|
this.interactionService.triggerSelect(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public show(): ILayer {
|
public show(): ILayer {
|
||||||
this.updateLayerConfig({
|
this.updateLayerConfig({
|
||||||
|
@ -502,6 +534,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public setCurrentPickId(id: number) {
|
||||||
|
this.currentPickId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCurrentPickId(): number | null {
|
||||||
|
return this.currentPickId;
|
||||||
|
}
|
||||||
public isVisible(): boolean {
|
public isVisible(): boolean {
|
||||||
const zoom = this.mapService.getZoom();
|
const zoom = this.mapService.getZoom();
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,10 @@ import {
|
||||||
IModelUniform,
|
IModelUniform,
|
||||||
ITexture2D,
|
ITexture2D,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
|
||||||
import { mat4 } from 'gl-matrix';
|
import { mat4 } from 'gl-matrix';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { HeatmapTriangulation } from '../../core/triangulation';
|
import { HeatmapTriangulation } from '../../core/triangulation';
|
||||||
import { generateColorRamp, IColorRamp } from '../../utils/color';
|
|
||||||
import heatmap3DFrag from '../shaders/heatmap_3d_frag.glsl';
|
import heatmap3DFrag from '../shaders/heatmap_3d_frag.glsl';
|
||||||
import heatmap3DVert from '../shaders/heatmap_3d_vert.glsl';
|
import heatmap3DVert from '../shaders/heatmap_3d_vert.glsl';
|
||||||
import heatmapColorFrag from '../shaders/heatmap_frag.glsl';
|
import heatmapColorFrag from '../shaders/heatmap_frag.glsl';
|
||||||
|
|
|
@ -9,8 +9,8 @@ import {
|
||||||
IStyleAttributeService,
|
IStyleAttributeService,
|
||||||
TYPES,
|
TYPES,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
import { rgb2arr } from '@antv/l7-utils';
|
||||||
import { inject, injectable } from 'inversify';
|
import { inject, injectable } from 'inversify';
|
||||||
import { rgb2arr } from '../utils/color';
|
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class DataMappingPlugin implements ILayerPlugin {
|
export default class DataMappingPlugin implements ILayerPlugin {
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default class DataSourcePlugin implements ILayerPlugin {
|
||||||
const source = layer.getSource();
|
const source = layer.getSource();
|
||||||
const cluster = source.cluster;
|
const cluster = source.cluster;
|
||||||
const { zoom = 0, maxZoom = 16 } = source.clusterOptions;
|
const { zoom = 0, maxZoom = 16 } = source.clusterOptions;
|
||||||
const newZoom = this.mapService.getZoom();
|
const newZoom = this.mapService.getZoom() - 1;
|
||||||
if (cluster && Math.abs(zoom - newZoom) > 1 && maxZoom > zoom) {
|
if (cluster && Math.abs(zoom - newZoom) > 1 && maxZoom > zoom) {
|
||||||
source.updateClusterData(Math.floor(newZoom));
|
source.updateClusterData(Math.floor(newZoom));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ILayer, ILayerPlugin, IMapService, TYPES } from '@antv/l7-core';
|
import { ILayer, ILayerPlugin, IMapService, TYPES } from '@antv/l7-core';
|
||||||
import Source from '@antv/l7-source';
|
import Source from '@antv/l7-source';
|
||||||
|
import { encodePickingColor, rgb2arr } from '@antv/l7-utils';
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import { encodePickingColor, rgb2arr } from '../utils/color';
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export default class LayerStylePlugin implements ILayerPlugin {
|
export default class LayerStylePlugin implements ILayerPlugin {
|
||||||
public apply(layer: ILayer) {
|
public apply(layer: ILayer) {
|
||||||
|
|
|
@ -7,8 +7,8 @@ import {
|
||||||
IRendererService,
|
IRendererService,
|
||||||
IStyleAttributeService,
|
IStyleAttributeService,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
import { encodePickingColor, rgb2arr } from '@antv/l7-utils';
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import { encodePickingColor, rgb2arr } from '../utils/color';
|
|
||||||
|
|
||||||
const PickingStage = {
|
const PickingStage = {
|
||||||
NONE: 0.0,
|
NONE: 0.0,
|
||||||
|
@ -95,6 +95,24 @@ export default class PixelPickingPlugin implements ILayerPlugin {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
layer.hooks.beforeSelect.tap(
|
||||||
|
'PixelPickingPlugin',
|
||||||
|
(pickedColor: number[]) => {
|
||||||
|
const { selectColor } = layer.getLayerConfig();
|
||||||
|
const highlightColorInArray =
|
||||||
|
typeof selectColor === 'string'
|
||||||
|
? rgb2arr(selectColor)
|
||||||
|
: selectColor || [1, 0, 0, 1];
|
||||||
|
layer.models.forEach((model) =>
|
||||||
|
model.addUniforms({
|
||||||
|
u_PickingStage: PickingStage.HIGHLIGHT,
|
||||||
|
u_PickingColor: pickedColor,
|
||||||
|
u_HighlightColor: highlightColorInArray.map((c) => c * 255),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import {
|
||||||
IModel,
|
IModel,
|
||||||
IModelUniform,
|
IModelUniform,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
import { rgb2arr } from '@antv/l7-utils';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { PointFillTriangulation } from '../../core/triangulation';
|
import { PointFillTriangulation } from '../../core/triangulation';
|
||||||
import { rgb2arr } from '../../utils/color';
|
|
||||||
import pointFillFrag from '../shaders/fill_frag.glsl';
|
import pointFillFrag from '../shaders/fill_frag.glsl';
|
||||||
import pointFillVert from '../shaders/fill_vert.glsl';
|
import pointFillVert from '../shaders/fill_vert.glsl';
|
||||||
interface IPointLayerStyleOptions {
|
interface IPointLayerStyleOptions {
|
||||||
|
|
|
@ -6,8 +6,8 @@ import {
|
||||||
IModelUniform,
|
IModelUniform,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
|
||||||
|
import { rgb2arr } from '@antv/l7-utils';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { rgb2arr } from '../../utils/color';
|
|
||||||
import normalFrag from '../shaders/normal_frag.glsl';
|
import normalFrag from '../shaders/normal_frag.glsl';
|
||||||
import normalVert from '../shaders/normal_vert.glsl';
|
import normalVert from '../shaders/normal_vert.glsl';
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import {
|
||||||
lazyInject,
|
lazyInject,
|
||||||
TYPES,
|
TYPES,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
|
||||||
import BaseLayer from '../core/BaseLayer';
|
import BaseLayer from '../core/BaseLayer';
|
||||||
import { generateColorRamp, IColorRamp } from '../utils/color';
|
|
||||||
import { RasterTriangulation } from './buffers/triangulation';
|
import { RasterTriangulation } from './buffers/triangulation';
|
||||||
import rasterFrag from './shaders/raster_frag.glsl';
|
import rasterFrag from './shaders/raster_frag.glsl';
|
||||||
import rasterVert from './shaders/raster_vert.glsl';
|
import rasterVert from './shaders/raster_vert.glsl';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { AttributeType, gl, IEncodeFeature, ITexture2D } from '@antv/l7-core';
|
import { AttributeType, gl, IEncodeFeature, ITexture2D } from '@antv/l7-core';
|
||||||
|
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
|
||||||
import BaseLayer from '../core/BaseLayer';
|
import BaseLayer from '../core/BaseLayer';
|
||||||
import { RasterImageTriangulation } from '../core/triangulation';
|
import { RasterImageTriangulation } from '../core/triangulation';
|
||||||
import { generateColorRamp, IColorRamp } from '../utils/color';
|
|
||||||
import rasterImageFrag from './shaders/raster_2d_frag.glsl';
|
import rasterImageFrag from './shaders/raster_2d_frag.glsl';
|
||||||
import rasterImageVert from './shaders/raster_2d_vert.glsl';
|
import rasterImageVert from './shaders/raster_2d_vert.glsl';
|
||||||
interface IRasterLayerStyleOptions {
|
interface IRasterLayerStyleOptions {
|
||||||
|
|
|
@ -15,6 +15,13 @@ export function rgb2arr(str: string) {
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function decodePickingColor(color: Uint8Array): number {
|
||||||
|
const [i1, i2, i3] = color;
|
||||||
|
// 1 was added to seperate from no selection
|
||||||
|
const index = i1 + i2 * 256 + i3 * 65536 - 1;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
export function encodePickingColor(
|
export function encodePickingColor(
|
||||||
featureIdx: number,
|
featureIdx: number,
|
||||||
): [number, number, number] {
|
): [number, number, number] {
|
|
@ -4,4 +4,5 @@ export * from './fetchData';
|
||||||
export * from './geo';
|
export * from './geo';
|
||||||
export * from './lru_cache';
|
export * from './lru_cache';
|
||||||
export * from './event';
|
export * from './event';
|
||||||
|
export * from './color';
|
||||||
export { DOM };
|
export { DOM };
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default class Point3D extends React.Component {
|
||||||
|
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
id: 'map',
|
id: 'map',
|
||||||
map: new GaodeMap({
|
map: new Mapbox({
|
||||||
center: [120.19382669582967, 30.258134],
|
center: [120.19382669582967, 30.258134],
|
||||||
pitch: 0,
|
pitch: 0,
|
||||||
style: 'dark',
|
style: 'dark',
|
||||||
|
@ -36,13 +36,18 @@ export default class Point3D extends React.Component {
|
||||||
type: 'quantile',
|
type: 'quantile',
|
||||||
})
|
})
|
||||||
.size('point_count', [5, 10, 15, 20, 25])
|
.size('point_count', [5, 10, 15, 20, 25])
|
||||||
.active(true)
|
.color('yellow')
|
||||||
.color('red')
|
|
||||||
.style({
|
.style({
|
||||||
opacity: 0.3,
|
opacity: 0.5,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
});
|
});
|
||||||
scene.addLayer(pointLayer);
|
scene.addLayer(pointLayer);
|
||||||
|
pointLayer.on('mousemove', (e) => {
|
||||||
|
const id = e.featureId;
|
||||||
|
console.log(id);
|
||||||
|
pointLayer.setActive(id);
|
||||||
|
});
|
||||||
|
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,21 +21,14 @@ export default class Point3D extends React.Component {
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const pointLayer = new PointLayer({
|
const pointLayer = new PointLayer();
|
||||||
enablePicking: false,
|
|
||||||
enableHighlight: false,
|
|
||||||
enableTAA: false,
|
|
||||||
onHover: (pickedFeature: any) => {
|
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
console.log('Scene4', pickedFeature.feature.name);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
pointLayer
|
pointLayer
|
||||||
.source(data, {
|
.source(data, {
|
||||||
cluster: true,
|
cluster: true,
|
||||||
})
|
})
|
||||||
.color('red')
|
.color('red')
|
||||||
.shape('cylinder')
|
.shape('cylinder')
|
||||||
|
.active({ color: 'blue' })
|
||||||
.size([15, 10]);
|
.size([15, 10]);
|
||||||
scene.addLayer(pointLayer);
|
scene.addLayer(pointLayer);
|
||||||
scene.render();
|
scene.render();
|
||||||
|
|
|
@ -41,6 +41,7 @@ export default class Polygon3D extends React.Component {
|
||||||
.source(await response.json())
|
.source(await response.json())
|
||||||
.shape('extrude')
|
.shape('extrude')
|
||||||
.size('h20', [100, 120, 160, 200, 260, 500])
|
.size('h20', [100, 120, 160, 200, 260, 500])
|
||||||
|
.active({ color: 'blue' })
|
||||||
.color('h20', [
|
.color('h20', [
|
||||||
'#816CAD',
|
'#816CAD',
|
||||||
'#A67FB5',
|
'#A67FB5',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { PolygonLayer, Scene } from '@antv/l7';
|
import { PolygonLayer, Popup, Scene } from '@antv/l7';
|
||||||
import { Mapbox } from '@antv/l7-maps';
|
import { Mapbox } from '@antv/l7-maps';
|
||||||
import * as dat from 'dat.gui';
|
import * as dat from 'dat.gui';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
@ -24,15 +24,7 @@ export default class Tooltip extends React.Component {
|
||||||
zoom: 3,
|
zoom: 3,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const layer = new PolygonLayer({
|
const layer = new PolygonLayer();
|
||||||
enablePicking: true,
|
|
||||||
enableHighlight: false,
|
|
||||||
onHover: (pickedFeature) => {
|
|
||||||
// tslint:disable-next-line:no-console
|
|
||||||
console.log(pickedFeature);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
layer
|
layer
|
||||||
.source(await response.json())
|
.source(await response.json())
|
||||||
.size('name', [0, 10000, 50000, 30000, 100000])
|
.size('name', [0, 10000, 50000, 30000, 100000])
|
||||||
|
@ -49,6 +41,14 @@ export default class Tooltip extends React.Component {
|
||||||
opacity: 0.8,
|
opacity: 0.8,
|
||||||
});
|
});
|
||||||
scene.addLayer(layer);
|
scene.addLayer(layer);
|
||||||
|
layer.on('click', (e) => {
|
||||||
|
const popup = new Popup({
|
||||||
|
offsets: [0, 0],
|
||||||
|
})
|
||||||
|
.setLnglat(e.lngLat)
|
||||||
|
.setText(e.feature.properties.name);
|
||||||
|
scene.addPopup(popup);
|
||||||
|
});
|
||||||
|
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue