* 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; this.alreadyInPicking = true;
const t = new Date().getTime(); const t = new Date().getTime();
// TODO: 优化拾取操作 在右键时 mousedown 和 contextmenu 几乎同时触发,所以不能舍去这一次的触发 // 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);
} }
// await this.pickingLayers(target); // await this.pickingLayers(target);

View File

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

View File

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

View File

@ -15,8 +15,12 @@ import { isNumber } from 'lodash';
import BaseModel from '../../core/BaseModel'; import BaseModel from '../../core/BaseModel';
import { ILineLayerStyleOptions, lineStyleType } from '../../core/interface'; import { ILineLayerStyleOptions, lineStyleType } from '../../core/interface';
import { LineTriangulation } from '../../core/triangulation'; 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_frag from '../shaders/line_frag.glsl';
import line_vert from '../shaders/line_vert.glsl'; import line_vert from '../shaders/line_vert.glsl';
const lineStyleObj: { [key: string]: number } = { const lineStyleObj: { [key: string]: number } = {
solid: 0.0, solid: 0.0,
dash: 1.0, dash: 1.0,
@ -139,11 +143,12 @@ export default class LineModel extends BaseModel {
mask = false, mask = false,
maskInside = true, maskInside = true,
} = this.layer.getLayerConfig() as ILineLayerStyleOptions; } = this.layer.getLayerConfig() as ILineLayerStyleOptions;
const { frag, vert, type } = this.getShaders();
return [ return [
this.layer.buildLayerModel({ this.layer.buildLayerModel({
moduleName: 'line', moduleName: 'line' + type,
vertexShader: line_vert, vertexShader: vert,
fragmentShader: line_frag, fragmentShader: frag,
triangulation: LineTriangulation, triangulation: LineTriangulation,
primitive: gl.TRIANGLES, primitive: gl.TRIANGLES,
blend: this.getBlend(), 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() { protected registerBuiltinAttributes() {
this.styleAttributeService.registerStyleAttribute({ this.styleAttributeService.registerStyleAttribute({
name: 'distance', 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; varying vec2 v_iconMapUV;
uniform float u_linearColor: 0;
uniform vec4 u_sourceColor;
uniform vec4 u_targetColor;
#pragma include "picking" #pragma include "picking"
uniform float u_time; uniform float u_time;
@ -38,13 +34,7 @@ void main() {
float opacity = styleMappingMat[0][0]; float opacity = styleMappingMat[0][0];
float animateSpeed = 0.0; // 运动速度 float animateSpeed = 0.0; // 运动速度
float d_distance_ratio = styleMappingMat[3].r; // 当前点位距离占线总长的比例 float d_distance_ratio = styleMappingMat[3].r; // 当前点位距离占线总长的比例
gl_FragColor = v_color;
if(u_linearColor == 1.0) { // 使用渐变颜色
gl_FragColor = mix(u_sourceColor, u_targetColor, d_distance_ratio);
} else { // 使用 color 方法传入的颜色
gl_FragColor = v_color;
}
// anti-alias // anti-alias
// float blur = 1.0 - smoothstep(u_blur, 1., length(v_normal.xy)); // float blur = 1.0 - smoothstep(u_blur, 1., length(v_normal.xy));
gl_FragColor.a *= opacity; // 全局透明度 gl_FragColor.a *= opacity; // 全局透明度

View File

@ -16,6 +16,9 @@ import {
GlobelPointFillTriangulation, GlobelPointFillTriangulation,
PointFillTriangulation, PointFillTriangulation,
} from '../../core/triangulation'; } 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 pointFillFrag from '../shaders/fill_frag.glsl';
import pointFillVert from '../shaders/fill_vert.glsl'; import pointFillVert from '../shaders/fill_vert.glsl';
@ -100,9 +103,11 @@ export default class FillModel extends BaseModel {
}; };
} }
public getAnimateUniforms(): IModelUniform { public getAnimateUniforms(): IModelUniform {
const { animateOption } = this.layer.getLayerConfig() as ILayerConfig; const {
animateOption = { enable: false },
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
return { return {
u_aimate: this.animateOption2Array(animateOption as IAnimateOption), u_aimate: this.animateOption2Array(animateOption),
u_time: this.layer.getLayerAnimateTime(), u_time: this.layer.getLayerAnimateTime(),
}; };
} }
@ -128,8 +133,6 @@ export default class FillModel extends BaseModel {
unit === 'meter' && unit === 'meter' &&
version !== Version.L7MAP && version !== Version.L7MAP &&
version !== Version.GLOBEL version !== Version.GLOBEL
// &&
// version !== Version.MAPBOX
) { ) {
this.isMeter = true; this.isMeter = true;
this.calMeter2Coord(); this.calMeter2Coord();
@ -138,6 +141,10 @@ export default class FillModel extends BaseModel {
return this.buildModels(); return this.buildModels();
} }
/**
* unit meter
* @returns
*/
public calMeter2Coord() { public calMeter2Coord() {
// @ts-ignore // @ts-ignore
const [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent; const [minLng, minLat, maxLng, maxLat] = this.layer.getSource().extent;
@ -181,14 +188,17 @@ export default class FillModel extends BaseModel {
const { const {
mask = false, mask = false,
maskInside = true, maskInside = true,
animateOption = { enable: false },
} = this.layer.getLayerConfig() as IPointLayerStyleOptions; } = this.layer.getLayerConfig() as IPointLayerStyleOptions;
const { frag, vert, type } = this.getShaders(animateOption);
// TODO: 判断当前的点图层的模型是普通地图模式还是地球模式 // TODO: 判断当前的点图层的模型是普通地图模式还是地球模式
const isGlobel = this.mapService.version === 'GLOBEL'; const isGlobel = this.mapService.version === 'GLOBEL';
return [ return [
this.layer.buildLayerModel({ this.layer.buildLayerModel({
moduleName: 'pointfill', moduleName: 'pointfill-' + type,
vertexShader: pointFillVert, vertexShader: vert,
fragmentShader: pointFillFrag, fragmentShader: frag,
triangulation: isGlobel triangulation: isGlobel
? GlobelPointFillTriangulation ? GlobelPointFillTriangulation
: PointFillTriangulation, : 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() { public clearModels() {
this.dataTexture?.destroy(); this.dataTexture?.destroy();
} }
// overwrite baseModel func
protected animateOption2Array(option: IAnimateOption): number[] { protected animateOption2Array(option: IAnimateOption): number[] {
return [option.enable ? 0 : 1.0, option.speed || 1, option.rings || 3, 0]; 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_globel;
uniform float u_additive; uniform float u_additive;
@ -8,8 +7,6 @@ varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
varying vec4 v_data; varying vec4 v_data;
varying vec4 v_color; varying vec4 v_color;
varying float v_radius; varying float v_radius;
uniform float u_time;
uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
#pragma include "sdf_2d" #pragma include "sdf_2d"
#pragma include "picking" #pragma include "picking"
@ -18,7 +15,6 @@ uniform vec4 u_aimate: [ 0, 2., 1.0, 0.2 ];
void main() { void main() {
int shape = int(floor(v_data.w + 0.5)); int shape = int(floor(v_data.w + 0.5));
vec4 textrueStroke = vec4( vec4 textrueStroke = vec4(
styleMappingMat[1][0], styleMappingMat[1][0],
styleMappingMat[1][1], styleMappingMat[1][1],
@ -78,9 +74,6 @@ void main() {
0.0, 0.0,
inner_df inner_df
); );
float PI = 3.14159;
float N_RINGS = 3.0;
float FREQ = 1.0;
if(strokeWidth < 0.01) { if(strokeWidth < 0.01) {
gl_FragColor = vec4(v_color.rgb, v_color.a * opacity); 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);
} }
// 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) { if(u_additive > 0.0) {
gl_FragColor *= opacity_t; gl_FragColor *= opacity_t;
} else { } else {
gl_FragColor.a *= opacity_t; 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((res) => res.json())
.then((data) => { .then((data) => {
let layer = new PointLayer() let layer = new PointLayer({}) // blend: "additive"
.source(data, { .source(data, {
parser: { parser: {
type: 'json', type: 'json',

View File

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

View File

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