mirror of https://gitee.com/antv-l7/antv-l7
Shihuidev (#890)
* 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: 点优化边缘锯齿 * fix: 修复pointLayer stroke 变暗问题 * fix: 修复混合导致的拾取错误 * feat: add simple point 1.0 * style: lint style * feat: simple point support stroke * style: lint style
This commit is contained in:
parent
c381840dba
commit
28ebfefea8
|
@ -33,6 +33,7 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
normal: {
|
||||
blend: 'additive',
|
||||
},
|
||||
simplePoint: {},
|
||||
fill: { blend: 'normal' },
|
||||
extrude: {},
|
||||
image: {},
|
||||
|
@ -60,6 +61,9 @@ export default class PointLayer extends BaseLayer<IPointLayerStyleOptions> {
|
|||
if (shape === 'dot') {
|
||||
return 'normal';
|
||||
}
|
||||
if (shape === 'simple') {
|
||||
return 'simplePoint';
|
||||
}
|
||||
if (shape2d?.indexOf(shape as string) !== -1) {
|
||||
return 'fill';
|
||||
}
|
||||
|
|
|
@ -4,12 +4,14 @@ import FillModel from './fill';
|
|||
import IconModel from './icon-font';
|
||||
import IMageModel from './image';
|
||||
import NormalModel from './normal';
|
||||
import SimplePopint from './simplePoint';
|
||||
import TextModel from './text';
|
||||
|
||||
export type PointType =
|
||||
| 'fill'
|
||||
| 'image'
|
||||
| 'normal'
|
||||
| 'simplePoint'
|
||||
| 'extrude'
|
||||
| 'text'
|
||||
| 'icon';
|
||||
|
@ -18,6 +20,7 @@ const PointModels: { [key in PointType]: any } = {
|
|||
fill: FillModel,
|
||||
image: IMageModel,
|
||||
normal: NormalModel,
|
||||
simplePoint: SimplePopint,
|
||||
extrude: ExtrudeModel,
|
||||
text: TextModel,
|
||||
icon: IconModel,
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
import {
|
||||
AttributeType,
|
||||
BlendType,
|
||||
gl,
|
||||
IEncodeFeature,
|
||||
ILayerConfig,
|
||||
IModel,
|
||||
IModelUniform,
|
||||
} from '@antv/l7-core';
|
||||
|
||||
import { rgb2arr } from '@antv/l7-utils';
|
||||
import { isNumber } from 'lodash';
|
||||
import BaseModel, {
|
||||
styleColor,
|
||||
styleOffset,
|
||||
styleSingle,
|
||||
} from '../../core/BaseModel';
|
||||
import { BlendTypes } from '../../utils/blend';
|
||||
import simplePointFrag from '../shaders/simplePoint_frag.glsl';
|
||||
import simplePointVert from '../shaders/simplePoint_vert.glsl';
|
||||
interface IPointLayerStyleOptions {
|
||||
opacity: styleSingle;
|
||||
offsets: styleOffset;
|
||||
blend: string;
|
||||
strokeOpacity: styleSingle;
|
||||
strokeWidth: styleSingle;
|
||||
stroke: styleColor;
|
||||
}
|
||||
export function PointTriangulation(feature: IEncodeFeature) {
|
||||
const coordinates = feature.coordinates as number[];
|
||||
return {
|
||||
vertices: [...coordinates],
|
||||
indices: [0],
|
||||
size: coordinates.length,
|
||||
};
|
||||
}
|
||||
|
||||
export default class SimplePointModel extends BaseModel {
|
||||
public getDefaultStyle(): Partial<IPointLayerStyleOptions & ILayerConfig> {
|
||||
return {
|
||||
blend: 'additive',
|
||||
};
|
||||
}
|
||||
public getUninforms(): IModelUniform {
|
||||
const {
|
||||
opacity = 1,
|
||||
offsets = [0, 0],
|
||||
blend,
|
||||
strokeOpacity = 1,
|
||||
strokeWidth = 0,
|
||||
stroke = '#fff',
|
||||
} = this.layer.getLayerConfig() as IPointLayerStyleOptions;
|
||||
|
||||
if (
|
||||
this.dataTextureTest &&
|
||||
this.dataTextureNeedUpdate({
|
||||
opacity,
|
||||
offsets,
|
||||
})
|
||||
) {
|
||||
// 判断当前的样式中哪些是需要进行数据映射的,哪些是常量,同时计算用于构建数据纹理的一些中间变量
|
||||
this.judgeStyleAttributes({
|
||||
opacity,
|
||||
offsets,
|
||||
});
|
||||
const encodeData = this.layer.getEncodedData();
|
||||
const { data, width, height } = this.calDataFrame(
|
||||
this.cellLength,
|
||||
encodeData,
|
||||
this.cellProperties,
|
||||
);
|
||||
this.rowCount = height; // 当前数据纹理有多少行
|
||||
|
||||
this.dataTexture =
|
||||
this.cellLength > 0 && data.length > 0
|
||||
? this.createTexture2D({
|
||||
flipY: true,
|
||||
data,
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
: this.createTexture2D({
|
||||
flipY: true,
|
||||
data: [1],
|
||||
format: gl.LUMINANCE,
|
||||
type: gl.FLOAT,
|
||||
width: 1,
|
||||
height: 1,
|
||||
});
|
||||
}
|
||||
return {
|
||||
u_additive: blend === 'additive' ? 1.0 : 0.0,
|
||||
u_dataTexture: this.dataTexture, // 数据纹理 - 有数据映射的时候纹理中带数据,若没有任何数据映射时纹理是 [1]
|
||||
u_cellTypeLayout: this.getCellTypeLayout(),
|
||||
|
||||
u_opacity: isNumber(opacity) ? opacity : 1.0,
|
||||
u_offsets: this.isOffsetStatic(offsets)
|
||||
? (offsets as [number, number])
|
||||
: [0, 0],
|
||||
u_stroke_opacity: isNumber(strokeOpacity) ? strokeOpacity : 1.0,
|
||||
u_stroke_width: isNumber(strokeWidth) ? strokeWidth : 0.0,
|
||||
u_stroke_color: this.getStrokeColor(stroke),
|
||||
};
|
||||
}
|
||||
|
||||
public initModels(): IModel[] {
|
||||
return this.buildModels();
|
||||
}
|
||||
|
||||
public buildModels(): IModel[] {
|
||||
return [
|
||||
this.layer.buildLayerModel({
|
||||
moduleName: 'simplepoint',
|
||||
vertexShader: simplePointVert,
|
||||
fragmentShader: simplePointFrag,
|
||||
triangulation: PointTriangulation,
|
||||
depth: { enable: false },
|
||||
primitive: gl.POINTS,
|
||||
blend: this.getBlend(),
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
public clearModels() {
|
||||
this.dataTexture?.destroy();
|
||||
}
|
||||
|
||||
protected registerBuiltinAttributes() {
|
||||
// point layer size;
|
||||
this.styleAttributeService.registerStyleAttribute({
|
||||
name: 'size',
|
||||
type: AttributeType.Attribute,
|
||||
descriptor: {
|
||||
name: 'a_Size',
|
||||
buffer: {
|
||||
// give the WebGL driver a hint that this buffer may change
|
||||
usage: gl.DYNAMIC_DRAW,
|
||||
data: [],
|
||||
type: gl.FLOAT,
|
||||
},
|
||||
size: 1,
|
||||
update: (
|
||||
feature: IEncodeFeature,
|
||||
featureIdx: number,
|
||||
vertex: number[],
|
||||
attributeIdx: number,
|
||||
) => {
|
||||
const { size = 1 } = feature;
|
||||
return Array.isArray(size) ? [size[0]] : [size as number];
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private defaultStyleOptions(): Partial<
|
||||
IPointLayerStyleOptions & ILayerConfig
|
||||
> {
|
||||
return {
|
||||
blend: BlendType.additive,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
uniform float u_opacity : 1;
|
||||
uniform vec2 u_offsets;
|
||||
uniform float u_additive;
|
||||
|
||||
uniform float u_stroke_opacity : 1;
|
||||
|
||||
uniform vec4 u_stroke_color : [0.0, 0.0, 0.0, 0.0];
|
||||
|
||||
varying vec4 v_color;
|
||||
varying mat4 styleMappingMat; // 传递从片元中传递的映射数据
|
||||
varying float v_blur;
|
||||
varying float v_innerRadius;
|
||||
|
||||
#pragma include "picking"
|
||||
void main() {
|
||||
vec2 center = vec2(0.5);
|
||||
|
||||
float opacity = styleMappingMat[0][0];
|
||||
// Tip: 片元到中心点的距离 0 - 1
|
||||
float fragmengTocenter = distance(center, gl_PointCoord) * 2.0;
|
||||
// Tip: 片元的剪切成圆形
|
||||
float circleClipOpacity = 1.0 - smoothstep(v_blur, 1.0, fragmengTocenter);
|
||||
|
||||
|
||||
if(v_innerRadius < 0.99) {
|
||||
// 当存在 stroke 且 stroke > 0.01
|
||||
float blurWidth = (1.0 - v_blur)/2.0;
|
||||
vec4 stroke = vec4(u_stroke_color.rgb, u_stroke_opacity);
|
||||
if(fragmengTocenter > v_innerRadius + blurWidth) {
|
||||
gl_FragColor = stroke;
|
||||
} else if(fragmengTocenter > v_innerRadius - blurWidth){
|
||||
float mixR = (fragmengTocenter - (v_innerRadius - blurWidth)) / (blurWidth * 2.0);
|
||||
gl_FragColor = mix(v_color, stroke, mixR);
|
||||
} else {
|
||||
gl_FragColor = v_color;
|
||||
}
|
||||
} else {
|
||||
// 当不存在 stroke 或 stroke <= 0.01
|
||||
gl_FragColor = v_color;
|
||||
}
|
||||
|
||||
gl_FragColor.a *= opacity;
|
||||
|
||||
gl_FragColor = filterColor(gl_FragColor);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(u_additive > 0.0) {
|
||||
gl_FragColor *= circleClipOpacity;
|
||||
} else {
|
||||
gl_FragColor.a *= circleClipOpacity;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
attribute vec3 a_Position;
|
||||
uniform mat4 u_ModelMatrix;
|
||||
uniform mat4 u_Mvp;
|
||||
attribute float a_Size;
|
||||
attribute vec4 a_Color;
|
||||
varying vec4 v_color;
|
||||
|
||||
uniform float u_opacity : 1;
|
||||
uniform vec2 u_offsets;
|
||||
uniform float u_stroke_width;
|
||||
|
||||
varying mat4 styleMappingMat; // 用于将在顶点着色器中计算好的样式值传递给片元
|
||||
varying float v_blur;
|
||||
varying float v_innerRadius;
|
||||
|
||||
#pragma include "styleMapping"
|
||||
#pragma include "styleMappingCalOpacity"
|
||||
|
||||
#pragma include "projection"
|
||||
#pragma include "picking"
|
||||
#pragma include "project"
|
||||
void main() {
|
||||
v_color = a_Color;
|
||||
v_blur = 1.0 - 0.05;
|
||||
v_innerRadius = max((a_Size - u_stroke_width) / a_Size, 0.0);
|
||||
|
||||
// cal style mapping - 数据纹理映射部分的计算
|
||||
styleMappingMat = mat4(
|
||||
0.0, 0.0, 0.0, 0.0, // opacity - strokeOpacity - strokeWidth - empty
|
||||
0.0, 0.0, 0.0, 0.0, // strokeR - strokeG - strokeB - strokeA
|
||||
0.0, 0.0, 0.0, 0.0, // offsets[0] - offsets[1]
|
||||
0.0, 0.0, 0.0, 0.0
|
||||
);
|
||||
|
||||
float rowCount = u_cellTypeLayout[0][0]; // 当前的数据纹理有几行
|
||||
float columnCount = u_cellTypeLayout[0][1]; // 当看到数据纹理有几列
|
||||
float columnWidth = 1.0/columnCount; // 列宽
|
||||
float rowHeight = 1.0/rowCount; // 行高
|
||||
float cellCount = calCellCount(); // opacity - strokeOpacity - strokeWidth - stroke - offsets
|
||||
float id = a_vertexId; // 第n个顶点
|
||||
float cellCurrentRow = floor(id * cellCount / columnCount) + 1.0; // 起始点在第几行
|
||||
float cellCurrentColumn = mod(id * cellCount, columnCount) + 1.0; // 起始点在第几列
|
||||
|
||||
// cell 固定顺序 opacity -> strokeOpacity -> strokeWidth -> stroke ...
|
||||
// 按顺序从 cell 中取值、若没有则自动往下取值
|
||||
float textureOffset = 0.0; // 在 cell 中取值的偏移量
|
||||
|
||||
vec2 opacityAndOffset = calOpacityAndOffset(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset, columnWidth, rowHeight);
|
||||
styleMappingMat[0][0] = opacityAndOffset.r;
|
||||
textureOffset = opacityAndOffset.g;
|
||||
|
||||
vec2 textrueOffsets = vec2(0.0, 0.0);
|
||||
if(hasOffsets()) {
|
||||
vec2 valueXPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
|
||||
textrueOffsets.r = pos2value(valueXPos, columnWidth, rowHeight); // x
|
||||
textureOffset += 1.0;
|
||||
|
||||
vec2 valueYPos = nextPos(cellCurrentRow, cellCurrentColumn, columnCount, textureOffset);
|
||||
textrueOffsets.g = pos2value(valueYPos, columnWidth, rowHeight); // x
|
||||
textureOffset += 1.0;
|
||||
} else {
|
||||
textrueOffsets = u_offsets;
|
||||
}
|
||||
|
||||
// cal style mapping
|
||||
|
||||
// vec2 offset = project_pixel(u_offsets);
|
||||
vec2 offset = project_pixel(textrueOffsets);
|
||||
// vec4 project_pos = project_position(vec4(a_Position, 1.0)) + vec4(a_Size / 2.,-a_Size /2.,0.,0.);
|
||||
// gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy+offset),project_pos.z,project_pos.w));\
|
||||
//
|
||||
if(u_CoordinateSystem == COORDINATE_SYSTEM_P20_2) { // gaode2.x
|
||||
// vec2 offset = project_pixel((u_offsets));
|
||||
gl_Position = u_Mvp * vec4(a_Position.xy + offset, a_Position.z, 1.0);
|
||||
} else { // else
|
||||
// vec2 offset = project_pixel(u_offsets);
|
||||
vec4 project_pos = project_position(vec4(a_Position, 1.0)) + vec4(a_Size / 2.,-a_Size /2.,0.,0.);
|
||||
gl_Position = project_common_position_to_clipspace(vec4(vec2(project_pos.xy+offset),project_pos.z,project_pos.w));
|
||||
}
|
||||
|
||||
gl_PointSize = a_Size * 2.0 * u_DevicePixelRatio;
|
||||
setPickingColor(a_PickingColor);
|
||||
}
|
|
@ -95,6 +95,14 @@ export default class GaodeMapComponent extends React.Component {
|
|||
scene.on('loaded', () => {
|
||||
scene.addLayer(layer);
|
||||
// scene.addLayer(trufCircle);
|
||||
// scene.on('movestart', e => console.log('e', e))
|
||||
// scene.on('mapmove', e => console.log('e', e))
|
||||
// scene.on('moveend', e => console.log('e', e))
|
||||
|
||||
// scene.on('zoomstart', e => console.log('e', e))
|
||||
// scene.on('zoomchange', e => console.log('e', e))
|
||||
// scene.on('zoomend', e => console.log('e', e))
|
||||
// scene.on('mousedown', e => console.log('e', e))
|
||||
});
|
||||
let c = 1;
|
||||
layer.on('click', () => {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
// @ts-ignore
|
||||
import { PointLayer, Scene, LineLayer, PolygonLayer } from '@antv/l7';
|
||||
import { GaodeMap, GaodeMapV2, Mapbox } from '@antv/l7-maps';
|
||||
import * as React from 'react';
|
||||
|
||||
export default class SimplePoint extends React.Component {
|
||||
// @ts-ignore
|
||||
private scene: Scene;
|
||||
|
||||
public componentWillUnmount() {
|
||||
this.scene.destroy();
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
map: new GaodeMap({
|
||||
center: [121.107846, 30.267069],
|
||||
pitch: 0,
|
||||
// style: 'dark',
|
||||
zoom: 15,
|
||||
}),
|
||||
});
|
||||
// normal = 'normal',
|
||||
// additive = 'additive',
|
||||
// subtractive = 'subtractive',
|
||||
// min = 'min',
|
||||
// max = 'max',
|
||||
// none = 'none',
|
||||
// blend: 'additive'
|
||||
|
||||
let layer = new PointLayer({ blend: 'additive' })
|
||||
.source(
|
||||
[
|
||||
{
|
||||
lng: 121.107846,
|
||||
lat: 30.267069,
|
||||
},
|
||||
{
|
||||
lng: 121.1,
|
||||
lat: 30.267069,
|
||||
},
|
||||
],
|
||||
{
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
},
|
||||
)
|
||||
.shape('simple')
|
||||
.color('#800')
|
||||
.size(50)
|
||||
.style({
|
||||
stroke: '#f00',
|
||||
strokeOpacity: 0.5,
|
||||
strokeWidth: 10,
|
||||
opacity: 0.5,
|
||||
})
|
||||
.active({ color: '#00f' });
|
||||
|
||||
this.scene = scene;
|
||||
|
||||
scene.on('loaded', () => {
|
||||
scene.addLayer(layer);
|
||||
});
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
id="map"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@ import DestroyClear from './components/destroyClear'
|
|||
import PlaneLine from './components/planeLine'
|
||||
import Slider from './components/slider'
|
||||
import WindMap from './components/amap2demo_wind'
|
||||
import SimplePoint from './components/simplePoint';
|
||||
|
||||
// @ts-ignore
|
||||
storiesOf('地图方法', module)
|
||||
|
@ -142,3 +143,4 @@ storiesOf('地图方法', module)
|
|||
.add('DestroyClear', () => <DestroyClear/>)
|
||||
.add('PlaneLine', () => <PlaneLine/>)
|
||||
.add('Slider', () => <Slider/>)
|
||||
.add('SimplePoint', () => <SimplePoint/>)
|
||||
|
|
Loading…
Reference in New Issue