Shihuidev (#887)

* feat: 增加着色器的拾取计算控制、完善 arcmini

* feat: 完善 enableShaderPick/disableShaderPick 功能

* style: lint style

* feat: 补充调用高德地图公交线路查询 demo

* style: lint style

* feat: 优化弧线的纹理动画

* style: lint style

* feat: 去除greatCircle 的纹理动画优化

* feat: 扩展点图层圆柱效果

* feat: 增加几何体的径向渐变配置

* style: lint style

* fix: 修复bug 图层触发的事件跟图层设置的zIndex无关,只跟插入图层先后顺序有关

* style: lint style

* feat: 补全挤出几何体拾取颜色的光照配置

* style: lint style

* fix: 修复圆柱 cull 问题 mapbox amap 不同

* feat: 图层销毁时的内存泄漏

* style: lint style

* feat: 平面弧线新增弧线偏移量的数据映射能力

* style: lint style

* fix: 修复重复销毁bug

* style: lint style

* feat: 修复 texture 重复销毁问题

* style: lint style

* fix: 修复图层叠加模式下的拾取失效问题

* style: lint style

* fix: 修复纹理贴图在 zoom 大于 12 时存在的问题

* fix: 修复水波点颜色偏暗

* feat: 优化点图层的渲染效果,叠加渲染效果

* style: lint style

* fix: 修复 layer contextmenu 事件丢失

* fix: 修复 map 类型 resize 失效

* style: lint style

* feat: 增加瓦片地图的请求节流

* style: lint style

* feat: 优化热力图在 radius 数值比较大时热力点边缘发生裁剪的现象

* style: lint style

* fix: 修复resize 后 picking shiqu 拾取失败的问题

* feat: 优化 marker/popup 在容器边缘的表现

* feat: 增加 setEnableRender 方法

* style: lint style

* feat: 增加城市图层扫光特效

* style: lint style

* feat: 补全拾取色混合配置

* style: lint style

* feat: 增加高德地图的面积大小点

* style: lint style

* feat: 点优化边缘锯齿
This commit is contained in:
YiQianYao 2021-12-21 13:57:48 +08:00 committed by GitHub
parent 56ec1259af
commit 7e73477219
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 203 additions and 30 deletions

View File

@ -70,7 +70,9 @@ const defaultLayerConfig: Partial<ILayerConfig> = {
enableHighlight: false,
enableSelect: false,
highlightColor: '#2f54eb',
activeMix: 0,
selectColor: 'blue',
selectMix: 0,
enableTAA: false,
jitterScale: 1,
enableLighting: false,

View File

@ -87,6 +87,7 @@ export interface IPickedFeature {
// 交互样式
export interface IActiveOption {
color: string | number[];
mix?: number;
}
type ILngLat = [number, number];
@ -339,6 +340,8 @@ export interface ILayerConfig {
selectColor: string | number[];
active: boolean;
activeColor: string | number[];
activeMix?: number;
selectMix?: number;
/**
* TAA
*/

View File

@ -3,6 +3,8 @@ uniform vec4 u_HighlightColor : [0, 0, 0, 0];
uniform float u_PickingStage : 0.0;
uniform float u_shaderPick;
uniform float u_activeMix: 0;
#define PICKING_NONE 0.0
#define PICKING_ENCODE 1.0
#define PICKING_HIGHLIGHT 2.0
@ -21,7 +23,7 @@ vec4 filterHighlightColor(vec4 color, float weight) {
float highLightRatio = highLightAlpha / (highLightAlpha + color.a * (1.0 - highLightAlpha));
vec3 resultRGB = mix(color.rgb, highLightColor.rgb, highLightRatio);
return vec4(resultRGB * weight, color.a);
return vec4(mix(resultRGB * weight, color.rgb, u_activeMix), color.a);
} else {
return color;
}

View File

@ -570,6 +570,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
if (options.color) {
activeOption.highlightColor = options.color;
}
if (options.mix) {
activeOption.activeMix = options.mix;
}
} else {
activeOption.enableHighlight = !!options;
}
@ -586,6 +589,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
highlightColor: isObject(options)
? options.color
: this.getLayerConfig().highlightColor,
activeMix: isObject(options)
? options.mix
: this.getLayerConfig().activeMix,
});
this.pick({ x, y });
} else {
@ -594,6 +600,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
highlightColor: isObject(options)
? options.color
: this.getLayerConfig().highlightColor,
activeMix: isObject(options)
? options.mix
: this.getLayerConfig().activeMix,
});
this.hooks.beforeSelect
.call(encodePickingColor(id as number) as number[])
@ -614,6 +623,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
if (option.color) {
activeOption.selectColor = option.color;
}
if (option.mix) {
activeOption.selectMix = option.mix;
}
} else {
activeOption.enableSelect = !!option;
}
@ -631,6 +643,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
selectColor: isObject(options)
? options.color
: this.getLayerConfig().selectColor,
selectMix: isObject(options)
? options.mix
: this.getLayerConfig().selectMix,
});
this.pick({ x, y });
} else {
@ -639,6 +654,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
selectColor: isObject(options)
? options.color
: this.getLayerConfig().selectColor,
selectMix: isObject(options)
? options.mix
: this.getLayerConfig().selectMix,
});
this.hooks.beforeSelect
.call(encodePickingColor(id as number) as number[])

View File

@ -83,7 +83,7 @@ export default class PixelPickingPlugin implements ILayerPlugin {
layer.hooks.beforeHighlight.tap(
'PixelPickingPlugin',
(pickedColor: number[]) => {
const { highlightColor } = layer.getLayerConfig();
const { highlightColor, activeMix = 0 } = layer.getLayerConfig();
const highlightColorInArray =
typeof highlightColor === 'string'
? rgb2arr(highlightColor)
@ -96,6 +96,7 @@ export default class PixelPickingPlugin implements ILayerPlugin {
u_PickingStage: PickingStage.HIGHLIGHT,
u_PickingColor: pickedColor,
u_HighlightColor: highlightColorInArray.map((c) => c * 255),
u_activeMix: activeMix,
}),
);
},
@ -104,7 +105,7 @@ export default class PixelPickingPlugin implements ILayerPlugin {
layer.hooks.beforeSelect.tap(
'PixelPickingPlugin',
(pickedColor: number[]) => {
const { selectColor } = layer.getLayerConfig();
const { selectColor, selectMix = 0 } = layer.getLayerConfig();
const highlightColorInArray =
typeof selectColor === 'string'
? rgb2arr(selectColor)
@ -117,6 +118,7 @@ export default class PixelPickingPlugin implements ILayerPlugin {
u_PickingStage: PickingStage.HIGHLIGHT,
u_PickingColor: pickedColor,
u_HighlightColor: highlightColorInArray.map((c) => c * 255),
u_activeMix: selectMix,
}),
);
},

View File

@ -24,7 +24,7 @@ import pointFillVert from '../shaders/fill_vert.glsl';
import { isNumber } from 'lodash';
import { mat4, vec3 } from 'gl-matrix';
import { Version } from '../../../../maps/src/version';
interface IPointLayerStyleOptions {
opacity: styleSingle;
strokeWidth: styleSingle;
@ -32,9 +32,12 @@ interface IPointLayerStyleOptions {
strokeOpacity: styleSingle;
offsets: styleOffset;
blend: string;
unit: string;
}
// 判断当前使用的 style 中的变量属性是否需要进行数据映射
export default class FillModel extends BaseModel {
public meter2coord: number = 1;
private isMeter: boolean = false;
public getUninforms(): IModelUniform {
const {
opacity = 1,
@ -92,8 +95,10 @@ export default class FillModel extends BaseModel {
});
}
return {
u_isMeter: Number(this.isMeter),
u_additive: blend === 'additive' ? 1.0 : 0.0,
u_globel: this.mapService.version === 'GLOBEL' ? 1 : 0,
u_globel: this.mapService.version === Version.GLOBEL ? 1 : 0,
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
u_cellTypeLayout: this.getCellTypeLayout(),
@ -127,9 +132,38 @@ 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 &&
version !== Version.MAPBOX
) {
this.isMeter = true;
this.calMeter2Coord();
}
return this.buildModels();
}
public calMeter2Coord() {
// @ts-ignore
const [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent;
const center = [(minLng + maxLng) / 2, (minLat + maxLat) / 2];
// @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,
]);
this.meter2coord = (m1 + m2) / 2;
}
public buildModels(): IModel[] {
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
const isGlobel = this.mapService.version === 'GLOBEL';
@ -246,7 +280,9 @@ export default class FillModel extends BaseModel {
) => {
const { size = 5 } = feature;
// console.log('featureIdx', featureIdx, feature)
return Array.isArray(size) ? [size[0]] : [size as number];
return Array.isArray(size)
? [size[0] * this.meter2coord]
: [(size as number) * this.meter2coord];
},
},
});

View File

@ -9,6 +9,7 @@ varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样
uniform float u_globel;
uniform mat4 u_ModelMatrix;
uniform mat4 u_Mvp;
uniform float u_isMeter;
varying vec4 v_data;
varying vec4 v_color;
@ -124,14 +125,22 @@ void main() {
// TODO: billboard
// anti-alias
// float antialiased_blur = -max(u_blur, antialiasblur);
float antialiasblur = -max(1.0 / u_DevicePixelRatio / (newSize + u_stroke_width), u_blur);
float antialiasblur = -max(2.0 / u_DevicePixelRatio / a_Size, u_blur);
vec2 offset = (extrude.xy * (newSize + u_stroke_width) + textrueOffsets);
if(u_isMeter < 1.0) {
// 不以米为实际单位
offset = project_pixel(offset);
} else {
// 以米为实际单位
antialiasblur *= pow(19.0 - u_Zoom, 2.0);
}
// construct point coords
// TODP: /abs(extrude.x) 是为了兼容地球模式
v_data = vec4(extrude.x/abs(extrude.x), extrude.y/abs(extrude.y), antialiasblur,shape_type);
// vec2 offset = project_pixel(extrude * (newSize + u_stroke_width) + u_offsets);
vec2 offset = project_pixel(extrude.xy * (newSize + u_stroke_width) + textrueOffsets);
vec4 project_pos = project_position(vec4(a_Position.xy, 0.0, 1.0));
// gl_Position = project_common_position_to_clipspace(vec4(project_pos.xy + offset, project_pixel(setPickingOrder(0.0)), 1.0));

View File

@ -425,6 +425,22 @@ export default class AMapService
this.viewport = new Viewport();
}
public meterToCoord(center: [number, number], outer: [number, number]) {
// 统一根据经纬度来转化
// Tip: 实际米距离 unit meter
const meterDis = AMap.GeometryUtil.distance(
new AMap.LngLat(...center),
new AMap.LngLat(...outer),
);
// Tip: 三维世界坐标距离
const [x1, y1] = this.lngLatToCoord(center);
const [x2, y2] = this.lngLatToCoord(outer);
const coordDis = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
return coordDis / meterDis;
}
public exportMap(type: 'jpg' | 'png'): string {
const renderCanvas = this.getContainer()?.getElementsByClassName(
'amap-layer',

View File

@ -517,6 +517,22 @@ export default class AMapService
});
}
public meterToCoord(center: [number, number], outer: [number, number]) {
// 统一根据经纬度来转化
// Tip: 实际米距离 unit meter
const meterDis = AMap.GeometryUtil.distance(
new AMap.LngLat(...center),
new AMap.LngLat(...outer),
);
// Tip: 三维世界坐标距离
const [x1, y1] = this.lngLatToCoord(center);
const [x2, y2] = this.lngLatToCoord(outer);
const coordDis = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
return coordDis / meterDis;
}
public exportMap(type: 'jpg' | 'png'): string {
const renderCanvas = this.getContainer()?.getElementsByClassName(
'amap-layer',

View File

@ -401,6 +401,33 @@ export default class MapboxService
return this.$mapContainer;
}
public meterToCoord(center: [number, number], outer: [number, number]) {
// 统一根据经纬度来转化
// Tip: 实际米距离 unit meter
const centerLnglat = new mapboxgl.LngLat(center[0], center[1]);
const outerLnglat = new mapboxgl.LngLat(outer[0], outer[1]);
const meterDis = centerLnglat.distanceTo(outerLnglat);
// Tip: 三维世界坐标距离
const centerMercator = mapboxgl.MercatorCoordinate.fromLngLat({
lng: center[0],
lat: center[1],
});
const outerMercator = mapboxgl.MercatorCoordinate.fromLngLat({
lng: outer[0],
lat: outer[1],
});
const { x: x1, y: y1 } = centerMercator;
const { x: x2, y: y2 } = outerMercator;
// Math.pow(2, 22) 4194304
const coordDis =
Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) * 4194304 * 2;
return coordDis / meterDis;
}
public exportMap(type: 'jpg' | 'png'): string {
const renderCanvas = this.map.getCanvas();
const layersPng =

View File

@ -32,18 +32,21 @@ export default class Amap2demo_citybuilding extends React.Component {
.animate({
enable: true,
})
.active(true)
.active({
color: '#0ff',
mix: 0.5,
})
.style({
opacity: 0.7,
baseColor: 'rgb(16,16,16)',
windowColor: 'rgb(30,60,89)',
brightColor: 'rgb(255,176,38)',
// sweep: {
// enable: true,
// sweepRadius: 4,
// sweepColor: 'rgb(0, 100, 100)',
// sweepSpeed: 0.5
// }
sweep: {
enable: true,
sweepRadius: 4,
sweepColor: 'rgb(0, 100, 100)',
sweepSpeed: 0.5,
},
});
scene.addLayer(pointLayer);

View File

@ -97,6 +97,16 @@ export default class Amap2demo_image extends React.Component {
},
})
.shape('name', ['00', '01', '02'])
// .active(true)
.active({
color: '#00f',
mix: 0.6,
})
// .select(true)
.select({
color: '#00f',
mix: 0.22,
})
.size(20);
scene.addLayer(this.imageLayer);
});

View File

@ -1,8 +1,13 @@
// @ts-ignore
import { PointLayer, Scene, LineLayer } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
import { PointLayer, Scene, LineLayer, PolygonLayer } from '@antv/l7';
import { GaodeMap, GaodeMapV2, Mapbox } from '@antv/l7-maps';
import * as React from 'react';
import * as turf from '@turf/turf';
const aspaceLnglat = [120.1019811630249, 30.264701434772807] as [
number,
number,
];
export default class GaodeMapComponent extends React.Component {
// @ts-ignore
private scene: Scene;
@ -15,11 +20,10 @@ export default class GaodeMapComponent extends React.Component {
const scene = new Scene({
id: 'map',
map: new GaodeMap({
center: [121.107846, 30.267069],
center: aspaceLnglat,
pitch: 0,
style: 'dark',
zoom: 20,
animateEnable: false,
// style: 'dark',
zoom: 17,
}),
});
// normal = 'normal',
@ -29,6 +33,29 @@ export default class GaodeMapComponent extends React.Component {
// max = 'max',
// none = 'none',
// blend: 'additive'
var circleRadius = 100;
var radius = circleRadius;
var data = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: turf.circle(aspaceLnglat, radius, {
steps: 10,
units: 'meters',
}).geometry.coordinates,
},
},
],
};
let trufCircle = new PolygonLayer()
.size('name', [0, 10000, 50000, 30000, 100000])
.source(data)
.color('#f00')
.shape('fill');
let layer = new PointLayer({ zIndex: 2, blend: 'additive' })
.source(
@ -38,8 +65,8 @@ export default class GaodeMapComponent extends React.Component {
lat: 30.267069,
},
{
lng: 121.107,
lat: 30.267069,
lng: aspaceLnglat[0],
lat: aspaceLnglat[1],
},
],
{
@ -51,20 +78,22 @@ export default class GaodeMapComponent extends React.Component {
},
)
.shape('circle')
.color('#1990FF')
.size(40)
.color('#00f')
.size(circleRadius)
.style({
stroke: '#f00',
strokeWidth: 3,
// strokeWidth: 10,
strokeOpacity: 1,
unit: 'meter',
})
.animate(true)
.active({ color: '#ff0' });
// .animate(true)
.active({ color: '#00f' });
this.scene = scene;
scene.on('loaded', () => {
scene.addLayer(layer);
// scene.addLayer(trufCircle);
});
let c = 1;
layer.on('click', () => {