feat(picking): support advanced picking API: `layer.pick({x, y})`

This commit is contained in:
yuqi.pyq 2019-10-25 17:16:53 +08:00
parent 5fc540f8fd
commit 39fb89cc7f
8 changed files with 48 additions and 13 deletions

View File

@ -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';

View File

@ -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;
}

View File

@ -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) {

View File

@ -73,6 +73,10 @@ export interface ILayer {
getEncodedData(): IEncodeFeature[];
getStyleOptions(): Partial<ILayerInitializationOptions>;
isDirty(): boolean;
/**
* 使
*/
pick(query: { x: number; y: number }): void;
}
/**

View File

@ -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,
});
}
}
/**

View File

@ -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, {

View File

@ -1 +0,0 @@
xxxss

View File

@ -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[]) => {