mirror of https://gitee.com/antv-l7/antv-l7
feat(picking): support advanced picking API: `layer.pick({x, y})`
This commit is contained in:
parent
5fc540f8fd
commit
39fb89cc7f
|
@ -55,6 +55,7 @@ export * from './services/component/IControlService';
|
|||
export * from './services/component/IMarkerService';
|
||||
export * from './services/component/IPopUpService';
|
||||
export * from './services/log/ILogService';
|
||||
export * from './services/interaction/IInteractionService';
|
||||
|
||||
/** 全部渲染服务接口 */
|
||||
export * from './services/renderer/IAttribute';
|
||||
|
|
|
@ -10,4 +10,5 @@ export interface IInteractionService {
|
|||
eventName: InteractionEvent,
|
||||
callback: (params: { x: number; y: number }) => void,
|
||||
): void;
|
||||
triggerHover({ x, y }: { x: number; y: number }): void;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ export default class InteractionService extends EventEmitter
|
|||
this.off(InteractionEvent.Hover);
|
||||
}
|
||||
|
||||
public triggerHover({ x, y }: { x: number; y: number }) {
|
||||
this.emit(InteractionEvent.Hover, { x, y });
|
||||
}
|
||||
|
||||
private addEventListenerOnMap() {
|
||||
const $containter = this.mapService.getMapContainer();
|
||||
if ($containter) {
|
||||
|
|
|
@ -73,6 +73,10 @@ export interface ILayer {
|
|||
getEncodedData(): IEncodeFeature[];
|
||||
getStyleOptions(): Partial<ILayerInitializationOptions>;
|
||||
isDirty(): boolean;
|
||||
/**
|
||||
* 直接调用拾取方法,在非鼠标交互场景中使用
|
||||
*/
|
||||
pick(query: { x: number; y: number }): void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -126,11 +126,17 @@ export default class PixelPickingPass implements IPass {
|
|||
const { width, height } = getViewportSize();
|
||||
const { enableHighlight } = this.layer.getStyleOptions();
|
||||
|
||||
const xInDevicePixel = x * window.devicePixelRatio;
|
||||
const yInDevicePixel = y * window.devicePixelRatio;
|
||||
if (xInDevicePixel > width || xInDevicePixel < 0 || yInDevicePixel > height || yInDevicePixel < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let pickedColors: Uint8Array | undefined;
|
||||
useFramebuffer(this.pickingFBO, () => {
|
||||
// avoid realloc
|
||||
pickedColors = readPixels({
|
||||
x: Math.round(x * window.devicePixelRatio),
|
||||
x: Math.round(xInDevicePixel),
|
||||
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
|
||||
y: Math.round(height - (y + 1) * window.devicePixelRatio),
|
||||
width: 1,
|
||||
|
@ -171,7 +177,6 @@ export default class PixelPickingPass implements IPass {
|
|||
y: number;
|
||||
feature: unknown;
|
||||
}) {
|
||||
// TODO: onClick
|
||||
const { onHover, onClick } = this.layer.getStyleOptions();
|
||||
if (onHover) {
|
||||
onHover({
|
||||
|
@ -180,6 +185,13 @@ export default class PixelPickingPass implements IPass {
|
|||
feature,
|
||||
});
|
||||
}
|
||||
if (onClick) {
|
||||
onClick({
|
||||
x,
|
||||
y,
|
||||
feature,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,12 +3,14 @@ import {
|
|||
IFontService,
|
||||
IGlobalConfigService,
|
||||
IIconService,
|
||||
IInteractionService,
|
||||
ILayer,
|
||||
ILayerInitializationOptions,
|
||||
ILayerPlugin,
|
||||
IMapService,
|
||||
IModel,
|
||||
IMultiPassRenderer,
|
||||
InteractionEvent,
|
||||
IRendererService,
|
||||
IShaderModuleService,
|
||||
ISourceCFG,
|
||||
|
@ -149,6 +151,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
|
|||
@lazyInject(TYPES.IMapService)
|
||||
private readonly map: IMapService;
|
||||
|
||||
@lazyInject(TYPES.IInteractionService)
|
||||
private readonly interactionService: IInteractionService;
|
||||
|
||||
constructor(
|
||||
styleOptions: Partial<ILayerInitializationOptions & ChildLayerStyleOptions>,
|
||||
) {
|
||||
|
@ -278,6 +283,10 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
|
|||
return this.encodedData;
|
||||
}
|
||||
|
||||
public pick({ x, y }: { x: number; y: number }) {
|
||||
this.interactionService.triggerHover({ x, y });
|
||||
}
|
||||
|
||||
protected buildLayerModel(options: ILayerModelInitializationOptions): IModel {
|
||||
const { moduleName, vertexShader, fragmentShader, triangulation } = options;
|
||||
this.shaderModuleService.registerModule(moduleName, {
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
xxxss
|
|
@ -69,17 +69,10 @@ export default class AdvancedAPI extends React.Component {
|
|||
enablePicking: true,
|
||||
enableHighlight: true,
|
||||
highlightColor: [0, 0, 255],
|
||||
pickingX: window.innerWidth / 2,
|
||||
pickingY: window.innerHeight / 2,
|
||||
};
|
||||
const pointFolder = gui.addFolder('拾取 & 高亮');
|
||||
// pointFolder
|
||||
// .add(styleOptions, 'enablePicking')
|
||||
// .onChange((enablePicking: boolean) => {
|
||||
// // FIXME: 该配置项会影响到初始化阶段 PixelPickingPass 的添加,暂不支持在运行时更改
|
||||
// layer.style({
|
||||
// enablePicking,
|
||||
// });
|
||||
// scene.render();
|
||||
// });
|
||||
const pointFolder = gui.addFolder('非鼠标 hover 交互');
|
||||
pointFolder
|
||||
.add(styleOptions, 'enableHighlight')
|
||||
.onChange((enableHighlight: boolean) => {
|
||||
|
@ -88,6 +81,18 @@ export default class AdvancedAPI extends React.Component {
|
|||
});
|
||||
scene.render();
|
||||
});
|
||||
pointFolder
|
||||
.add(styleOptions, 'pickingX', 0, window.innerWidth)
|
||||
.onChange((pickingX: number) => {
|
||||
layer.pick({ x: pickingX, y: styleOptions.pickingY });
|
||||
// scene.render();
|
||||
});
|
||||
pointFolder
|
||||
.add(styleOptions, 'pickingY', 0, window.innerHeight)
|
||||
.onChange((pickingY: number) => {
|
||||
layer.pick({ x: styleOptions.pickingX, y: pickingY });
|
||||
// scene.render();
|
||||
});
|
||||
pointFolder
|
||||
.addColor(styleOptions, 'highlightColor')
|
||||
.onChange((highlightColor: number[]) => {
|
||||
|
|
Loading…
Reference in New Issue