mirror of https://gitee.com/antv-l7/antv-l7
fix(layers): heatmap 3d effect
This commit is contained in:
parent
0e000f5715
commit
4c5c1a9d49
|
@ -1,55 +0,0 @@
|
|||
import { Scene } from '@l7/scene';
|
||||
import { HeatMapGridLayer } from '@l7/layers';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
style: 'light',
|
||||
pitch: 0,
|
||||
center: [116.49434030056, 39.868073421167621],
|
||||
type: 'amap',
|
||||
zoom: 16,
|
||||
});
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/c3f8bda2-081b-449d-aa9f-9413b779205b.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const layer =
|
||||
new HeatMapGridLayer({
|
||||
})
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'lng',
|
||||
y: 'lat',
|
||||
},
|
||||
transforms: [
|
||||
{
|
||||
type: 'grid',
|
||||
size: 50,
|
||||
field: 'count',
|
||||
method: 'sum',
|
||||
},
|
||||
],
|
||||
})
|
||||
.size('sum', (value) => {
|
||||
return value;
|
||||
})
|
||||
.shape('square')
|
||||
.style({
|
||||
coverage: 0.8,
|
||||
angle: 0,
|
||||
opacity: 0.6,
|
||||
})
|
||||
.color('count', [
|
||||
'#002466',
|
||||
'#105CB3',
|
||||
'#2894E0',
|
||||
'#CFF6FF',
|
||||
'#FFF5B8',
|
||||
'#FFAB5C',
|
||||
'#F27049',
|
||||
'#730D1C',
|
||||
]);
|
||||
scene.addLayer(layer);
|
||||
|
||||
|
||||
});
|
|
@ -5,7 +5,7 @@
|
|||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "grid.js",
|
||||
"filename": "world3d.js",
|
||||
"title": "网格热力图"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -16,7 +16,9 @@ fetch('https://gw.alipayobjects.com/os/basement_prod/337ddbb7-aa3f-4679-ab60-d64
|
|||
new HeatMapLayer({
|
||||
})
|
||||
.source(data)
|
||||
.size('capacity', [0, 1]) // weight映射通道
|
||||
.size('capacity', [0, 1])
|
||||
.shape('heatmap')
|
||||
// weight映射通道
|
||||
.style({
|
||||
intensity: 10,
|
||||
radius: 5,
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import { Scene } from '@l7/scene';
|
||||
import { HeatMapLayer } from '@l7/layers';
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
style: 'dark',
|
||||
pitch: 0,
|
||||
center: [116.49434030056, 39.868073421167621],
|
||||
type: 'mapbox',
|
||||
zoom: 3,
|
||||
});
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/337ddbb7-aa3f-4679-ab60-d64359241955.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const layer =
|
||||
new HeatMapLayer({
|
||||
})
|
||||
.source(data)
|
||||
.size('capacity', [0, 1])
|
||||
.shape('heatmap3D')
|
||||
// weight映射通道
|
||||
.style({
|
||||
intensity: 10,
|
||||
radius: 5,
|
||||
opacity: 1.0,
|
||||
rampColors: {
|
||||
colors: [
|
||||
'#2E8AE6',
|
||||
'#69D1AB',
|
||||
'#DAF291',
|
||||
'#FFD591',
|
||||
'#FF7A45',
|
||||
'#CF1D49',
|
||||
],
|
||||
positions: [0,0.2, 0.4, 0.6, 0.8, 1.0],
|
||||
},
|
||||
});
|
||||
scene.addLayer(layer);
|
||||
|
||||
|
||||
});
|
|
@ -13,6 +13,11 @@
|
|||
"filename": "world.js",
|
||||
"title": "气泡图 - 电厂装机量"
|
||||
|
||||
},
|
||||
{
|
||||
"filename": "text.js",
|
||||
"title": "文本"
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import { Scene } from '@l7/scene';
|
||||
import { PointLayer, PointImageLayer } from '@l7/layers'
|
||||
const scene = new Scene({
|
||||
id: 'map',
|
||||
pitch: 0,
|
||||
type: 'amap',
|
||||
style: 'light',
|
||||
center: [121.40, 31.258134],
|
||||
zoom: 15,
|
||||
minZoom: 10
|
||||
});
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9140d288ae.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const pointLayer =
|
||||
new PointLayer({
|
||||
})
|
||||
.source(data, {
|
||||
parser: {
|
||||
type: 'json',
|
||||
x: 'longitude',
|
||||
y: 'latitude'
|
||||
}
|
||||
}).shape('circle')
|
||||
.size('unit_price', [5, 25])
|
||||
.color('#5B8FF9')
|
||||
.label('name')
|
||||
.style({
|
||||
opacity: 0.3,
|
||||
strokeWidth: 1,
|
||||
strokeColor: "#5B8FF9",
|
||||
|
||||
})
|
||||
|
||||
scene.addLayer(pointLayer);
|
||||
console.log(pointLayer);
|
||||
|
||||
});
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ fetch('https://gw.alipayobjects.com/os/basement_prod/893d1d5f-11d9-45f3-8322-ee9
|
|||
}
|
||||
})
|
||||
.shape('name', ['00', '01','02'])
|
||||
.size('unit_price', [30, 100])
|
||||
.size('unit_price', [5, 15])
|
||||
scene.addLayer(imageLayer);
|
||||
});
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ export interface ILayer {
|
|||
size(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
color(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
shape(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
label(field: StyleAttrField, value?: StyleAttributeOption): ILayer;
|
||||
// pattern(field: string, value: StyleAttributeOption): ILayer;
|
||||
// filter(field: string, value: StyleAttributeOption): ILayer;
|
||||
// active(option: ActiveOption): ILayer;
|
||||
|
|
|
@ -130,6 +130,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
@lazyInject(TYPES.ILayerService)
|
||||
protected readonly layerService: ILayerService;
|
||||
|
||||
protected enodeOptions: {
|
||||
[type: string]: {
|
||||
field: StyleAttributeField;
|
||||
values?: StyleAttributeOption;
|
||||
};
|
||||
} = {};
|
||||
|
||||
private encodedData: IEncodeFeature[];
|
||||
|
||||
private configSchema: object;
|
||||
|
@ -142,12 +149,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
>;
|
||||
private scaleOptions: IScaleOptions = {};
|
||||
|
||||
private enodeOptions: {
|
||||
[type: string]: {
|
||||
field: string;
|
||||
};
|
||||
};
|
||||
|
||||
@lazyInject(TYPES.IInteractionService)
|
||||
private readonly interactionService: IInteractionService;
|
||||
|
||||
|
@ -236,6 +237,10 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
values?: StyleAttributeOption,
|
||||
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
||||
) {
|
||||
this.enodeOptions.shape = {
|
||||
field,
|
||||
values,
|
||||
};
|
||||
this.styleAttributeService.updateStyleAttribute(
|
||||
'shape',
|
||||
{
|
||||
|
@ -254,6 +259,29 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> extends EventEmitter
|
|||
);
|
||||
return this;
|
||||
}
|
||||
public label(
|
||||
field: StyleAttributeField,
|
||||
values?: StyleAttributeOption,
|
||||
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
||||
) {
|
||||
this.styleAttributeService.updateStyleAttribute(
|
||||
'label',
|
||||
{
|
||||
// @ts-ignore
|
||||
scale: {
|
||||
field,
|
||||
...this.splitValuesAndCallbackInAttribute(
|
||||
// @ts-ignore
|
||||
values,
|
||||
null,
|
||||
),
|
||||
},
|
||||
},
|
||||
// @ts-ignore
|
||||
updateOptions,
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
public source(data: any, options?: ISourceCFG): ILayer {
|
||||
this.sourceOption = {
|
||||
|
|
|
@ -56,7 +56,8 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
|||
|
||||
protected renderModels() {
|
||||
const { clear, useFramebuffer } = this.rendererService;
|
||||
|
||||
const shapeAttr = this.styleAttributeService.getLayerStyleAttribute('shape');
|
||||
const shapeType = shapeAttr?.scale?.field || 'heatmap';
|
||||
useFramebuffer(this.heatmapFramerBuffer, () => {
|
||||
clear({
|
||||
color: [0, 0, 0, 0],
|
||||
|
@ -66,17 +67,19 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
|||
});
|
||||
this.drawIntensityMode();
|
||||
});
|
||||
this.draw3DHeatMap();
|
||||
// this.draw3DHeatMap();
|
||||
shapeType === 'heatmap' ? this.drawColorMode(): this.draw3DHeatMap();
|
||||
// this.drawIntensityMode();
|
||||
return this;
|
||||
}
|
||||
|
||||
protected buildModels() {
|
||||
const shapeAttr = this.styleAttributeService.getLayerStyleAttribute('shape');
|
||||
const shapeType = shapeAttr?.scale?.field || 'heatmap';
|
||||
this.registerBuiltinAttributes(this);
|
||||
this.intensityModel = this.buildHeatMapIntensity();
|
||||
this.models = [this.intensityModel];
|
||||
// this.colorModel = this.buildHeatmapColor();
|
||||
this.colorModel = this.build3dHeatMap();
|
||||
this.colorModel = shapeType === 'heatmap' ? this.buildHeatmapColor(): this.build3dHeatMap();
|
||||
this.models.push(this.colorModel);
|
||||
const { rampColors } = this.getStyleOptions();
|
||||
const imageData = generateColorRamp(rampColors as IColorRamp);
|
||||
|
@ -95,8 +98,8 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
|||
height,
|
||||
wrapS: gl.CLAMP_TO_EDGE,
|
||||
wrapT: gl.CLAMP_TO_EDGE,
|
||||
min: gl.NEAREST,
|
||||
mag: gl.NEAREST,
|
||||
min: gl.LINEAR,
|
||||
mag: gl.LINEAR,
|
||||
}),
|
||||
});
|
||||
|
||||
|
@ -175,9 +178,9 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
|||
enable: true,
|
||||
func: {
|
||||
srcRGB: gl.ONE,
|
||||
srcAlpha: 1,
|
||||
srcAlpha: gl.ONE_MINUS_SRC_ALPHA,
|
||||
dstRGB: gl.ONE,
|
||||
dstAlpha: 1,
|
||||
dstAlpha: gl.ONE_MINUS_SRC_ALPHA,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -280,7 +283,7 @@ export default class HeatMapLayer extends BaseLayer<IHeatMapLayerStyleOptions> {
|
|||
private build3dHeatMap() {
|
||||
const { getViewportSize } = this.rendererService;
|
||||
const { width, height } = getViewportSize();
|
||||
const triangulation = heatMap3DTriangulation(width / 4.0, height / 4.0);
|
||||
const triangulation = heatMap3DTriangulation(width / 2.0, height / 2.0);
|
||||
this.shaderModuleService.registerModule('heatmap3dColor', {
|
||||
vs: heatmap3DVert,
|
||||
fs: heatmap3DFrag,
|
||||
|
|
|
@ -5,14 +5,13 @@ varying vec2 v_texCoord;
|
|||
varying float v_intensity;
|
||||
|
||||
void main(){
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
vec2 ramp_pos = vec2(
|
||||
fract(16.0 * (1.0 - v_intensity)),
|
||||
floor(16.0 * (1.0 - v_intensity)) / 16.0);
|
||||
// vec4 color = texture2D(u_colorTexture,vec2(0.5,1.0-intensity));
|
||||
vec4 color = texture2D(u_colorTexture,ramp_pos);
|
||||
gl_FragColor = color;
|
||||
// gl_FragColor.a = color.a * smoothstep(0.0, 0.01, v_intensity) * u_opacity;
|
||||
// gl_FragColor.a = 0.2;
|
||||
|
||||
gl_FragColor.a = color.a * smoothstep(0.1,0.2,intensity)* u_opacity;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,6 @@ void main() {
|
|||
|
||||
v_intensity = texture2D(u_texture, v_texCoord).r;
|
||||
fh = toBezier(v_intensity, b).y;
|
||||
gl_Position = project_common_position_to_clipspace(vec4(position.xy, v_intensity * 50., 1.0));
|
||||
gl_Position = project_common_position_to_clipspace(vec4(position.xy, fh * 50., 1.0));
|
||||
|
||||
}
|
||||
|
|
|
@ -2,15 +2,16 @@ uniform sampler2D u_texture;
|
|||
uniform sampler2D u_colorTexture;
|
||||
uniform float u_opacity;
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_intensity;
|
||||
|
||||
void main(){
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
vec2 ramp_pos = vec2(
|
||||
fract(16.0 * (1.0 - intensity)),
|
||||
floor(16.0 * (1.0 - intensity)) / 16.0);
|
||||
// vec4 color = texture2D(u_colorTexture,vec2(0.5,1.0-intensity));
|
||||
vec4 color = texture2D(u_colorTexture,ramp_pos);
|
||||
gl_FragColor = color;
|
||||
gl_FragColor.a = color.a * smoothstep(0.,0.01,intensity) * u_opacity;
|
||||
gl_FragColor.a = color.a * smoothstep(0.,0.05,intensity) * u_opacity;
|
||||
|
||||
}
|
||||
|
|
|
@ -3,8 +3,9 @@ attribute vec3 a_Position;
|
|||
attribute vec2 a_Uv;
|
||||
uniform sampler2D u_texture;
|
||||
varying vec2 v_texCoord;
|
||||
varying float v_intensity;
|
||||
void main() {
|
||||
v_texCoord = a_Uv;
|
||||
float intensity = texture2D(u_texture, v_texCoord).r;
|
||||
gl_Position = vec4(a_Position.xy,intensity -0.5, 1.);
|
||||
v_intensity = texture2D(u_texture, v_texCoord).r;
|
||||
gl_Position = vec4(a_Position.xy, 0, 1.);
|
||||
}
|
||||
|
|
|
@ -93,14 +93,21 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
if (scales.some((scale) => scale.type === StyleScaleType.VARIABLE)) {
|
||||
attributeScale.type = StyleScaleType.VARIABLE;
|
||||
scales.forEach((scale) => {
|
||||
// 如果设置了回调干啥这不需要设置让range
|
||||
if (!attributeScale.callback && attributeScale.values.length > 0) {
|
||||
scale.scale.range(attributeScale.values);
|
||||
// 如果设置了回调, 这不需要设置让range
|
||||
if (!attributeScale.callback) {
|
||||
if(attributeScale.values) {
|
||||
scale.scale.range(attributeScale.values);
|
||||
} else if(scale.option?.type==='cat') {
|
||||
|
||||
// 如果没有设置初值且 类型为cat,range ==domain;
|
||||
scale.scale.range(scale.option.domain);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 设置attribute 常量值 常量直接在value取值
|
||||
|
||||
attributeScale.type = StyleScaleType.CONSTANT;
|
||||
attributeScale.values = scales.map((scale, index) => {
|
||||
return scale.scale(attributeScale.names[index]);
|
||||
});
|
||||
|
@ -166,7 +173,7 @@ export default class FeatureScalePlugin implements ILayerPlugin {
|
|||
type: StyleScaleType.VARIABLE,
|
||||
option: scaleOption,
|
||||
};
|
||||
if (!data || !data.length) {
|
||||
if (!data || !data.length) {
|
||||
|
||||
if (scaleOption && scaleOption.type) {
|
||||
styleScale.scale = this.createDefaultScale(scaleOption);
|
||||
|
|
|
@ -164,14 +164,14 @@ export default class TextLayer extends BaseLayer<IPointTextLayerStyleOptions> {
|
|||
});
|
||||
}
|
||||
|
||||
private iniTextFont() {
|
||||
private initTextFont() {
|
||||
const { fontWeight = 'normal', fontFamily } = this.getStyleOptions();
|
||||
const data = this.getEncodedData();
|
||||
const characterSet: string[] = [];
|
||||
data.forEach((item: IEncodeFeature) => {
|
||||
let { text = '' } = item;
|
||||
text = text.toString();
|
||||
for (const char of text) {
|
||||
let { shape = '' } = item;
|
||||
shape = shape.toString();
|
||||
for (const char of shape) {
|
||||
// 去重
|
||||
if (characterSet.indexOf(char) === -1) {
|
||||
characterSet.push(char);
|
||||
|
|
|
@ -46,7 +46,7 @@ export default class ReglRendererService implements IRendererService {
|
|||
alpha: true,
|
||||
// use TAA instead of MSAA
|
||||
// @see https://www.khronos.org/registry/webgl/specs/1.0/#5.2.1
|
||||
antialias: false,
|
||||
antialias: true,
|
||||
premultipliedAlpha: true,
|
||||
},
|
||||
// TODO: use extensions
|
||||
|
|
Loading…
Reference in New Issue