mirror of https://gitee.com/antv-l7/antv-l7
feat: 矢量图层支持 geojson-vt (#1302)
* feat: 矢量图层支持 geojson-vt * feat: 优化 parser 类型获取、内置 sourceLayer * style: lint style Co-authored-by: shihui <yiqianyao.yqy@alibaba-inc.com>
This commit is contained in:
parent
ae1aa59879
commit
1e9dfaa310
|
@ -0,0 +1,2 @@
|
||||||
|
### geojson - vt
|
||||||
|
<code src="./geojson-vt.tsx"></code>
|
|
@ -0,0 +1,72 @@
|
||||||
|
// @ts-ignore
|
||||||
|
import { Scene, Source, PolygonLayer } from '@antv/l7';
|
||||||
|
// @ts-ignore
|
||||||
|
import { Mapbox } from '@antv/l7-maps';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
useEffect(() => {
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
stencil: true,
|
||||||
|
map: new Mapbox({
|
||||||
|
center: [121.268, 30.3628],
|
||||||
|
pitch: 0,
|
||||||
|
style: 'blank',
|
||||||
|
zoom: 4,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(
|
||||||
|
'https://gw.alipayobjects.com/os/bmw-prod/2b7aae6e-5f40-437f-8047-100e9a0d2808.json',
|
||||||
|
)
|
||||||
|
.then((d) => d.json())
|
||||||
|
.then((data) => {
|
||||||
|
const source = new Source(data, {
|
||||||
|
parser: {
|
||||||
|
type: 'geojsonvt',
|
||||||
|
tileSize: 256,
|
||||||
|
zoomOffset: 0,
|
||||||
|
maxZoom: 9,
|
||||||
|
extent: [-180, -85.051129, 179, 85.051129],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// const line = new LineLayer({
|
||||||
|
// featureId: 'COLOR',
|
||||||
|
// sourceLayer: 'testName', // woods hillshade contour ecoregions ecoregions2 city
|
||||||
|
// }).source(source)
|
||||||
|
// .color('COLOR')
|
||||||
|
// .size(2)
|
||||||
|
// scene.addLayer(line);
|
||||||
|
|
||||||
|
const polygon = new PolygonLayer({
|
||||||
|
featureId: 'COLOR',
|
||||||
|
// sourceLayer: 'testName', // woods hillshade contour ecoregions ecoregions2 city
|
||||||
|
})
|
||||||
|
.source(source)
|
||||||
|
.color('COLOR')
|
||||||
|
.active(true);
|
||||||
|
scene.addLayer(polygon);
|
||||||
|
|
||||||
|
// const point = new PointLayer({
|
||||||
|
// featureId: 'COLOR',
|
||||||
|
// sourceLayer: 'testName', // woods hillshade contour ecoregions ecoregions2 city
|
||||||
|
// })
|
||||||
|
// .source(source)
|
||||||
|
// // .color('COLOR')
|
||||||
|
// .color('#f00')
|
||||||
|
// .size(20)
|
||||||
|
// scene.addLayer(point);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="map"
|
||||||
|
style={{
|
||||||
|
height: '500px',
|
||||||
|
position: 'relative',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -4,57 +4,6 @@ import { Scene, LineLayer } from '@antv/l7';
|
||||||
import { Mapbox } from '@antv/l7-maps';
|
import { Mapbox } from '@antv/l7-maps';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
const list = [
|
|
||||||
{
|
|
||||||
value: -28.0,
|
|
||||||
color1: 'orange',
|
|
||||||
province_adcode: '630000',
|
|
||||||
province_adName: '青海省',
|
|
||||||
province: '青海省',
|
|
||||||
nnh: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 29.0,
|
|
||||||
color1: 'orange',
|
|
||||||
province_adcode: '640000',
|
|
||||||
province_adName: '宁夏回族自治区',
|
|
||||||
province: '宁夏回族自治区',
|
|
||||||
nnh: 3,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 60.0,
|
|
||||||
color1: 'orange',
|
|
||||||
province_adcode: '650000',
|
|
||||||
province_adName: '新疆维吾尔自治区',
|
|
||||||
province: '新疆维吾尔自治区',
|
|
||||||
nnh: 4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: -31.0,
|
|
||||||
color1: 'orange',
|
|
||||||
province_adcode: '710000',
|
|
||||||
province_adName: '台湾省',
|
|
||||||
province: '台湾省',
|
|
||||||
nnh: 4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 80.0,
|
|
||||||
color1: 'orange',
|
|
||||||
province_adcode: '810000',
|
|
||||||
province_adName: '香港特别行政区',
|
|
||||||
province: '香港特别行政区',
|
|
||||||
nnh: 4,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: -33.0,
|
|
||||||
color1: 'orange',
|
|
||||||
province_adcode: '820000',
|
|
||||||
province_adName: '澳门特别行政区',
|
|
||||||
province: '澳门特别行政区',
|
|
||||||
nnh: 4,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
|
@ -83,18 +32,10 @@ export default () => {
|
||||||
maxZoom: 9,
|
maxZoom: 9,
|
||||||
extent: [-180, -85.051129, 179, 85.051129],
|
extent: [-180, -85.051129, 179, 85.051129],
|
||||||
},
|
},
|
||||||
transforms: [
|
|
||||||
{
|
|
||||||
type: 'join',
|
|
||||||
sourceField: 'nnh',
|
|
||||||
targetField: 'NNH', // data 对应字段名 绑定到的地理数据
|
|
||||||
data: list,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.shape('simple')
|
.shape('simple')
|
||||||
// .shape('line')
|
|
||||||
.color('COLOR')
|
.color('COLOR')
|
||||||
.size(2)
|
.size(2)
|
||||||
.select(true);
|
.select(true);
|
||||||
|
|
|
@ -73,6 +73,7 @@ export interface ISource {
|
||||||
updateClusterData(zoom: number): void;
|
updateClusterData(zoom: number): void;
|
||||||
getFeatureById(id: number): unknown;
|
getFeatureById(id: number): unknown;
|
||||||
getFeatureId(field: string, value: any): number | undefined;
|
getFeatureId(field: string, value: any): number | undefined;
|
||||||
|
getParserType(): string;
|
||||||
getClusters(zoom: number): any;
|
getClusters(zoom: number): any;
|
||||||
getClustersLeaves(id: number): any;
|
getClustersLeaves(id: number): any;
|
||||||
updateFeaturePropertiesById(
|
updateFeaturePropertiesById(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import BaseLayer from '../core/BaseLayer';
|
import BaseLayer from '../core/BaseLayer';
|
||||||
import { ILineLayerStyleOptions } from '../core/interface';
|
import { ILineLayerStyleOptions } from '../core/interface';
|
||||||
import LineModels, { LineModelType } from './models';
|
import LineModels, { LineModelType } from './models';
|
||||||
|
import { isVectorTile } from '../tile/utils';
|
||||||
|
|
||||||
export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
|
export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
|
||||||
public type: string = 'LineLayer';
|
public type: string = 'LineLayer';
|
||||||
|
@ -49,9 +50,11 @@ export default class LineLayer extends BaseLayer<ILineLayerStyleOptions> {
|
||||||
if (this.layerType) {
|
if (this.layerType) {
|
||||||
return this.layerType as LineModelType;
|
return this.layerType as LineModelType;
|
||||||
}
|
}
|
||||||
if (this.layerSource.parser.type === 'mvt') {
|
const parserType = this.layerSource.getParserType();
|
||||||
|
if (isVectorTile(parserType)) {
|
||||||
return 'vectorline';
|
return 'vectorline';
|
||||||
}
|
}
|
||||||
|
|
||||||
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
|
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
|
||||||
'shape',
|
'shape',
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { IEncodeFeature } from '@antv/l7-core';
|
||||||
import BaseLayer from '../core/BaseLayer';
|
import BaseLayer from '../core/BaseLayer';
|
||||||
import { IPointLayerStyleOptions } from '../core/interface';
|
import { IPointLayerStyleOptions } from '../core/interface';
|
||||||
import PointModels, { PointType } from './models/index';
|
import PointModels, { PointType } from './models/index';
|
||||||
|
import { isVectorTile } from '../tile/utils';
|
||||||
|
|
||||||
export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
||||||
public type: string = 'PointLayer';
|
public type: string = 'PointLayer';
|
||||||
|
@ -92,7 +93,8 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
||||||
'earthFill',
|
'earthFill',
|
||||||
'earthExtrude',
|
'earthExtrude',
|
||||||
];
|
];
|
||||||
if (this.layerSource.parser.type === 'mvt') {
|
const parserType = this.layerSource.getParserType();
|
||||||
|
if (isVectorTile(parserType)) {
|
||||||
return 'vectorpoint';
|
return 'vectorpoint';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { IEncodeFeature } from '@antv/l7-core';
|
||||||
import BaseLayer from '../core/BaseLayer';
|
import BaseLayer from '../core/BaseLayer';
|
||||||
import { IPolygonLayerStyleOptions } from '../core/interface';
|
import { IPolygonLayerStyleOptions } from '../core/interface';
|
||||||
import PolygonModels, { PolygonModelType } from './models/';
|
import PolygonModels, { PolygonModelType } from './models/';
|
||||||
|
import { isVectorTile } from '../tile/utils';
|
||||||
|
|
||||||
export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
|
export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
|
||||||
public type: string = 'PolygonLayer';
|
public type: string = 'PolygonLayer';
|
||||||
|
@ -29,9 +30,11 @@ export default class PolygonLayer extends BaseLayer<IPolygonLayerStyleOptions> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getModelType(): PolygonModelType {
|
protected getModelType(): PolygonModelType {
|
||||||
if (this.layerSource.parser.type === 'mvt') {
|
const parserType = this.layerSource.getParserType();
|
||||||
|
if (isVectorTile(parserType)) {
|
||||||
return 'vectorpolygon';
|
return 'vectorpolygon';
|
||||||
}
|
}
|
||||||
|
|
||||||
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
|
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
|
||||||
'shape',
|
'shape',
|
||||||
);
|
);
|
||||||
|
|
|
@ -37,7 +37,8 @@ export default class RaterLayer extends BaseLayer<IRasterLayerStyleOptions> {
|
||||||
|
|
||||||
protected getModelType(): RasterModelType {
|
protected getModelType(): RasterModelType {
|
||||||
// 根据 source 的类型判断 model type
|
// 根据 source 的类型判断 model type
|
||||||
switch (this.layerSource.parser.type) {
|
const parserType = this.layerSource.getParserType();
|
||||||
|
switch (parserType) {
|
||||||
case 'raster':
|
case 'raster':
|
||||||
return 'raster';
|
return 'raster';
|
||||||
case 'rasterTile':
|
case 'rasterTile':
|
||||||
|
|
|
@ -175,6 +175,7 @@ export class TileLayerManager implements ITileLayerManager {
|
||||||
);
|
);
|
||||||
const source = this.parent.getSource();
|
const source = this.parent.getSource();
|
||||||
const { coords } = source?.data?.tilesetOptions || {};
|
const { coords } = source?.data?.tilesetOptions || {};
|
||||||
|
const parentParserType = source.getParserType();
|
||||||
|
|
||||||
const layerShape = getLayerShape(this.parent.type, this.parent);
|
const layerShape = getLayerShape(this.parent.type, this.parent);
|
||||||
|
|
||||||
|
@ -189,7 +190,7 @@ export class TileLayerManager implements ITileLayerManager {
|
||||||
shape: layerShape,
|
shape: layerShape,
|
||||||
zIndex,
|
zIndex,
|
||||||
opacity,
|
opacity,
|
||||||
sourceLayer,
|
sourceLayer: parentParserType === 'geojsonvt' ? 'geojsonvt' : sourceLayer,
|
||||||
coords,
|
coords,
|
||||||
featureId,
|
featureId,
|
||||||
color: colorValue,
|
color: colorValue,
|
||||||
|
|
|
@ -6,6 +6,13 @@ import {
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { DOM, Tile } from '@antv/l7-utils';
|
import { DOM, Tile } from '@antv/l7-utils';
|
||||||
import { Container } from 'inversify';
|
import { Container } from 'inversify';
|
||||||
|
|
||||||
|
export const tileVectorParser = ['mvt', 'geojsonvt'];
|
||||||
|
|
||||||
|
export function isVectorTile(parserType: string) {
|
||||||
|
return tileVectorParser.indexOf(parserType) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
export function registerLayers(parentLayer: ILayer, layers: ILayer[]) {
|
export function registerLayers(parentLayer: ILayer, layers: ILayer[]) {
|
||||||
layers.map((layer) => {
|
layers.map((layer) => {
|
||||||
const container = createLayerContainer(
|
const container = createLayerContainer(
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
"@babel/runtime": "^7.7.7",
|
"@babel/runtime": "^7.7.7",
|
||||||
"@mapbox/geojson-rewind": "^0.5.2",
|
"@mapbox/geojson-rewind": "^0.5.2",
|
||||||
"@mapbox/vector-tile": "^1.3.1",
|
"@mapbox/vector-tile": "^1.3.1",
|
||||||
|
"geojson-vt": "^3.2.1",
|
||||||
"@turf/helpers": "^6.1.4",
|
"@turf/helpers": "^6.1.4",
|
||||||
"@turf/invariant": "^6.1.2",
|
"@turf/invariant": "^6.1.2",
|
||||||
"@turf/meta": "^6.0.2",
|
"@turf/meta": "^6.0.2",
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
"supercluster": "^7.0.0"
|
"supercluster": "^7.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/geojson-vt": "3.2.0",
|
||||||
"@types/d3-dsv": "^1.0.36",
|
"@types/d3-dsv": "^1.0.36",
|
||||||
"@types/d3-hexbin": "^0.2.3",
|
"@types/d3-hexbin": "^0.2.3",
|
||||||
"@types/lodash": "^4.14.138",
|
"@types/lodash": "^4.14.138",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import geojson from './parser/geojson';
|
||||||
import image from './parser/image';
|
import image from './parser/image';
|
||||||
import json, { defaultData, defaultParser, defaultSource } from './parser/json';
|
import json, { defaultData, defaultParser, defaultSource } from './parser/json';
|
||||||
import mapboxVectorTile from './parser/mvt';
|
import mapboxVectorTile from './parser/mvt';
|
||||||
|
import geojsonVTTile from './parser/geojsonvt';
|
||||||
import raster from './parser/raster';
|
import raster from './parser/raster';
|
||||||
import rasterTile from './parser/raster-tile';
|
import rasterTile from './parser/raster-tile';
|
||||||
import Source from './source';
|
import Source from './source';
|
||||||
|
@ -16,6 +17,7 @@ import { map } from './transform/map';
|
||||||
|
|
||||||
registerParser('rasterTile', rasterTile);
|
registerParser('rasterTile', rasterTile);
|
||||||
registerParser('mvt', mapboxVectorTile);
|
registerParser('mvt', mapboxVectorTile);
|
||||||
|
registerParser('geojsonvt', geojsonVTTile);
|
||||||
registerParser('geojson', geojson);
|
registerParser('geojson', geojson);
|
||||||
registerParser('image', image);
|
registerParser('image', image);
|
||||||
registerParser('csv', csv);
|
registerParser('csv', csv);
|
||||||
|
|
|
@ -27,7 +27,20 @@ export enum RasterTileType {
|
||||||
IMAGE = 'image',
|
IMAGE = 'image',
|
||||||
ARRAYBUFFER = 'arraybuffer',
|
ARRAYBUFFER = 'arraybuffer',
|
||||||
}
|
}
|
||||||
export interface IRasterTileParserCFG {
|
|
||||||
|
export interface IGeojsonvtOptions {
|
||||||
|
maxZoom: number; // max zoom to preserve detail on
|
||||||
|
indexMaxZoom: number; // max zoom in the tile index
|
||||||
|
indexMaxPoints: number; // max number of points per tile in the tile index
|
||||||
|
tolerance: number; // simplification tolerance (higher means simpler)
|
||||||
|
extent: number; // tile extent
|
||||||
|
buffer: number; // tile buffer on each side
|
||||||
|
lineMetrics: boolean; // whether to calculate line metrics
|
||||||
|
promoteId: null; // name of a feature property to be promoted to feature.id
|
||||||
|
generateId: boolean; // whether to generate feature ids. Cannot be used with promoteId
|
||||||
|
debug: number; // logging level (0, 1 or 2)
|
||||||
|
}
|
||||||
|
export interface ITileParserCFG {
|
||||||
tileSize?: number;
|
tileSize?: number;
|
||||||
minZoom?: number;
|
minZoom?: number;
|
||||||
maxZoom?: number;
|
maxZoom?: number;
|
||||||
|
@ -42,6 +55,8 @@ export interface IRasterTileParserCFG {
|
||||||
// 指定栅格瓦片的类型
|
// 指定栅格瓦片的类型
|
||||||
dataType?: RasterTileType;
|
dataType?: RasterTileType;
|
||||||
|
|
||||||
|
geojsonvtOptions?: IGeojsonvtOptions;
|
||||||
|
|
||||||
format?: any;
|
format?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,259 @@
|
||||||
|
import { Tile, TileLoadParams, TilesetManagerOptions } from '@antv/l7-utils';
|
||||||
|
import {
|
||||||
|
Feature,
|
||||||
|
FeatureCollection,
|
||||||
|
Geometries,
|
||||||
|
Properties,
|
||||||
|
} from '@turf/helpers';
|
||||||
|
import geojsonvt from 'geojson-vt';
|
||||||
|
import { VectorTileLayer } from '@mapbox/vector-tile';
|
||||||
|
import { IParserData, ITileParserCFG, IGeojsonvtOptions } from '../interface';
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG: Partial<TilesetManagerOptions> = {
|
||||||
|
tileSize: 256,
|
||||||
|
minZoom: 0,
|
||||||
|
maxZoom: Infinity,
|
||||||
|
zoomOffset: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
function signedArea(ring: any[]) {
|
||||||
|
let sum = 0;
|
||||||
|
for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
|
||||||
|
p1 = ring[i];
|
||||||
|
p2 = ring[j];
|
||||||
|
sum += (p2.x - p1.x) * (p1.y + p2.y);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
function classifyRings(rings: any[]) {
|
||||||
|
const len = rings.length;
|
||||||
|
|
||||||
|
if (len <= 1) {
|
||||||
|
return [rings];
|
||||||
|
}
|
||||||
|
|
||||||
|
const polygons: any = [];
|
||||||
|
let polygon: any;
|
||||||
|
let ccw;
|
||||||
|
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
const area = signedArea(rings[i]);
|
||||||
|
if (area === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ccw === undefined) {
|
||||||
|
ccw = area < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ccw === area < 0) {
|
||||||
|
if (polygon) {
|
||||||
|
polygons.push(polygon);
|
||||||
|
}
|
||||||
|
polygon = [rings[i]];
|
||||||
|
} else {
|
||||||
|
polygon.push(rings[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (polygon) {
|
||||||
|
polygons.push(polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
return polygons;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VectorTileFeatureTypes = ['Unknown', 'Point', 'LineString', 'Polygon'];
|
||||||
|
|
||||||
|
function GetGeoJSON(
|
||||||
|
extent: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
z: number,
|
||||||
|
vectorTileFeature: any,
|
||||||
|
) {
|
||||||
|
let coords = vectorTileFeature.geometry as any;
|
||||||
|
const currenType = vectorTileFeature.type;
|
||||||
|
|
||||||
|
const currentProperties = vectorTileFeature.tags;
|
||||||
|
const currentId = vectorTileFeature.id;
|
||||||
|
|
||||||
|
const size = extent * Math.pow(2, z);
|
||||||
|
const x0 = extent * x;
|
||||||
|
const y0 = extent * y;
|
||||||
|
|
||||||
|
let type = VectorTileFeatureTypes[currenType];
|
||||||
|
let i;
|
||||||
|
let j;
|
||||||
|
|
||||||
|
function project(line: any[]) {
|
||||||
|
for (let j = 0; j < line.length; j++) {
|
||||||
|
const p = line[j];
|
||||||
|
if (p[3]) {
|
||||||
|
// 避免重复计算
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const y2 = 180 - ((p[1] + y0) * 360) / size;
|
||||||
|
const lng = ((p[0] + x0) * 360) / size - 180;
|
||||||
|
const lat =
|
||||||
|
(360 / Math.PI) * Math.atan(Math.exp((y2 * Math.PI) / 180)) - 90;
|
||||||
|
line[j] = [lng, lat, 0, 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (currenType) {
|
||||||
|
case 1:
|
||||||
|
const points = [];
|
||||||
|
for (i = 0; i < coords.length; i++) {
|
||||||
|
points[i] = coords[i][0];
|
||||||
|
}
|
||||||
|
coords = points;
|
||||||
|
project(coords);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
for (i = 0; i < coords.length; i++) {
|
||||||
|
project(coords[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
coords = classifyRings(coords);
|
||||||
|
for (i = 0; i < coords.length; i++) {
|
||||||
|
for (j = 0; j < coords[i].length; j++) {
|
||||||
|
project(coords[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coords.length === 1) {
|
||||||
|
coords = coords[0];
|
||||||
|
} else {
|
||||||
|
type = 'Multi' + type;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
type: 'Feature',
|
||||||
|
geometry: {
|
||||||
|
type,
|
||||||
|
coordinates: coords,
|
||||||
|
},
|
||||||
|
properties: currentProperties,
|
||||||
|
id: currentId,
|
||||||
|
tileOrigin: [0, 0],
|
||||||
|
coord: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MapboxVectorTile = {
|
||||||
|
layers: { [_: string]: VectorTileLayer & { features: Feature[] } };
|
||||||
|
};
|
||||||
|
|
||||||
|
const getVectorTile = async (
|
||||||
|
tile: Tile,
|
||||||
|
tileIndex: any,
|
||||||
|
tileParams: TileLoadParams,
|
||||||
|
extent: number,
|
||||||
|
): Promise<MapboxVectorTile> => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const tileData = tileIndex.getTile(tile.z, tile.x, tile.y);
|
||||||
|
// tileData
|
||||||
|
const features: any = [];
|
||||||
|
tileData.features.map((vectorTileFeature: any) => {
|
||||||
|
const feature = GetGeoJSON(
|
||||||
|
extent,
|
||||||
|
tileParams.x,
|
||||||
|
tileParams.y,
|
||||||
|
tileParams.z,
|
||||||
|
vectorTileFeature,
|
||||||
|
);
|
||||||
|
features.push(feature);
|
||||||
|
});
|
||||||
|
|
||||||
|
const vectorTile = {
|
||||||
|
layers: {
|
||||||
|
// Tip: fixed SourceLayer Name
|
||||||
|
geojsonvt: {
|
||||||
|
features,
|
||||||
|
} as VectorTileLayer & {
|
||||||
|
features: Feature[];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as MapboxVectorTile;
|
||||||
|
|
||||||
|
resolve(vectorTile);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function getGeoJSONVTOptions(cfg?: ITileParserCFG) {
|
||||||
|
const defaultOptions = {
|
||||||
|
// geojson-vt default options
|
||||||
|
maxZoom: 14, // max zoom to preserve detail on
|
||||||
|
indexMaxZoom: 5, // max zoom in the tile index
|
||||||
|
indexMaxPoints: 100000, // max number of points per tile in the tile index
|
||||||
|
tolerance: 3, // simplification tolerance (higher means simpler)
|
||||||
|
extent: 4096, // tile extent
|
||||||
|
buffer: 64, // tile buffer on each side
|
||||||
|
lineMetrics: false, // whether to calculate line metrics
|
||||||
|
promoteId: null, // name of a feature property to be promoted to feature.id
|
||||||
|
generateId: true, // whether to generate feature ids. Cannot be used with promoteId
|
||||||
|
debug: 0, // logging level (0, 1 or 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cfg === undefined || typeof cfg.geojsonvtOptions === 'undefined') {
|
||||||
|
return defaultOptions;
|
||||||
|
} else {
|
||||||
|
cfg.geojsonvtOptions.maxZoom &&
|
||||||
|
(defaultOptions.maxZoom = cfg.geojsonvtOptions.maxZoom);
|
||||||
|
cfg.geojsonvtOptions.indexMaxZoom &&
|
||||||
|
(defaultOptions.indexMaxZoom = cfg.geojsonvtOptions.indexMaxZoom);
|
||||||
|
cfg.geojsonvtOptions.indexMaxPoints &&
|
||||||
|
(defaultOptions.indexMaxPoints = cfg.geojsonvtOptions.indexMaxPoints);
|
||||||
|
cfg.geojsonvtOptions.tolerance &&
|
||||||
|
(defaultOptions.tolerance = cfg.geojsonvtOptions.tolerance);
|
||||||
|
cfg.geojsonvtOptions.extent &&
|
||||||
|
(defaultOptions.extent = cfg.geojsonvtOptions.extent);
|
||||||
|
cfg.geojsonvtOptions.buffer &&
|
||||||
|
(defaultOptions.buffer = cfg.geojsonvtOptions.buffer);
|
||||||
|
cfg.geojsonvtOptions.lineMetrics &&
|
||||||
|
(defaultOptions.lineMetrics = cfg.geojsonvtOptions.lineMetrics);
|
||||||
|
cfg.geojsonvtOptions.promoteId &&
|
||||||
|
(defaultOptions.promoteId = cfg.geojsonvtOptions.promoteId);
|
||||||
|
cfg.geojsonvtOptions.generateId &&
|
||||||
|
(defaultOptions.generateId = cfg.geojsonvtOptions.generateId);
|
||||||
|
cfg.geojsonvtOptions.debug &&
|
||||||
|
(defaultOptions.debug = cfg.geojsonvtOptions.debug);
|
||||||
|
return defaultOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function geojsonVTTile(
|
||||||
|
data: FeatureCollection<Geometries, Properties>,
|
||||||
|
cfg: ITileParserCFG,
|
||||||
|
): IParserData {
|
||||||
|
const geojsonOptions = getGeoJSONVTOptions(cfg) as geojsonvt.Options &
|
||||||
|
IGeojsonvtOptions;
|
||||||
|
|
||||||
|
const extent = geojsonOptions.extent || 4096;
|
||||||
|
const tileIndex = geojsonvt(data, geojsonOptions);
|
||||||
|
|
||||||
|
const getTileData = (tileParams: TileLoadParams, tile: Tile) => {
|
||||||
|
return getVectorTile(tile, tileIndex, tileParams, extent);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tilesetOptions = {
|
||||||
|
...DEFAULT_CONFIG,
|
||||||
|
...cfg,
|
||||||
|
getTileData,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
dataArray: [],
|
||||||
|
tilesetOptions,
|
||||||
|
isTile: true,
|
||||||
|
};
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import {
|
||||||
} from '@mapbox/vector-tile';
|
} from '@mapbox/vector-tile';
|
||||||
import { Feature } from '@turf/helpers';
|
import { Feature } from '@turf/helpers';
|
||||||
import Protobuf from 'pbf';
|
import Protobuf from 'pbf';
|
||||||
import { IParserData, IRasterTileParserCFG } from '../interface';
|
import { IParserData, ITileParserCFG } from '../interface';
|
||||||
|
|
||||||
const DEFAULT_CONFIG: Partial<TilesetManagerOptions> = {
|
const DEFAULT_CONFIG: Partial<TilesetManagerOptions> = {
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
|
@ -214,7 +214,7 @@ const getVectorTile = async (
|
||||||
|
|
||||||
export default function mapboxVectorTile(
|
export default function mapboxVectorTile(
|
||||||
data: string | string[],
|
data: string | string[],
|
||||||
cfg?: IRasterTileParserCFG,
|
cfg?: ITileParserCFG,
|
||||||
): IParserData {
|
): IParserData {
|
||||||
const coord = cfg?.coord || 'lnglat'; // lnglat - offset
|
const coord = cfg?.coord || 'lnglat'; // lnglat - offset
|
||||||
const getTileData = (tileParams: TileLoadParams, tile: Tile) =>
|
const getTileData = (tileParams: TileLoadParams, tile: Tile) =>
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
import { Tile, TileLoadParams, TilesetManagerOptions } from '@antv/l7-utils';
|
import { Tile, TileLoadParams, TilesetManagerOptions } from '@antv/l7-utils';
|
||||||
import {
|
import { IParserData, ITileParserCFG, RasterTileType } from '../interface';
|
||||||
IParserData,
|
|
||||||
IRasterTileParserCFG,
|
|
||||||
RasterTileType,
|
|
||||||
} from '../interface';
|
|
||||||
import { defaultFormat, getTileBuffer, getTileImage } from '../utils/getTile';
|
import { defaultFormat, getTileBuffer, getTileImage } from '../utils/getTile';
|
||||||
|
|
||||||
const DEFAULT_CONFIG: Partial<TilesetManagerOptions> = {
|
const DEFAULT_CONFIG: Partial<TilesetManagerOptions> = {
|
||||||
|
@ -15,7 +11,7 @@ const DEFAULT_CONFIG: Partial<TilesetManagerOptions> = {
|
||||||
|
|
||||||
export default function rasterTile(
|
export default function rasterTile(
|
||||||
data: string | string[],
|
data: string | string[],
|
||||||
cfg?: IRasterTileParserCFG,
|
cfg?: ITileParserCFG,
|
||||||
): IParserData {
|
): IParserData {
|
||||||
const tileDataType: RasterTileType = cfg?.dataType || RasterTileType.IMAGE;
|
const tileDataType: RasterTileType = cfg?.dataType || RasterTileType.IMAGE;
|
||||||
const getTileData = (tileParams: TileLoadParams, tile: Tile) => {
|
const getTileData = (tileParams: TileLoadParams, tile: Tile) => {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import { SyncHook } from '@antv/async-hook';
|
import { SyncHook } from '@antv/async-hook';
|
||||||
import {
|
import {
|
||||||
IClusterOptions,
|
IClusterOptions,
|
||||||
IMapService,
|
|
||||||
IParseDataItem,
|
IParseDataItem,
|
||||||
IParserCfg,
|
IParserCfg,
|
||||||
IParserData,
|
IParserData,
|
||||||
|
@ -57,7 +56,6 @@ export default class Source extends EventEmitter implements ISource {
|
||||||
|
|
||||||
// 瓦片数据管理器
|
// 瓦片数据管理器
|
||||||
public tileset: TilesetManager | undefined;
|
public tileset: TilesetManager | undefined;
|
||||||
private readonly mapService: IMapService;
|
|
||||||
// 是否有效范围
|
// 是否有效范围
|
||||||
private invalidExtent: boolean = false;
|
private invalidExtent: boolean = false;
|
||||||
|
|
||||||
|
@ -87,6 +85,10 @@ export default class Source extends EventEmitter implements ISource {
|
||||||
return this.clusterIndex.getLeaves(id, Infinity);
|
return this.clusterIndex.getLeaves(id, Infinity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getParserType() {
|
||||||
|
return this.parser.type;
|
||||||
|
}
|
||||||
|
|
||||||
public updateClusterData(zoom: number): void {
|
public updateClusterData(zoom: number): void {
|
||||||
const { method = 'sum', field } = this.clusterOptions;
|
const { method = 'sum', field } = this.clusterOptions;
|
||||||
let data = this.clusterIndex.getClusters(
|
let data = this.clusterIndex.getClusters(
|
||||||
|
|
Loading…
Reference in New Issue