feat: support simple line vector layer (#1295)

* feat: 矢量图层支持 join/transfrom 透传

* style: lint style

* feat: support simple line vector tile layer

Co-authored-by: shihui <yiqianyao.yqy@alibaba-inc.com>
This commit is contained in:
YiQianYao 2022-08-18 10:30:20 +08:00 committed by GitHub
parent 340fd77729
commit 02ac2ab4a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 332 additions and 44 deletions

View File

@ -6,6 +6,7 @@ import {
// @ts-ignore
import { GaodeMap } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { polygonToLineString, MultiPolygon } from '@turf/turf';
function getImageData(img: HTMLImageElement) {
const canvas: HTMLCanvasElement = document.createElement('canvas');
@ -80,52 +81,179 @@ export default () => {
const scene = new Scene({
id: 'map',
map: new GaodeMap({
center: [121.268, 30.3628],
// center: [121.268, 30.3628],
// center: [115.565185546875,41.31082388091818],
center: [112.796630859375, 21.80030805097259],
pitch: 0,
// style: 'blank',
zoom: 3,
// zoom: 3,
zoom: 10,
}),
});
const layer = new LineLayer()
.source({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'MultiLineString',
coordinates: [
[
[80, 30, 5000],
[150, 30, 5000],
[150, 10, 5000],
],
[
[120, 50, 5000],
[120, 30, 5000],
],
const testdata = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'MultiLineString',
coordinates: [
[
[115.565185546875, 41.31082388091818],
[115.3948974609375, 41.203456192051306],
[115.1751708984375, 40.979898069620134],
[115.0982666015625, 40.90105786688403],
[114.697265625, 40.701463603604594],
[114.89501953125, 40.50126945841643],
[114.9993896484375, 40.50126945841643],
[115.0982666015625, 40.400947631519614],
[114.9993896484375, 40.3004760797495],
[114.697265625, 40.20405042511331],
[114.697265625, 40.3004760797495],
[114.3951416015625, 40.20405042511331],
[114.1973876953125, 40.20405042511331],
[114.0985107421875, 40.00237193587648],
[113.9996337890625, 39.90130858574736],
[113.697509765625, 39.80009595634837],
[113.2965087890625, 39.90130858574736],
[113.0987548828125, 39.80009595634837],
[112.9998779296875, 39.70296052957232],
[112.69775390625, 39.202462225882385],
[112.598876953125, 39.202462225882385],
[112.5, 39.0533181067413],
[112.3956298828125, 38.90385833966778],
[112.1978759765625, 38.70265930723801],
[112.060546875, 38.77121637244272],
[112.060546875, 40.061256581404734],
[112.1978759765625, 40.20405042511331],
[112.060546875, 40.20405042511331],
[112.060546875, 41.31082388091818],
[115.565185546875, 41.31082388091818],
],
},
],
},
{
type: 'Feature',
properties: {},
geometry: {
type: 'MultiLineString',
coordinates: [
[
[100, 35, 100],
[120, 50, 100],
[120, 20, 100],
[130, 20, 100],
],
],
},
properties: {
ECO_NAME: 'Mongolian-Manchurian grassland',
BIOME_NAME: 'Temperate Grasslands, Savannas & Shrublands',
REALM: 'Palearctic',
NNH: 3,
NNH_NAME: 'Nature Could Recover',
COLOR: '#F6FC38',
COLOR_BIO: '#FEFF73',
COLOR_NNH: '#F9A91B',
},
},
],
};
const multipolygon = {
type: 'Feature',
geometry: {
type: 'MultiPolygon',
coordinates: [
[
[
[112.796630859375, 21.80030805097259],
[112.796630859375, 21.601258036965902],
[112.69775390625, 21.70336934552425],
[112.796630859375, 21.80030805097259],
],
],
[
[
[113.5491943359375, 22.350075806124863],
[113.5986328125, 22.304343762932234],
[113.499755859375, 22.2026634080092],
[113.2965087890625, 22.2026634080092],
[113.1976318359375, 22.004174972902007],
[113.0987548828125, 22.10090935057272],
[112.9998779296875, 22.10090935057272],
[112.9998779296875, 21.902277966668635],
[112.8955078125, 21.902277966668635],
[112.8515625, 21.94304553343818],
[112.796630859375, 22.004174972902007],
[112.74169921875, 21.94304553343818],
[112.598876953125, 21.80030805097259],
[112.3956298828125, 21.80030805097259],
[112.3956298828125, 21.70336934552425],
[112.2967529296875, 21.70336934552425],
[112.1978759765625, 21.80030805097259],
[112.060546875, 21.80030805097259],
[112.060546875, 22.350075806124863],
[113.5491943359375, 22.350075806124863],
],
],
[
[
[114.2962646484375, 22.350075806124863],
[114.1973876953125, 22.304343762932234],
[114.049072265625, 22.350075806124863],
[114.2962646484375, 22.350075806124863],
],
],
],
})
},
properties: {
ECO_NAME: 'Mongolian-Manchurian grassland',
BIOME_NAME: 'Temperate Grasslands, Savannas & Shrublands',
REALM: 'Palearctic',
NNH: 3,
NNH_NAME: 'Nature Could Recover',
COLOR: '#F6FC38',
COLOR_BIO: '#FEFF73',
COLOR_NNH: '#F9A91B',
},
};
const testdata2 = {
type: 'FeatureCollection',
features: [],
};
console.log(polygonToLineString((multipolygon as unknown) as MultiPolygon));
const layer = new LineLayer()
// .source({
// type: 'FeatureCollection',
// features: [
// {
// type: 'Feature',
// properties: {},
// geometry: {
// type: 'MultiLineString',
// coordinates: [
// [
// [80, 30, 5000],
// [150, 30, 5000],
// [150, 10, 5000],
// ],
// [
// [120, 50, 5000],
// [120, 30, 5000],
// ],
// ],
// },
// },
// {
// type: 'Feature',
// properties: {},
// geometry: {
// type: 'MultiLineString',
// coordinates: [
// [
// [100, 35, 100],
// [120, 50, 100],
// [120, 20, 100],
// [130, 20, 100],
// ],
// ],
// },
// },
// ],
// })
// @ts-ignore
// .source(polygonToLine(testdata2))
// .source(testdata)
.source(polygonToLineString((multipolygon as unknown) as MultiPolygon))
// .source([
// {
// lng1: 120,
@ -145,9 +273,9 @@ export default () => {
.shape('simple')
.color('#f00')
.style({
vertexHeightScale: 2000,
sourceColor: '#f00',
targetColor: '#0f0',
// vertexHeightScale: 2000,
// sourceColor: '#f00',
// targetColor: '#0f0',
});
scene.on('loaded', () => {

View File

@ -0,0 +1,2 @@
### Vector Point Tile
<code src="./vectorPointTile.tsx"></code>

View File

@ -0,0 +1,118 @@
// @ts-ignore
import { Scene, PointLayer } from '@antv/l7';
// @ts-ignore
import { Mapbox } from '@antv/l7-maps';
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 () => {
useEffect(() => {
const scene = new Scene({
id: 'map',
stencil: true,
map: new Mapbox({
center: [121.268, 30.3628],
pitch: 0,
style: 'blank',
zoom: 4,
}),
});
const layer = new PointLayer({
featureId: 'COLOR',
sourceLayer: 'ecoregions2', // woods hillshade contour ecoregions ecoregions2 city
});
layer
.source(
'http://ganos.oss-cn-hangzhou.aliyuncs.com/m2/rs_l7/{z}/{x}/{y}.pbf',
{
parser: {
type: 'mvt',
tileSize: 256,
zoomOffset: 0,
maxZoom: 9,
extent: [-180, -85.051129, 179, 85.051129],
},
transforms: [
{
type: 'join',
sourceField: 'nnh',
targetField: 'NNH', // data 对应字段名 绑定到的地理数据
data: list,
},
],
},
)
// .shape('simple')
// .shape('line')
.color('COLOR')
.size(10)
.select(true);
scene.on('loaded', () => {
scene.addLayer(layer);
layer.on('click', (e) => {
console.log(e);
});
});
}, []);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -93,6 +93,8 @@ export default () => {
],
},
)
.shape('simple')
// .shape('line')
.color('COLOR')
.size(2)
.select(true);

View File

@ -34,6 +34,7 @@
"@babel/runtime": "^7.7.7",
"@mapbox/martini": "^0.2.0",
"@turf/helpers": "^6.1.4",
"@turf/polygon-to-line": "^6.5.0",
"@turf/meta": "^6.0.2",
"@turf/union": "^6.5.0",
"d3-array": "1",

View File

@ -19,6 +19,7 @@ import VectorLayer from './vectorLayer';
import * as turf from '@turf/helpers';
import union from '@turf/union';
import polygonToLineString from '@turf/polygon-to-line';
import {
CacheEvent,
ILayerTileConfig,
@ -69,7 +70,7 @@ export default class TileFactory implements ITileFactory {
vectorTileLayer: null,
source: null,
};
const { sourceLayer, featureId, transforms } = initOptions;
const { sourceLayer, featureId, transforms, layerType, shape } = initOptions;
if (!sourceLayer) {
return emptyData;
}
@ -78,10 +79,28 @@ export default class TileFactory implements ITileFactory {
if (!(Array.isArray(features) && features.length > 0)) {
return emptyData;
} else {
let geofeatures = [];
if(layerType === 'LineLayer' && shape === 'simple') {
features.map(feature => {
if(feature.geometry.type === 'MultiPolygon') {
// @ts-ignore
const linefeatures = polygonToLineString(feature).features
geofeatures.push(...linefeatures)
} else if(feature.geometry.type === 'Polygon') {
feature.geometry.type = 'MultiLineString'
geofeatures.push(feature);
} else {
geofeatures.push(feature);
}
})
} else {
geofeatures = features;
}
const source = new Source(
{
type: 'FeatureCollection',
features,
features: geofeatures,
},
{
parser: {
@ -93,7 +112,7 @@ export default class TileFactory implements ITileFactory {
);
return {
features,
features: geofeatures,
featureId,
vectorTileLayer,
source,

View File

@ -6,6 +6,8 @@ import {
IPolygonLayerStyleOptions,
} from '../../core/interface';
import lineFillModel from '../../line/models/tile';
import lineSimpleModel from '../../line/models/simpleLine';
import pointTextModel from '../../point/models/text';
import pointFillModel from '../../point/models/tile';
import polygonFillModel from '../../polygon/models/tile';
@ -46,7 +48,7 @@ export default class VectorLayer extends BaseLayer<
case 'PolygonLayer':
return polygonFillModel;
case 'LineLayer':
return lineFillModel;
return this.getLineModel();
case 'PointLayer':
return this.getPointModel();
default:
@ -54,6 +56,22 @@ export default class VectorLayer extends BaseLayer<
}
}
protected getLineModel() {
const shapeAttribute = this.styleAttributeService.getLayerStyleAttribute(
'shape',
);
const shape = shapeAttribute?.scale?.field;
switch(shape) {
case 'tileline':
case 'line':
return lineFillModel;
case 'simple':
return lineSimpleModel;
default:
return lineFillModel;
}
}
protected getPointModel() {
const layerData = this.getEncodedData();
const { shape2d } = this.getLayerConfig();