mirror of https://gitee.com/antv-l7/antv-l7
feat: 优化、修复点图层等面积点模式 (#1222)
* feat: 去处事件节流 * feat: 修复、优化等面积点存在的问题和可视化表现 * style: lint style * style: lint style
This commit is contained in:
parent
6dde6c9c7f
commit
107b6a38e0
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue