mirror of https://gitee.com/antv-l7/antv-l7
Shihui (#960)
* 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:
parent
71483e03d7
commit
8763a3a718
|
@ -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);
|
||||
|
|
|
@ -76,6 +76,7 @@ export enum AttributeType {
|
|||
|
||||
export interface IAnimateOption {
|
||||
enable: boolean;
|
||||
type?: string;
|
||||
interval?: number;
|
||||
duration?: number;
|
||||
trailLength?: number;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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; // 全局透明度
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue