feat: 优化、修复点图层等面积点模式 (#1222)

* feat: 去处事件节流

* feat: 修复、优化等面积点存在的问题和可视化表现

* style: lint style

* style: lint style
This commit is contained in:
YiQianYao 2022-07-07 14:29:46 +08:00 committed by GitHub
parent 6dde6c9c7f
commit 107b6a38e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 71 deletions

View File

@ -91,6 +91,7 @@ export interface IMapService<RawMap = {}> {
setMapStatus(option: Partial<IStatusOptions>): void;
// coordinates methods
meterToCoord(center: number[], lnglat: number[]): number;
pixelToLngLat(pixel: Point): ILngLat;
lngLatToPixel(lnglat: Point): IPoint;
containerToLngLat(pixel: Point): ILngLat;
@ -170,6 +171,7 @@ export interface IEarthService<RawMap = {}> {
setMapStatus(option: Partial<IStatusOptions>): void;
// coordinates methods
meterToCoord(center: number[], lnglat: number[]): number;
pixelToLngLat(pixel: Point): ILngLat;
lngLatToPixel(lnglat: Point): IPoint;
containerToLngLat(pixel: Point): ILngLat;

View File

@ -9,7 +9,7 @@ import {
IModel,
IModelUniform,
} from '@antv/l7-core';
import { getCullFace, getMask } from '@antv/l7-utils';
import { $window, getCullFace, getMask } from '@antv/l7-utils';
import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel';
import { IPointLayerStyleOptions } from '../../core/interface';
@ -26,8 +26,11 @@ import pointFillVert from '../shaders/fill_vert.glsl';
import { Version } from '@antv/l7-maps';
import { mat4, vec3 } from 'gl-matrix';
export default class FillModel extends BaseModel {
public meter2coord: number = 1;
private meter2coord: number = 1;
private meteryScale: number = 1; // 兼容 mapbox
private isMeter: boolean = false;
private unit: string = 'l7size';
public getUninforms(): IModelUniform {
const {
opacity = 1,
@ -38,7 +41,9 @@ export default class FillModel extends BaseModel {
blend,
blur = 0,
raisingHeight = 0,
unit = 'l7size',
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
this.updateUnit(unit);
if (
this.dataTextureTest &&
@ -89,6 +94,8 @@ export default class FillModel extends BaseModel {
return {
u_raisingHeight: Number(raisingHeight),
u_meter2coord: this.meter2coord,
u_meteryScale: this.meteryScale,
u_isMeter: Number(this.isMeter),
u_blur: blur,
@ -129,18 +136,7 @@ export default class FillModel extends BaseModel {
}
public initModels(): IModel[] {
const {
unit = 'l7size',
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
const { version } = this.mapService;
if (
unit === 'meter' &&
version !== Version.L7MAP &&
version !== Version.GLOBEL
) {
this.isMeter = true;
this.calMeter2Coord();
}
this.updateUnit('l7size');
return this.buildModels();
}
@ -154,28 +150,36 @@ export default class FillModel extends BaseModel {
const center = [(minLng + maxLng) / 2, (minLat + maxLat) / 2];
const { version } = this.mapService;
if (version === Version.MAPBOX && window.mapboxgl.MercatorCoordinate) {
const coord = window.mapboxgl.MercatorCoordinate.fromLngLat(
const mapboxContext = $window?.mapboxgl;
if (version === Version.MAPBOX && mapboxContext?.MercatorCoordinate) {
// 参考:
// https://docs.mapbox.com/mapbox-gl-js/api/geography/#mercatorcoordinate#meterinmercatorcoordinateunits
const coord = mapboxContext.MercatorCoordinate.fromLngLat(
{ lng: center[0], lat: center[1] },
0,
);
const offsetInMeters = 1;
const offsetInMercatorCoordinateUnits =
offsetInMeters * coord.meterInMercatorCoordinateUnits();
const westCoord = new window.mapboxgl.MercatorCoordinate(
const offsetInMercatorCoordinateUnits = coord.meterInMercatorCoordinateUnits();
const westCoord = new mapboxContext.MercatorCoordinate(
coord.x - offsetInMercatorCoordinateUnits,
coord.y,
coord.z,
);
const westLnglat = westCoord.toLngLat();
const southCoord = new mapboxContext.MercatorCoordinate(
coord.x,
coord.y - offsetInMercatorCoordinateUnits,
coord.z,
);
const southLnglat = southCoord.toLngLat();
this.meter2coord = center[0] - westLnglat.lng;
this.meteryScale = (southLnglat.lat - center[1]) / this.meter2coord;
return;
}
// @ts-ignore
const m1 = this.mapService.meterToCoord(center, [minLng, minLat]);
// @ts-ignore
const m2 = this.mapService.meterToCoord(center, [
maxLng === minLng ? maxLng + 0.1 : maxLng,
maxLat === minLat ? minLat + 0.1 : maxLat,
@ -213,10 +217,6 @@ export default class FillModel extends BaseModel {
depth: { enable: isGlobel },
blend: this.getBlend(),
stencil: getMask(mask, maskInside),
cull: {
enable: true,
face: getCullFace(this.mapService.version),
},
}),
];
}
@ -350,10 +350,7 @@ export default class FillModel extends BaseModel {
attributeIdx: number,
) => {
const { size = 5 } = feature;
// console.log('featureIdx', featureIdx, feature)
return Array.isArray(size)
? [size[0] * this.meter2coord]
: [(size as number) * this.meter2coord];
return Array.isArray(size) ? [size[0]] : [size as number];
},
},
});
@ -385,4 +382,29 @@ export default class FillModel extends BaseModel {
},
});
}
/**
*
* @param unit
*/
private updateUnit(unit: string) {
const { version } = this.mapService;
if (this.unit !== unit) {
// l7size => meter
if (
this.unit !== 'meter' &&
unit === 'meter' &&
version !== Version.L7MAP &&
version !== Version.GLOBEL
) {
this.isMeter = true;
this.calMeter2Coord();
// meter => l7size
} else if (this.unit === 'meter' && unit !== 'meter') {
this.isMeter = false;
this.meter2coord = 1;
}
this.unit = unit;
}
}
}

View File

@ -9,6 +9,8 @@ varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样
uniform float u_globel;
uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp;
uniform float u_meter2coord;
uniform float u_meteryScale;
uniform float u_isMeter;
varying vec4 v_data;
@ -36,7 +38,12 @@ uniform float u_raisingHeight: 0.0;
void main() {
vec3 extrude = a_Extrude;
float shape_type = a_Shape;
float newSize = setPickingSize(a_Size);
/*
* setPickingSize 设置拾取大小
* u_meter2coord 在等面积大小的时候设置单位
*/
float newSize = setPickingSize(a_Size) * u_meter2coord;
// float newSize = setPickingSize(a_Size) * 0.00001038445708445579;
// cal style mapping - 数据纹理映射部分的计算
styleMappingMat = mat4(
@ -126,7 +133,7 @@ void main() {
// TODO: billboard
// anti-alias
// float antialiased_blur = -max(u_blur, antialiasblur);
float antialiasblur = -max(2.0 / u_DevicePixelRatio / a_Size, u_blur);
float antialiasblur = -max(2.0 / u_DevicePixelRatio / newSize, u_blur);
vec2 offset = (extrude.xy * (newSize + u_stroke_width) + textrueOffsets);
vec3 aPosition = a_Position;
@ -135,14 +142,18 @@ void main() {
offset = project_pixel(offset);
} else {
// 以米为实际单位
antialiasblur *= pow(19.0 - u_Zoom, 2.0);
antialiasblur = max(antialiasblur, -0.01);
// offset *= 0.5;
if(newSize * pow(2.0, u_Zoom) < 48.0) {
antialiasblur = max(antialiasblur, -0.05);
} else if(newSize * pow(2.0, u_Zoom) < 128.0) {
antialiasblur = max(antialiasblur, -0.6/pow(u_Zoom, 2.0));
} else {
antialiasblur = max(antialiasblur, -0.8/pow(u_Zoom, 2.0));
}
if(u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT || u_CoordinateSystem == COORDINATE_SYSTEM_LNGLAT_OFFSET) {
aPosition.xy += offset;
offset.x = 0.0;
offset.y = 0.0;
aPosition.x += offset.x / u_meteryScale;
aPosition.y += offset.y;
offset = vec2(0.0);
}
}

View File

@ -1,7 +1,7 @@
import { Map } from '@antv/l7-map';
import BaseMapWrapper from '../BaseMapWrapper';
import MapService from './map';
export default class MapboxWrapper extends BaseMapWrapper<Map> {
export default class EarthWrapper extends BaseMapWrapper<Map> {
protected getServiceConstructor() {
return MapService;
}

View File

@ -36,7 +36,7 @@ import { MapTheme } from './theme';
const LNGLAT_OFFSET_ZOOM_THRESHOLD = 12;
/**
* AMapService
* EarthService
*/
@injectable()
export default class L7EarthService implements IEarthService<Map> {
@ -231,6 +231,10 @@ export default class L7EarthService implements IEarthService<Map> {
return this.map.unproject(pixel);
}
public meterToCoord(center: [number, number], outer: [number, number]) {
return 1.0;
}
public lngLatToPixel(lnglat: [number, number]): IPoint {
return this.map.project(lnglat);
}

View File

@ -223,6 +223,11 @@ export default class L7MapService implements IMapService<Map> {
public setMapStyle(style: any): void {
this.map.setStyle(this.getMapStyle(style));
}
public meterToCoord(center: [number, number], outer: [number, number]) {
return 1.0;
}
// TODO: 计算像素坐标
public pixelToLngLat(pixel: [number, number]): ILngLat {
return this.map.unproject(pixel);

View File

@ -24,45 +24,46 @@ export default class Amap2demo extends React.Component {
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new GaodeMap({
pitch: 0,
style: 'blank',
// center: [115, 30],
map: new Mapbox({
// style: 'blank',
center: [120, 30],
zoom: 0,
// layers: [new window.AMap.TileLayer.Satellite()]
zoom: 15,
}),
});
this.scene = scene;
scene.on('loaded', () => {
const layer = new HeatmapLayer({})
.source([{ lng: 120, lat: 30, mag: 1 }], {
parser: { type: 'json', x: 'lng', y: 'lat' },
})
.shape('heatmap')
.size('mag', [0, 1.0]) // weight映射通道
.style({
intensity: 2,
radius: 20,
opacity: 1.0,
rampColors: {
colors: [
'#FF4818',
'#F7B74A',
'#FFF598',
'#F27DEB',
'#8C1EB2',
'#421EB2',
].reverse(),
positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0],
const layer = new PointLayer()
.source(
[
{
lng: 120,
lat: 30,
},
],
{
parser: {
type: 'json',
x: 'lng',
y: 'lat',
},
},
)
.shape('circle')
.color('#f00')
.size(150)
.style({
unit: 'meter',
});
this.scene.addLayer(layer);
// setTimeout(() => {
// layer.style({
// opacity: 0.5,
// unit: ''
// })
// scene.render()
// }, 2000)
scene.addLayer(layer);
});
}