mirror of https://gitee.com/antv-l7/antv-l7
feat: 完善矢量图层事件的数据拾取 (#1449)
* feat: change vector tile get data * feat: 瓦片图层事件支持获取数据 * style: lint style * feat: 修改瓦片图层事件获取数据的方法 * style: lint style * fix: 修复 MaskLayer 失效 * feat: 完善矢量瓦片事件获取数据 * feat: geojson-vt 兼容新的数据解析逻辑 * style: lint style * feat: add tile getMainLayer * style: lint style Co-authored-by: shihui <yiqianyao.yqy@alibaba-inc.com>
This commit is contained in:
parent
58947c2461
commit
cf6b0f8147
|
@ -45,7 +45,7 @@ export default () => {
|
|||
// const height = image.getHeight();
|
||||
// const value0 = await image.readRasters();
|
||||
|
||||
const image1 = await tiff.getImage(1);
|
||||
const image1 = await tiff.getImage(2);
|
||||
const value1 = await image1.readRasters();
|
||||
// console.log(value1)
|
||||
|
||||
|
@ -67,14 +67,43 @@ export default () => {
|
|||
operation: {
|
||||
// blue green red nir
|
||||
// 标准真彩色 rgb
|
||||
r: ['-', ['band', 2], 155],
|
||||
g: ['-', ['band', 1], 184],
|
||||
b: ['-', ['band', 0], 295],
|
||||
// r: ['-', ['band', 2], 155],
|
||||
// g: ['-', ['band', 1], 184],
|
||||
// b: ['-', ['band', 0], 295],
|
||||
|
||||
// 标准假彩色 4,3,2
|
||||
// // 标准假彩色 4,3,2
|
||||
// r: ['-', ['band', 3], 295],
|
||||
// g: ['-', ['band', 2], 184],
|
||||
// b: ['-', ['band', 1], 295],
|
||||
|
||||
// 标准假彩色 4,3,2
|
||||
|
||||
|
||||
// r: ['*', ['/', ['band', 3], 234], 255],
|
||||
// g: ['*', ['/', ['band', 2], 296], 255],
|
||||
// b: ['*', ['/', ['band', 1], 296], 255],
|
||||
|
||||
// r: ['-', ['band', 3], 234],
|
||||
// g: ['-', ['band', 2], 296],
|
||||
// b: ['-', ['band', 1], 296],
|
||||
|
||||
// r: ['/', ['band', 3], 234],
|
||||
// g: ['/', ['band', 2], 296],
|
||||
// b: ['/', ['band', 1], 296],
|
||||
|
||||
|
||||
// r: ['/', ['band', 3], 2],
|
||||
// g: ['/', ['band', 2], 2],
|
||||
// b: ['/', ['band', 1], 2],
|
||||
|
||||
|
||||
// r: ['band', 3],
|
||||
// g: ['band', 2],
|
||||
// b: ['band', 1],
|
||||
|
||||
r: ['-', ['band', 3], 113],
|
||||
g: ['-', ['band', 2], 155],
|
||||
b: ['-', ['band', 1], 184],
|
||||
},
|
||||
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
|
||||
},
|
||||
|
@ -89,9 +118,17 @@ export default () => {
|
|||
// channelGMax: 131,
|
||||
// channelBMax: 141
|
||||
|
||||
// channelRMax: 256,
|
||||
// channelGMax: 256,
|
||||
// channelBMax: 256
|
||||
// channelRMax: 234,
|
||||
// channelGMax: 296,
|
||||
// channelBMax: 296
|
||||
|
||||
channelRMax: 234 - 133,
|
||||
channelGMax: 296 - 155,
|
||||
channelBMax: 296 - 184
|
||||
|
||||
// channelRMax: 255,
|
||||
// channelGMax: 255,
|
||||
// channelBMax: 255
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
});
|
||||
|
|
|
@ -16,7 +16,10 @@ export default () => {
|
|||
}),
|
||||
});
|
||||
|
||||
fetch('http://30.230.91.181:8080/water.geojson')
|
||||
// fetch('http://30.230.91.181:8080/water.geojson')
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/2b7aae6e-5f40-437f-8047-100e9a0d2808.json',
|
||||
)
|
||||
.then((d) => d.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @ts-ignore
|
||||
import { Scene, RasterLayer } from '@antv/l7';
|
||||
import { Scene, RasterLayer, MaskLayer } from '@antv/l7';
|
||||
// @ts-ignore
|
||||
import { Map } from '@antv/l7-maps';
|
||||
import React, { useEffect } from 'react';
|
||||
|
@ -16,26 +16,26 @@ export default () => {
|
|||
}),
|
||||
});
|
||||
|
||||
// const mask = new MaskLayer({
|
||||
// sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city
|
||||
// }).source(
|
||||
// 'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf',
|
||||
// {
|
||||
// parser: {
|
||||
// type: 'mvt',
|
||||
// tileSize: 256,
|
||||
// maxZoom: 9,
|
||||
// extent: [-180, -85.051129, 179, 85.051129],
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
const mask = new MaskLayer({
|
||||
sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city
|
||||
}).source(
|
||||
'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf',
|
||||
{
|
||||
parser: {
|
||||
type: 'mvt',
|
||||
tileSize: 256,
|
||||
maxZoom: 9,
|
||||
extent: [-180, -85.051129, 179, 85.051129],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const layer = new RasterLayer({
|
||||
zIndex: 1,
|
||||
// mask: true,
|
||||
mask: true,
|
||||
}).source(
|
||||
'https://www.google.cn/maps/vt?lyrs=s@820&gl=cn&x={x}&y={y}&z={z}',
|
||||
// 'http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
// 'https://www.google.cn/maps/vt?lyrs=s@820&gl=cn&x={x}&y={y}&z={z}',
|
||||
'http://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}',
|
||||
{
|
||||
parser: {
|
||||
type: 'rasterTile',
|
||||
|
@ -46,7 +46,7 @@ export default () => {
|
|||
);
|
||||
|
||||
scene.on('loaded', () => {
|
||||
// scene.addLayer(mask);
|
||||
scene.addLayer(mask);
|
||||
scene.addLayer(layer);
|
||||
});
|
||||
}, []);
|
||||
|
|
|
@ -225,7 +225,7 @@ export default class PickingService implements IPickingService {
|
|||
) {
|
||||
const pickedFeatureIdx = decodePickingColor(pickedColors);
|
||||
|
||||
const rawFeature = layer.layerPickService.getFeatureById(pickedFeatureIdx, lngLat);
|
||||
const rawFeature = layer.layerPickService.getFeatureById(pickedFeatureIdx);
|
||||
if (
|
||||
pickedFeatureIdx !== layer.getCurrentPickId() &&
|
||||
type === 'mousemove'
|
||||
|
|
|
@ -225,27 +225,9 @@ export interface ITile {
|
|||
sourceTile: SourceTile;
|
||||
visible: boolean;
|
||||
isLoaded: boolean;
|
||||
getMainLayer(): ILayer | undefined;
|
||||
getLayers(): ILayer[];
|
||||
styleUpdate(...args: any): void;
|
||||
initTileLayer(): Promise<void>;
|
||||
lnglatInBounds(lnglat: {
|
||||
lng: number;
|
||||
lat: number;
|
||||
}): boolean;
|
||||
updateVisible(value: boolean): void;
|
||||
updateOptions(key: string, value: any): void;
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
export interface ITile {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
key: string;
|
||||
sourceTile: SourceTile;
|
||||
visible: boolean;
|
||||
isLoaded: boolean;
|
||||
getLayers(): ILayer[];
|
||||
getFeatureById(id: number): any;
|
||||
styleUpdate(...args: any): void;
|
||||
initTileLayer(): Promise<void>;
|
||||
lnglatInBounds(lnglat: {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { ILayerService, ITile, ITilePickService, ILngLat, IInteractionTarget } from '@antv/l7-core';
|
||||
import { ILayerService, ITile, ITilePickService, IInteractionTarget } from '@antv/l7-core';
|
||||
import { TileLayerService } from './TileLayerService';
|
||||
import { TileSourceService } from './TileSourceService';
|
||||
export interface ITilePickServiceOptions {
|
||||
layerService: ILayerService;
|
||||
tileLayerService: TileLayerService;
|
||||
|
@ -10,18 +11,22 @@ const ACTIVE = 'active';
|
|||
export class TilePickService implements ITilePickService{
|
||||
private layerService: ILayerService;
|
||||
private tileLayerService: TileLayerService;
|
||||
private tileSourceService: TileSourceService;
|
||||
private tilePickID = new Map();
|
||||
constructor({ layerService, tileLayerService }: ITilePickServiceOptions) {
|
||||
this.layerService = layerService;
|
||||
this.tileLayerService = tileLayerService;
|
||||
this.tileSourceService = new TileSourceService();
|
||||
}
|
||||
pickRender(target: IInteractionTarget) {
|
||||
// 一个 TileLayer 有多个 Tile,但是会同时触发事件的只有一个 Tile
|
||||
const tile = this.tileLayerService.getVisibleTileBylngLat(target.lngLat);
|
||||
if (tile) {
|
||||
// TODO 多图层拾取
|
||||
const pickLayer = tile.getLayers()[0];
|
||||
pickLayer.layerPickService.pickRender(target)
|
||||
const pickLayer = tile.getMainLayer();
|
||||
if (pickLayer) {
|
||||
pickLayer.layerPickService.pickRender(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
selectFeature(pickedColors: Uint8Array | undefined) {
|
||||
|
@ -80,30 +85,20 @@ export class TilePickService implements ITilePickService{
|
|||
}
|
||||
|
||||
/** 从瓦片中根据数据 */
|
||||
getFeatureById(pickedFeatureIdx: number, lngLat: ILngLat) {
|
||||
const tile = this.tileLayerService.getVisibleTileBylngLat(lngLat)
|
||||
if (!tile) {
|
||||
getFeatureById(pickedFeatureIdx: number) {
|
||||
// 提取当前可见瓦片
|
||||
const tiles = this.tileLayerService.getTiles().filter(tile => tile.visible);
|
||||
// 提取当前可见瓦片中匹配 ID 的 feature 列表
|
||||
const features: any[] = [];
|
||||
tiles.map(tile => {
|
||||
features.push(...tile.getFeatureById(pickedFeatureIdx));
|
||||
})
|
||||
|
||||
if (features.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const layers = tile.getLayers();
|
||||
let features = null;
|
||||
// 瓦片数据各自独立分布,没有完整的集合
|
||||
// TODO: 合并瓦片矢量数据,返回完整的的数据集
|
||||
layers.some(layer => {
|
||||
// 图层的 originData 可能并没有 id,因此我们使用编码后的 dataArray
|
||||
const data = layer.getSource().data.dataArray;
|
||||
|
||||
// _id 编码值可能根据字段进行编码,因此可能命中多个 feature
|
||||
const pickedFeature = data.filter(d => d._id === pickedFeatureIdx)
|
||||
|
||||
if(pickedFeature.length > 0) {
|
||||
features = pickedFeature;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
return features;
|
||||
// 将 feature 列表合并后返回
|
||||
// 统一返回成 polygon 的格式 点、线、面可以通用
|
||||
return this.tileSourceService.getCombineFeature(features);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import { IParseDataItem } from '@antv/l7-core';
|
||||
import * as turf from '@turf/helpers';
|
||||
import union from '@turf/union';
|
||||
|
||||
/**
|
||||
* 专门处理 Tile 数据相关
|
||||
*/
|
||||
export class TileSourceService {
|
||||
public getCombineFeature(features: IParseDataItem[]) {
|
||||
let p: any = null;
|
||||
const properties = features[0];
|
||||
features.map((feature) => {
|
||||
const polygon = turf.polygon(feature.coordinates);
|
||||
if (p === null) {
|
||||
p = polygon;
|
||||
} else {
|
||||
p = union(p, polygon);
|
||||
}
|
||||
});
|
||||
|
||||
if (properties) {
|
||||
p.properties = { ...properties };
|
||||
}
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -25,8 +25,7 @@ export default class MaskTile extends Tile {
|
|||
const { sourceLayer, featureId } = this.parent.getLayerConfig<{
|
||||
featureId: string;
|
||||
}>();
|
||||
const features = this.sourceTile.data.layers[sourceLayer as string]
|
||||
.features;
|
||||
const features = this.getFeatures(sourceLayer)
|
||||
return {
|
||||
data: {
|
||||
type: 'FeatureCollection',
|
||||
|
|
|
@ -68,10 +68,25 @@ export default abstract class Tile implements ITile{
|
|||
});
|
||||
}
|
||||
|
||||
public getFeatures(sourceLayer: string | undefined){
|
||||
if(!sourceLayer || !this.sourceTile.data?.layers[sourceLayer]) return [];
|
||||
/**
|
||||
* 一个 Tile 可能有多个 layer,但是在发生拾取、点击事件的时候只有一个生效
|
||||
*/
|
||||
public getMainLayer(): ILayer | undefined {
|
||||
return this.layers[0];
|
||||
}
|
||||
|
||||
public getFeatures(sourceLayer: string | undefined){
|
||||
if(!sourceLayer || !this.sourceTile.data?.layers[sourceLayer]) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const vectorTile = this.sourceTile.data?.layers[sourceLayer];
|
||||
|
||||
if(Array.isArray(vectorTile.features)) {
|
||||
// 数据不需要被解析 geojson-vt 类型
|
||||
return vectorTile.features;
|
||||
}
|
||||
|
||||
const { x, y, z } = this.sourceTile;
|
||||
const features: Feature<GeoJSON.Geometry, Properties>[] = [];
|
||||
for( let i = 0; i < vectorTile.length; i++ ) {
|
||||
|
@ -88,6 +103,19 @@ export default abstract class Tile implements ITile{
|
|||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在一个 Tile 中可能存在一个相同 ID 的 feature
|
||||
* @param id
|
||||
* @returns
|
||||
*/
|
||||
public getFeatureById(id: number) {
|
||||
const layer = this.getMainLayer();
|
||||
if (!layer) {
|
||||
return [];
|
||||
}
|
||||
return layer.getSource().data.dataArray.filter(d => d._id === id);
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.layers.forEach((layer) => layer.destroy());
|
||||
}
|
||||
|
|
|
@ -60,13 +60,7 @@ export default class VectorTile extends Tile {
|
|||
const { sourceLayer = 'defaultLayer', featureId = 'id'} = this.parent.getLayerConfig<{
|
||||
featureId: string;
|
||||
}>();
|
||||
|
||||
const vectorLayer = this.sourceTile.data.layers[sourceLayer as string]
|
||||
if(!vectorLayer) {
|
||||
return false
|
||||
}
|
||||
|
||||
const features = vectorLayer.features;
|
||||
const features = this.getFeatures(sourceLayer)
|
||||
return {
|
||||
data: {
|
||||
type: 'FeatureCollection',
|
||||
|
|
Loading…
Reference in New Issue