* feat: 补全 mapbox 模式下等面积点

* style: lint style

* fix: 修复 pointLayer animate 模式 opacity 失效

* style: lint style

* feat: 拆分 pointLayer 的 shader

* style: lint sytle

* feat: 拆分 lineLayer 的 linear 模式

* style: lint style

* feat: 优化点击的拾取判断

* style: lint style
This commit is contained in:
YiQianYao 2022-02-12 19:13:59 +08:00 committed by GitHub
parent 71483e03d7
commit 8763a3a718
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 210 additions and 68 deletions

View File

@ -176,7 +176,11 @@ export default class PickingService implements IPickingService {
this.alreadyInPicking = true;
const t = new Date().getTime();
// TODO: 优化拾取操作 在右键时 mousedown 和 contextmenu 几乎同时触发,所以不能舍去这一次的触发
if (t - this.lastPickTime > 10 || target.type === 'contextmenu') {
if (
t - this.lastPickTime > 10 ||
target.type === 'contextmenu' ||
target.type === 'click'
) {
await this.pickingLayers(target);
}
// await this.pickingLayers(target);

View File

@ -76,6 +76,7 @@ export enum AttributeType {
export interface IAnimateOption {
enable: boolean;
type?: string;
interval?: number;
duration?: number;
trailLength?: number;

View File

@ -1,3 +1,4 @@
import { IAnimateOption } from '@antv/l7-core';
import { generateColorRamp, getMask, IColorRamp } from '@antv/l7-utils';
import { styleColor, styleOffset, styleSingle } from '../core/BaseModel';
import {
@ -59,6 +60,8 @@ export interface IPointLayerStyleOptions {
unit?: string;
mask?: boolean;
maskInside?: boolean;
animateOption?: IAnimateOption;
}
export interface IPolygonLayerStyleOptions {

View File

@ -15,8 +15,12 @@ import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel';
import { ILineLayerStyleOptions, lineStyleType } from '../../core/interface';
import { LineTriangulation } from '../../core/triangulation';
// other function shaders
import linear_line_frag from '../shaders/frag/linear_frag.glsl';
// basic line shader
import line_frag from '../shaders/line_frag.glsl';
import line_vert from '../shaders/line_vert.glsl';
const lineStyleObj: { [key: string]: number } = {
solid: 0.0,
dash: 1.0,
@ -139,11 +143,12 @@ export default class LineModel extends BaseModel {
mask = false,
maskInside = true,
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
const { frag, vert, type } = this.getShaders();
return [
this.layer.buildLayerModel({
moduleName: 'line',
vertexShader: line_vert,
fragmentShader: line_frag,
moduleName: 'line' + type,
vertexShader: vert,
fragmentShader: frag,
triangulation: LineTriangulation,
primitive: gl.TRIANGLES,
blend: this.getBlend(),
@ -152,6 +157,32 @@ export default class LineModel extends BaseModel {
}),
];
}
/**
* shader
* @returns
*/
public getShaders(): { frag: string; vert: string; type: string } {
const {
sourceColor,
targetColor,
} = this.layer.getLayerConfig() as ILineLayerStyleOptions;
if (sourceColor && targetColor) {
// 分离 linear 功能
return {
frag: linear_line_frag,
vert: line_vert,
type: 'linear',
};
} else {
return {
frag: line_frag,
vert: line_vert,
type: 'normal',
};
}
}
protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({
name: 'distance',

View File

@ -0,0 +1,32 @@
#define LineTypeSolid 0.0
#define LineTypeDash 1.0
#define Animate 0.0
#define LineTexture 1.0
uniform float u_blur : 0.99;
uniform float u_line_type: 0.0;
uniform float u_opacity : 1.0;
varying vec4 v_color;
uniform float u_linearColor: 0;
uniform vec4 u_sourceColor;
uniform vec4 u_targetColor;
#pragma include "picking"
varying mat4 styleMappingMat;
// [animate, duration, interval, trailLength],
void main() {
float opacity = styleMappingMat[0][0];
float d_distance_ratio = styleMappingMat[3].r; // 当前点位距离占线总长的比例
if(u_linearColor == 1.0) { // 使用渐变颜色
gl_FragColor = mix(u_sourceColor, u_targetColor, d_distance_ratio);
} else { // 使用 color 方法传入的颜色
gl_FragColor = v_color;
}
gl_FragColor.a *= opacity; // 全局透明度
gl_FragColor = filterColor(gl_FragColor);
}

View File

@ -23,10 +23,6 @@ varying vec4 v_dash_array;
varying vec2 v_iconMapUV;
uniform float u_linearColor: 0;
uniform vec4 u_sourceColor;
uniform vec4 u_targetColor;
#pragma include "picking"
uniform float u_time;
@ -38,13 +34,7 @@ void main() {
float opacity = styleMappingMat[0][0];
float animateSpeed = 0.0; // 运动速度
float d_distance_ratio = styleMappingMat[3].r; // 当前点位距离占线总长的比例
if(u_linearColor == 1.0) { // 使用渐变颜色
gl_FragColor = mix(u_sourceColor, u_targetColor, d_distance_ratio);
} else { // 使用 color 方法传入的颜色
gl_FragColor = v_color;
}
gl_FragColor = v_color;
// anti-alias
// float blur = 1.0 - smoothstep(u_blur, 1., length(v_normal.xy));
gl_FragColor.a *= opacity; // 全局透明度

View File

@ -16,6 +16,9 @@ import {
GlobelPointFillTriangulation,
PointFillTriangulation,
} from '../../core/triangulation';
// animate pointLayer shader - support animate
import waveFillFrag from '../shaders/animate/wave_frag.glsl';
// static pointLayer shader - not support animate
import pointFillFrag from '../shaders/fill_frag.glsl';
import pointFillVert from '../shaders/fill_vert.glsl';
@ -100,9 +103,11 @@ export default class FillModel extends BaseModel {
};
}
public getAnimateUniforms(): IModelUniform {
const { animateOption } = this.layer.getLayerConfig() as ILayerConfig;
const {
animateOption = { enable: false },
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
return {
u_aimate: this.animateOption2Array(animateOption as IAnimateOption),
u_aimate: this.animateOption2Array(animateOption),
u_time: this.layer.getLayerAnimateTime(),
};
}
@ -128,8 +133,6 @@ export default class FillModel extends BaseModel {
unit === 'meter' &&
version !== Version.L7MAP &&
version !== Version.GLOBEL
// &&
// version !== Version.MAPBOX
) {
this.isMeter = true;
this.calMeter2Coord();
@ -138,6 +141,10 @@ export default class FillModel extends BaseModel {
return this.buildModels();
}
/**
* unit meter
* @returns
*/
public calMeter2Coord() {
// @ts-ignore
const [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent;
@ -181,14 +188,17 @@ export default class FillModel extends BaseModel {
const {
mask = false,
maskInside = true,
animateOption = { enable: false },
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
const { frag, vert, type } = this.getShaders(animateOption);
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
const isGlobel = this.mapService.version === 'GLOBEL';
return [
this.layer.buildLayerModel({
moduleName: 'pointfill',
vertexShader: pointFillVert,
fragmentShader: pointFillFrag,
moduleName: 'pointfill-' + type,
vertexShader: vert,
fragmentShader: frag,
triangulation: isGlobel
? GlobelPointFillTriangulation
: PointFillTriangulation,
@ -200,10 +210,42 @@ export default class FillModel extends BaseModel {
];
}
/**
* animateOption shader
* @returns
*/
public getShaders(
animateOption: IAnimateOption,
): { frag: string; vert: string; type: string } {
if (animateOption.enable) {
switch (animateOption.type) {
case 'wave':
return {
frag: waveFillFrag,
vert: pointFillVert,
type: 'wave',
};
default:
return {
frag: waveFillFrag,
vert: pointFillVert,
type: 'wave',
};
}
} else {
return {
frag: pointFillFrag,
vert: pointFillVert,
type: 'normal',
};
}
}
public clearModels() {
this.dataTexture?.destroy();
}
// overwrite baseModel func
protected animateOption2Array(option: IAnimateOption): number[] {
return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0];
}

View File

@ -0,0 +1,50 @@
uniform float u_additive;
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
varying vec4 v_data;
varying vec4 v_color;
varying float v_radius;
uniform float u_time;
uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
#pragma include "sdf_2d"
#pragma include "picking"
void main() {
vec4 textrueStroke = vec4(
styleMappingMat[1][0],
styleMappingMat[1][1],
styleMappingMat[1][2],
styleMappingMat[1][3]
);
float opacity = styleMappingMat[0][0];
float stroke_opacity = styleMappingMat[0][1];
float strokeWidth = styleMappingMat[0][2];
vec4 strokeColor = textrueStroke == vec4(0) ? v_color : textrueStroke;
float r = v_radius / (v_radius + strokeWidth);
// 'circle'
float outer_df = sdCircle(v_data.xy, 1.0);
float inner_df = sdCircle(v_data.xy, r);
float d = length(v_data.xy);
if(d > 0.5) {
discard;
}
float PI = 3.14159;
float intensity = clamp(cos(d * PI), 0.0, 1.0) * clamp(cos(2.0 * PI * (d * 2.0 * u_aimate.z - u_aimate.y * u_time)), 0.0, 1.0);
// TODO: 根据叠加水波效果
gl_FragColor = vec4(v_color.xyz, v_color.a * opacity * intensity);
// TODO: 优化在水波纹情况下的拾取
if(d < 0.45) {
gl_FragColor = filterColor(gl_FragColor);
}
}

View File

@ -1,4 +1,3 @@
#define Animate 0.0
uniform float u_globel;
uniform float u_additive;
@ -8,8 +7,6 @@ varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
varying vec4 v_data;
varying vec4 v_color;
varying float v_radius;
uniform float u_time;
uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
#pragma include "sdf_2d"
#pragma include "picking"
@ -18,7 +15,6 @@ uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
void main() {
int shape = int(floor(v_data.w + 0.5));
vec4 textrueStroke = vec4(
styleMappingMat[1][0],
styleMappingMat[1][1],
@ -78,9 +74,6 @@ void main() {
0.0,
inner_df
);
float PI = 3.14159;
float N_RINGS = 3.0;
float FREQ = 1.0;
if(strokeWidth < 0.01) {
gl_FragColor = vec4(v_color.rgb, v_color.a * opacity);
@ -88,37 +81,13 @@ void main() {
gl_FragColor = mix(vec4(v_color.rgb, v_color.a * opacity), strokeColor * stroke_opacity, color_t);
}
// gl_FragColor = mix(vec4(v_color.rgb, v_color.a * opacity), strokeColor * stroke_opacity, color_t);
if(u_aimate.x == Animate) {
float d = length(v_data.xy);
float intensity = clamp(cos(d * PI), 0.0, 1.0) * clamp(cos(2.0 * PI * (d * 2.0 * u_aimate.z - u_aimate.y * u_time)), 0.0, 1.0);
// TODO: 根据叠加模式选择效果
if(u_additive > 0.0) {
gl_FragColor *= intensity;
} else {
gl_FragColor = vec4(gl_FragColor.xyz, intensity);
}
// TODO: 优化在水波纹情况下的拾取a == 0 时无法拾取)
if(d < 0.7) {
gl_FragColor.a = max(gl_FragColor.a, 0.001);
}
if(u_additive > 0.0) {
gl_FragColor = filterColorAnimate(gl_FragColor);
} else {
gl_FragColor = filterColor(gl_FragColor);
}
gl_FragColor.a *= opacity;
} else {
gl_FragColor = filterColor(gl_FragColor);
}
if(u_additive > 0.0) {
gl_FragColor *= opacity_t;
} else {
gl_FragColor.a *= opacity_t;
}
if(gl_FragColor.a > 0.0) {
gl_FragColor = filterColor(gl_FragColor);
}
}

View File

@ -26,7 +26,7 @@ export default class Amap2demo_styleMap extends React.Component {
)
.then((res) => res.json())
.then((data) => {
let layer = new PointLayer()
let layer = new PointLayer({}) // blend: "additive"
.source(data, {
parser: {
type: 'json',

View File

@ -25,6 +25,7 @@ export default class GaodeMapComponent extends React.Component {
pitch: 40,
// style: 'dark',
zoom: 17,
// dragEnable: false
}),
});
// normal = 'normal',
@ -78,7 +79,7 @@ export default class GaodeMapComponent extends React.Component {
textOffset: [50, 20],
});
let layer = new PointLayer({})
let layer = new PointLayer({}) // blend: 'additive'
.source(
[
{
@ -86,8 +87,12 @@ export default class GaodeMapComponent extends React.Component {
lat: 30.267069,
},
{
lng: aspaceLnglat[0],
lat: aspaceLnglat[1],
lng: 120.1025,
lat: 30.264701434772807,
},
{
lng: 120.1019811630249,
lat: 30.264701434772807,
},
],
{
@ -100,16 +105,23 @@ export default class GaodeMapComponent extends React.Component {
)
.shape('circle')
// .color('#0f9')
.color('#f00')
.color('#4169E1')
// .size([10, 10, 100])
.size(100)
// .animate({
// // enable: true,
// enable: false,
// // type: 'www'
// })
// .animate(true)
.active({ color: '#00f' })
.style({
// opacity: 0.1,
// opacity: 0.5,
stroke: '#f00',
// strokeWidth: 10,
strokeWidth: 0,
strokeOpacity: 1,
unit: 'meter',
// unit: 'meter',
});
// .animate(true)
// .animate({
@ -148,6 +160,14 @@ export default class GaodeMapComponent extends React.Component {
// console.log(scene.getLayers());
// });
// layer.on('unclick', (e) => {
// console.log('unclick');
// });
// layer.on('dbclick', () => {
// console.log('dbclick')
// })
// setTimeout(() => {
// layer.destroy();
// }, 2000);

View File

@ -374,11 +374,11 @@ export default class ScaleComponent extends React.Component {
},
},
)
// .shape('circle')
.shape('cylinder')
.shape('circle')
// .shape('cylinder')
.color('#f00')
.size('', () => [1, 1, 10])
// .size(20)
// .size('', () => [1, 1, 10])
.size(20)
.style({
// opacity: 0.6,
})