mirror of https://gitee.com/antv-l7/antv-l7
feat: 栅格rampcolor 支持cat、quantize、custom 着色方式 (#1554)
* fix: circle meter size && remove unuse code file * docs: add demo * feat: 新增attribute diff 校验 * fix: lint error * feat: 增强 rampcolor 类型 * fix: rampcolor domain * docs: rampcolor 优化 * fix: 纬度范围大于85 的情况 * fix: rampcolor quantize * docs: 更新demo
This commit is contained in:
parent
5f489e55c8
commit
ba7c9a0c1d
|
@ -0,0 +1,98 @@
|
||||||
|
import type { ChoroplethLayerProps,IconImageLayerProps } from '@antv/larkmap';
|
||||||
|
import { ChoroplethLayer, LarkMap,LegendRamp,CustomControl,IconImageLayer} from '@antv/larkmap';
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
;
|
||||||
|
const layerOptions: Omit<ChoroplethLayerProps, 'source'> = {
|
||||||
|
autoFit: true,
|
||||||
|
fillColor: {
|
||||||
|
field: '达峰进度条',
|
||||||
|
value: [
|
||||||
|
'#fee5d9',
|
||||||
|
'#fc9272',
|
||||||
|
'#fb6a4a',
|
||||||
|
'#de2d26',
|
||||||
|
'#a50f15',
|
||||||
|
],
|
||||||
|
scale: {
|
||||||
|
type: 'quantize',
|
||||||
|
domain: [0, 100],
|
||||||
|
unknown: '#f7f4f9',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
opacity: 1,
|
||||||
|
strokeColor: '#ddd',
|
||||||
|
lineWidth: 1,
|
||||||
|
state: {
|
||||||
|
active: { strokeColor: 'green', lineWidth: 1.5, lineOpacity: 0.8 },
|
||||||
|
select: { strokeColor: 'red', lineWidth: 1.5, lineOpacity: 0.8 },
|
||||||
|
},
|
||||||
|
|
||||||
|
label: {
|
||||||
|
field: 'name',
|
||||||
|
visible: false,
|
||||||
|
style: {
|
||||||
|
textAllowOverlap: true,
|
||||||
|
fill: '#333', fontSize: 10, stroke: '#aaa', strokeWidth: 1 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const [update,setUpdate] = useState<number>()
|
||||||
|
const [options, setOptions] = useState(layerOptions);
|
||||||
|
const [source, setSource] = useState({
|
||||||
|
data: { type: 'FeatureCollection', features: [] },
|
||||||
|
parser: {
|
||||||
|
type: 'json',
|
||||||
|
geometry: 'geometry',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const [labelsource, setLabelsource] = useState({
|
||||||
|
data: { type: 'FeatureCollection', features: [] },
|
||||||
|
parser: {
|
||||||
|
type: 'json',
|
||||||
|
geometry: 'centroid',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch('https://mdn.alipayobjects.com/afts/file/A*7HqFT7he7KoAAAAAAAAAAAAADrd2AQ/12.20%20%E5%90%84%E7%9C%81%E4%BB%BD%E9%A6%96%E8%BD%AE%E6%84%9F%E6%9F%93%E9%AB%98%E5%B3%B0%E6%9C%9F%E9%A2%84%E6%B5%8B.json')
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data: any) => {
|
||||||
|
setSource((prevState) => ({ ...prevState, data }));
|
||||||
|
setLabelsource((prevState) => ({ ...prevState, data }))
|
||||||
|
});
|
||||||
|
setInterval(()=>{
|
||||||
|
setUpdate(Math.random())
|
||||||
|
},2000)
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<LarkMap mapType="Gaode" style={{ height: '70vh' }}>
|
||||||
|
<ChoroplethLayer {...options} source={source}
|
||||||
|
onDataUpdate={()=>{
|
||||||
|
console.log('onDataUpdate')
|
||||||
|
}} />
|
||||||
|
<CustomControl
|
||||||
|
position="bottomright"
|
||||||
|
className="custom-control-class"
|
||||||
|
style={{ background: '#fff', borderRadius: 4, overflow: 'hidden', padding: 16 }}
|
||||||
|
>
|
||||||
|
<h3>达峰进度</h3>
|
||||||
|
<LegendRamp
|
||||||
|
lableUnit="%"
|
||||||
|
labels={[ 0,20, 40, 60, 80, 100]}
|
||||||
|
colors={[
|
||||||
|
'#fee5d9',
|
||||||
|
'#fc9272',
|
||||||
|
'#fb6a4a',
|
||||||
|
'#de2d26',
|
||||||
|
'#a50f15',
|
||||||
|
]}
|
||||||
|
barWidth={300}
|
||||||
|
/>
|
||||||
|
</CustomControl>
|
||||||
|
|
||||||
|
</LarkMap>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
### 区域图
|
||||||
|
<code src="./demos/polygon.tsx"></code>
|
File diff suppressed because it is too large
Load Diff
|
@ -1,2 +1,2 @@
|
||||||
### polygon
|
### select
|
||||||
<code src="./demos/select.tsx"></code>
|
<code src="./demos/select.tsx"></code>
|
|
@ -54,13 +54,9 @@ export default () => {
|
||||||
rampColors: {
|
rampColors: {
|
||||||
colors: [
|
colors: [
|
||||||
'#FF4818',
|
'#FF4818',
|
||||||
'#F7B74A',
|
|
||||||
'#FFF598',
|
|
||||||
'#91EABC',
|
|
||||||
'#2EA9A1',
|
|
||||||
'#206C7C',
|
'#206C7C',
|
||||||
],
|
],
|
||||||
weights: [0.1, 0.1, 0.1, 0.1, 0.1, 0.5],
|
positions: [0., 1.0],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
### 疫情达峰
|
||||||
|
<code src="./map.tsx"></code>
|
|
@ -0,0 +1,112 @@
|
||||||
|
import { PolygonLayer, LineLayer, PointLayer, Scene, Source } from '@antv/l7';
|
||||||
|
import { GaodeMap } from '@antv/l7-maps';
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
useEffect(() => {
|
||||||
|
fetch(
|
||||||
|
'https://mdn.alipayobjects.com/afts/file/A*7HqFT7he7KoAAAAAAAAAAAAADrd2AQ/12.20%20%E5%90%84%E7%9C%81%E4%BB%BD%E9%A6%96%E8%BD%AE%E6%84%9F%E6%9F%93%E9%AB%98%E5%B3%B0%E6%9C%9F%E9%A2%84%E6%B5%8B.json',
|
||||||
|
)
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => {
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
map: new GaodeMap({
|
||||||
|
pitch: 0,
|
||||||
|
style: 'dark',
|
||||||
|
center: [112, 37.8],
|
||||||
|
zoom: 3,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const chinaSource = new Source(data, {
|
||||||
|
parser: {
|
||||||
|
type: 'json',
|
||||||
|
geometry: 'geometry',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const layer = new PolygonLayer({
|
||||||
|
autoFit: true,
|
||||||
|
})
|
||||||
|
.source(chinaSource)
|
||||||
|
.scale('达峰进度条', {
|
||||||
|
type: 'quantize',
|
||||||
|
domain: [0, 100],
|
||||||
|
unknown: '#f7f4f9',
|
||||||
|
})
|
||||||
|
.shape('fill')
|
||||||
|
.color('达峰进度条', [
|
||||||
|
'#fee5d9',
|
||||||
|
'#fc9272',
|
||||||
|
'#fb6a4a',
|
||||||
|
'#de2d26',
|
||||||
|
'#a50f15',
|
||||||
|
])
|
||||||
|
.style({
|
||||||
|
opacity: 1,
|
||||||
|
});
|
||||||
|
const linelayer = new LineLayer({})
|
||||||
|
.source(chinaSource)
|
||||||
|
.shape('line')
|
||||||
|
.color('#ddd')
|
||||||
|
.style({
|
||||||
|
opacity: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
layer.on('inited', () => {
|
||||||
|
console.log(layer.getLegend('color'));
|
||||||
|
});
|
||||||
|
const pointSource = new Source(data, {
|
||||||
|
parser: {
|
||||||
|
type: 'json',
|
||||||
|
geometry: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const nameLayer = new PointLayer()
|
||||||
|
.source(pointSource)
|
||||||
|
.size(12)
|
||||||
|
.shape('name', 'text')
|
||||||
|
.color('#525252')
|
||||||
|
.style({
|
||||||
|
textAnchor: 'top', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
|
||||||
|
textOffset: [0, 0], // 文本相对锚点的偏移量 [水平, 垂直]
|
||||||
|
// spacing: 2, // 字符间距
|
||||||
|
// padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||||
|
stroke: '#fff', // 描边颜色
|
||||||
|
strokeWidth: 1, // 描边宽度
|
||||||
|
strokeOpacity: 1.0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const textLayer = new PointLayer()
|
||||||
|
.source(pointSource)
|
||||||
|
.size(14)
|
||||||
|
.shape('达峰进度条', 'text')
|
||||||
|
.color('#e7298a')
|
||||||
|
.style({
|
||||||
|
textAnchor: 'bottom', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
|
||||||
|
textOffset: [0, -20], // 文本相对锚点的偏移量 [水平, 垂直]
|
||||||
|
// spacing: 2, // 字符间距
|
||||||
|
// padding: [ 1, 1 ], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
|
||||||
|
stroke: '#fff', // 描边颜色
|
||||||
|
strokeWidth: 2, // 描边宽度
|
||||||
|
strokeOpacity: 1.0,
|
||||||
|
fontWeight: 800,
|
||||||
|
textAllowOverlap: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
scene.addLayer(layer);
|
||||||
|
scene.addLayer(linelayer);
|
||||||
|
scene.addLayer(nameLayer);
|
||||||
|
scene.addLayer(textLayer);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="map"
|
||||||
|
style={{
|
||||||
|
height: '100vh',
|
||||||
|
position: 'relative',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -42,7 +42,7 @@ export default () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.style({
|
.style({
|
||||||
opacity: 0.8,
|
opacity: 1.0,
|
||||||
clampLow: false,
|
clampLow: false,
|
||||||
clampHigh: false,
|
clampHigh: false,
|
||||||
domain: [100, 8000],
|
domain: [100, 8000],
|
||||||
|
|
|
@ -59,10 +59,12 @@ export default () => {
|
||||||
.style({
|
.style({
|
||||||
clampLow: false,
|
clampLow: false,
|
||||||
clampHigh: false,
|
clampHigh: false,
|
||||||
domain: [ 0, 90 ],
|
domain: [ 1, 90 ],
|
||||||
nodataValue: 0,
|
nodataValue: 0,
|
||||||
rampColors: {
|
rampColors: {
|
||||||
colors: [ 'rgba(92,58,16,0)', 'rgba(92,58,16,0)', '#fabd08', '#f1e93f', '#f1ff8f', '#fcfff7' ],
|
type:'quantize',
|
||||||
|
colors:['#1b9e77','#d95f02','#7570b3','#e7298a','#66a61e','#e6ab02'],
|
||||||
|
// colors: [ 'rgba(92,58,16,0)', 'rgba(92,58,16,0)', '#fabd08', '#f1e93f', '#f1ff8f', '#fcfff7' ],
|
||||||
positions: [ 0, 0.05, 0.1, 0.25, 0.5, 1.0 ]
|
positions: [ 0, 0.05, 0.1, 0.25, 0.5, 1.0 ]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { RasterLayer, Scene } from '@antv/l7';
|
import { RasterLayer, Scene } from '@antv/l7';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { GaodeMap } from '@antv/l7-maps';
|
import { GaodeMap,Map } from '@antv/l7-maps';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import * as GeoTIFF from 'geotiff';
|
import * as GeoTIFF from 'geotiff';
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ export default () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
id: 'map',
|
id: 'map',
|
||||||
map: new GaodeMap({
|
map: new Map({
|
||||||
center: [121.268, 30.3628],
|
center: [121.268, 30.3628],
|
||||||
zoom: 3,
|
zoom: 3,
|
||||||
}),
|
}),
|
||||||
|
@ -42,20 +42,14 @@ export default () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.style({
|
.style({
|
||||||
opacity: 0.8,
|
opacity: 1,
|
||||||
clampLow: false,
|
clampLow: false,
|
||||||
clampHigh: false,
|
clampHigh: false,
|
||||||
domain: [100, 8000],
|
domain: [0, 10000],
|
||||||
rampColors: {
|
rampColors: {
|
||||||
colors: [
|
type:'custom',
|
||||||
'#FF4818',
|
colors: ['#b2182b','#d6604d','#f4a582','#fddbc7','#f7f7f7','#d1e5f0','#92c5de','#4393c3','#2166ac'],
|
||||||
'#F7B74A',
|
positions: [0, 50, 200, 500, 2000, 3000, 4000, 5000, 8000,10000],
|
||||||
'#FFF598',
|
|
||||||
'#91EABC',
|
|
||||||
'#2EA9A1',
|
|
||||||
'#206C7C',
|
|
||||||
].reverse(),
|
|
||||||
positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0],
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,59 +2,36 @@ import { RasterLayer, Scene, Source } from '@antv/l7';
|
||||||
import { Map } from '@antv/l7-maps';
|
import { Map } from '@antv/l7-maps';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import * as GeoTIFF from 'geotiff';
|
import * as GeoTIFF from 'geotiff';
|
||||||
|
// https://gee-community-catalog.org/projects/esrilc2020/
|
||||||
const colorList = [
|
const colorList = [
|
||||||
'#419bdf', // Water
|
'#419bdf', // Water
|
||||||
'#419bdf',
|
|
||||||
|
|
||||||
'#397d49', // Tree
|
'#358221', // Tree
|
||||||
'#397d49',
|
|
||||||
|
|
||||||
'#88b053', // Grass
|
'#88b053', // Grass
|
||||||
'#88b053',
|
|
||||||
|
|
||||||
'#7a87c6', // vegetation
|
'#7a87c6', // vegetation
|
||||||
'#7a87c6',
|
|
||||||
|
|
||||||
'#e49635', // Crops
|
'#e49635', // Crops
|
||||||
'#e49635',
|
|
||||||
|
|
||||||
'#dfc35a', // shrub
|
'#dfc35a', // shrub
|
||||||
'#dfc35a',
|
|
||||||
|
|
||||||
'#c4281b', // Built Area
|
|
||||||
'#c4281b',
|
|
||||||
|
|
||||||
'#a59b8f', // Bare ground
|
'#ED022A', // Built Area
|
||||||
'#a59b8f',
|
|
||||||
|
|
||||||
'#a8ebff', // Snow
|
|
||||||
'#a8ebff',
|
|
||||||
|
|
||||||
'#616161', // Clouds
|
'#EDE9E4', // Bare ground
|
||||||
'#616161',
|
|
||||||
|
|
||||||
|
'#F2FAFF', // Snow
|
||||||
|
|
||||||
|
'#C8C8C8', // Clouds
|
||||||
];
|
];
|
||||||
const positions = [
|
const positions = [
|
||||||
0.0,
|
1,2,3,4,5,6,7,8,9,10,11,
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0.2,
|
|
||||||
0.2,
|
|
||||||
0.3,
|
|
||||||
0.3,
|
|
||||||
0.4,
|
|
||||||
0.4,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0.6,
|
|
||||||
0.6,
|
|
||||||
0.7,
|
|
||||||
0.7,
|
|
||||||
0.8,
|
|
||||||
0.8,
|
|
||||||
0.9,
|
|
||||||
0.9,
|
|
||||||
1.0,
|
|
||||||
];
|
];
|
||||||
export default () => {
|
export default () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -93,6 +70,7 @@ export default () => {
|
||||||
const width = image.getWidth();
|
const width = image.getWidth();
|
||||||
const height = image.getHeight();
|
const height = image.getHeight();
|
||||||
const values = await image.readRasters();
|
const values = await image.readRasters();
|
||||||
|
console.log(values)
|
||||||
return { rasterData: values[0], width, height };
|
return { rasterData: values[0], width, height };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -100,13 +78,13 @@ export default () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
layer.source(tileSource).style({
|
layer.source(tileSource).style({
|
||||||
domain: [0.001, 11.001],
|
// domain: [0, 255],
|
||||||
clampLow: false,
|
clampLow: false,
|
||||||
rampColors: {
|
rampColors: {
|
||||||
|
type:"cat",
|
||||||
colors: colorList,
|
colors: colorList,
|
||||||
positions,
|
positions,
|
||||||
// colors: ['#f00', '#f00'],
|
|
||||||
// positions: [0, 1]
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { IColorRamp } from '@antv/l7-utils';
|
import { IColorRamp } from '@antv/l7-utils';
|
||||||
import { ITexture2D } from '../renderer/ITexture2D';
|
import { ITexture2D } from '../renderer/ITexture2D';
|
||||||
export interface ITextureService {
|
export interface ITextureService {
|
||||||
setColorTexture(texture: ITexture2D,colorRamp: IColorRamp):void;
|
setColorTexture(texture: ITexture2D,colorRamp: IColorRamp,domain?:[number,number]):void;
|
||||||
getColorTexture(colorRamp: IColorRamp): ITexture2D
|
getColorTexture(colorRamp: IColorRamp, domain?:[number,number]): ITexture2D
|
||||||
destroy():void;
|
destroy():void;
|
||||||
|
|
||||||
}
|
}
|
|
@ -406,7 +406,7 @@ export interface ILayer {
|
||||||
field: StyleAttributeField,
|
field: StyleAttributeField,
|
||||||
values?: StyleAttributeOption,
|
values?: StyleAttributeOption,
|
||||||
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
||||||
): void;
|
): boolean;
|
||||||
setLayerPickService(layerPickService:ILayerPickService):void;
|
setLayerPickService(layerPickService:ILayerPickService):void;
|
||||||
init(): Promise<void>;
|
init(): Promise<void>;
|
||||||
scale(field: string | number | IScaleOptions, cfg?: IScale): ILayer;
|
scale(field: string | number | IScaleOptions, cfg?: IScale): ILayer;
|
||||||
|
|
|
@ -94,6 +94,7 @@ export interface ITexture2DInitializationOptions {
|
||||||
|
|
||||||
export interface ITexture2D {
|
export interface ITexture2D {
|
||||||
get(): unknown;
|
get(): unknown;
|
||||||
|
getSize():[number,number];
|
||||||
update(options: any): void;
|
update(options: any): void;
|
||||||
bind(): void;
|
bind(): void;
|
||||||
resize(options: { width: number; height: number }): void;
|
resize(options: { width: number; height: number }): void;
|
||||||
|
|
|
@ -57,7 +57,7 @@ import Source from '@antv/l7-source';
|
||||||
import { encodePickingColor, WorkerSourceMap } from '@antv/l7-utils';
|
import { encodePickingColor, WorkerSourceMap } from '@antv/l7-utils';
|
||||||
import { EventEmitter } from 'eventemitter3';
|
import { EventEmitter } from 'eventemitter3';
|
||||||
import { Container } from 'inversify';
|
import { Container } from 'inversify';
|
||||||
import { isFunction, isObject, isUndefined } from 'lodash';
|
import { isEqual, isFunction, isObject, isUndefined } from 'lodash';
|
||||||
import { BlendTypes } from '../utils/blend';
|
import { BlendTypes } from '../utils/blend';
|
||||||
import { styleDataMapping } from '../utils/dataMappingStyle';
|
import { styleDataMapping } from '../utils/dataMappingStyle';
|
||||||
import { calculateData } from '../utils/layerData';
|
import { calculateData } from '../utils/layerData';
|
||||||
|
@ -140,7 +140,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
||||||
// 每个 Layer 都有一个
|
// 每个 Layer 都有一个
|
||||||
public multiPassRenderer: IMultiPassRenderer;
|
public multiPassRenderer: IMultiPassRenderer;
|
||||||
|
|
||||||
// 注入插件集
|
// 注入插件
|
||||||
public plugins: ILayerPlugin[];
|
public plugins: ILayerPlugin[];
|
||||||
|
|
||||||
public startInit: boolean = false;
|
public startInit: boolean = false;
|
||||||
|
@ -538,8 +538,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
||||||
values?: StyleAttributeOption,
|
values?: StyleAttributeOption,
|
||||||
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
||||||
) {
|
) {
|
||||||
this.updateStyleAttribute('filter', field, values, updateOptions);
|
const flag = this.updateStyleAttribute(
|
||||||
this.dataState.dataSourceNeedUpdate = true;
|
'filter',
|
||||||
|
field,
|
||||||
|
values,
|
||||||
|
updateOptions,
|
||||||
|
);
|
||||||
|
this.dataState.dataSourceNeedUpdate = flag;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,8 +557,13 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
||||||
field,
|
field,
|
||||||
values,
|
values,
|
||||||
};
|
};
|
||||||
this.updateStyleAttribute('shape', field, values, updateOptions);
|
const flag = this.updateStyleAttribute(
|
||||||
this.dataState.dataSourceNeedUpdate = true; // 通过数据更新驱动shape 更新
|
'shape',
|
||||||
|
field,
|
||||||
|
values,
|
||||||
|
updateOptions,
|
||||||
|
);
|
||||||
|
this.dataState.dataSourceNeedUpdate = flag;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public label(
|
public label(
|
||||||
|
@ -1338,7 +1348,14 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
||||||
field: StyleAttributeField,
|
field: StyleAttributeField,
|
||||||
values?: StyleAttributeOption,
|
values?: StyleAttributeOption,
|
||||||
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
updateOptions?: Partial<IStyleAttributeUpdateOptions>,
|
||||||
) {
|
): boolean {
|
||||||
|
// encode diff
|
||||||
|
const preAttribute = this.configService.getAttributeConfig(this.id) || {};
|
||||||
|
// @ts-ignore
|
||||||
|
if (isEqual(preAttribute[type], { field, values })) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 存储 Attribute
|
// 存储 Attribute
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
|
@ -1358,6 +1375,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.startInit) {
|
if (!this.startInit) {
|
||||||
// 开始初始化执行
|
// 开始初始化执行
|
||||||
this.pendingStyleAttributes.push({
|
this.pendingStyleAttributes.push({
|
||||||
|
@ -1385,6 +1403,7 @@ export default class BaseLayer<ChildLayerStyleOptions = {}>
|
||||||
updateOptions,
|
updateOptions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLayerAttributeConfig(): Partial<ILayerAttributesOption> {
|
public getLayerAttributeConfig(): Partial<ILayerAttributesOption> {
|
||||||
|
|
|
@ -6,7 +6,14 @@ import {
|
||||||
TYPES,
|
TYPES,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
|
|
||||||
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
|
import {
|
||||||
|
generateCatRamp,
|
||||||
|
generateColorRamp,
|
||||||
|
generateCustomRamp,
|
||||||
|
generateLinearRamp,
|
||||||
|
generateQuantizeRamp,
|
||||||
|
IColorRamp,
|
||||||
|
} from '@antv/l7-utils';
|
||||||
|
|
||||||
export default class TextureService implements ITextureService {
|
export default class TextureService implements ITextureService {
|
||||||
private layer: ILayer;
|
private layer: ILayer;
|
||||||
|
@ -20,21 +27,21 @@ export default class TextureService implements ITextureService {
|
||||||
TYPES.IRendererService,
|
TYPES.IRendererService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public getColorTexture(colorRamp: IColorRamp) {
|
public getColorTexture(colorRamp: IColorRamp, domain?: [number, number]) {
|
||||||
// TODO 支持传入图片
|
// TODO 支持传入图片
|
||||||
const currentkey = this.getTextureKey(colorRamp);
|
const currentkey = this.getTextureKey(colorRamp, domain);
|
||||||
if (this.key === currentkey) {
|
if (this.key === currentkey) {
|
||||||
return this.colorTexture;
|
return this.colorTexture;
|
||||||
} else {
|
} else {
|
||||||
this.createColorTexture(colorRamp);
|
this.createColorTexture(colorRamp, domain);
|
||||||
}
|
}
|
||||||
this.key = currentkey;
|
this.key = currentkey;
|
||||||
return this.colorTexture;
|
return this.colorTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public createColorTexture(colorRamp: IColorRamp) {
|
public createColorTexture(colorRamp: IColorRamp, domain?: [number, number]) {
|
||||||
const { createTexture2D } = this.rendererService;
|
const { createTexture2D } = this.rendererService;
|
||||||
const imageData = generateColorRamp(colorRamp) as ImageData;
|
const imageData = this.getColorRampBar(colorRamp, domain) as ImageData;
|
||||||
const texture = createTexture2D({
|
const texture = createTexture2D({
|
||||||
data: imageData.data,
|
data: imageData.data,
|
||||||
width: imageData.width,
|
width: imageData.width,
|
||||||
|
@ -45,8 +52,12 @@ export default class TextureService implements ITextureService {
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setColorTexture(texture: ITexture2D, colorRamp: IColorRamp) {
|
public setColorTexture(
|
||||||
this.key = this.getTextureKey(colorRamp);
|
texture: ITexture2D,
|
||||||
|
colorRamp: IColorRamp,
|
||||||
|
domain: [number, number],
|
||||||
|
) {
|
||||||
|
this.key = this.getTextureKey(colorRamp, domain);
|
||||||
this.colorTexture = texture;
|
this.colorTexture = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +65,27 @@ export default class TextureService implements ITextureService {
|
||||||
this.colorTexture?.destroy();
|
this.colorTexture?.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTextureKey(colorRamp: IColorRamp): string {
|
private getColorRampBar(colorRamp: IColorRamp, domain?: [number, number]) {
|
||||||
return `${colorRamp.colors.join('_')}_${colorRamp.positions.join('_')}`;
|
switch (colorRamp.type) {
|
||||||
|
case 'cat':
|
||||||
|
return generateCatRamp(colorRamp);
|
||||||
|
case 'quantize':
|
||||||
|
return generateQuantizeRamp(colorRamp);
|
||||||
|
case 'custom':
|
||||||
|
return generateCustomRamp(colorRamp, domain as [number, number]);
|
||||||
|
case 'linear':
|
||||||
|
return generateLinearRamp(colorRamp, domain as [number, number]);
|
||||||
|
default:
|
||||||
|
return generateColorRamp(colorRamp) as ImageData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTextureKey(
|
||||||
|
colorRamp: IColorRamp,
|
||||||
|
domain?: [number, number],
|
||||||
|
): string {
|
||||||
|
return `${colorRamp.colors.join('_')}_${colorRamp?.positions?.join('_')}_${
|
||||||
|
colorRamp.type
|
||||||
|
}_${domain?.join('_')}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,7 @@ export default class DataMappingPlugin implements ILayerPlugin {
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
layer.dataState.dataMappingNeedUpdate = false;
|
layer.dataState.dataMappingNeedUpdate = false;
|
||||||
this.generateMaping(layer, { styleAttributeService });
|
return this.generateMaping(layer, { styleAttributeService });
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -72,7 +70,6 @@ export default class DataMappingPlugin implements ILayerPlugin {
|
||||||
return this.applyAttributeMapping(filter, record)[0];
|
return this.applyAttributeMapping(filter, record)[0];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributesToRemapping.length) {
|
if (attributesToRemapping.length) {
|
||||||
// 过滤数据
|
// 过滤数据
|
||||||
const encodeData = this.mapping(
|
const encodeData = this.mapping(
|
||||||
|
@ -83,6 +80,7 @@ export default class DataMappingPlugin implements ILayerPlugin {
|
||||||
);
|
);
|
||||||
layer.setEncodedData(encodeData);
|
layer.setEncodedData(encodeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理文本更新,更新文字形状
|
// 处理文本更新,更新文字形状
|
||||||
// layer.emit('remapping', null);
|
// layer.emit('remapping', null);
|
||||||
});
|
});
|
||||||
|
@ -96,7 +94,6 @@ export default class DataMappingPlugin implements ILayerPlugin {
|
||||||
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
|
const attributes = styleAttributeService.getLayerStyleAttributes() || [];
|
||||||
const filter = styleAttributeService.getLayerStyleAttribute('filter');
|
const filter = styleAttributeService.getLayerStyleAttribute('filter');
|
||||||
const { dataArray } = layer.getSource().data;
|
const { dataArray } = layer.getSource().data;
|
||||||
|
|
||||||
let filterData = dataArray;
|
let filterData = dataArray;
|
||||||
// 数据过滤完 再执行数据映射
|
// 数据过滤完 再执行数据映射
|
||||||
if (filter?.scale) {
|
if (filter?.scale) {
|
||||||
|
@ -111,8 +108,13 @@ export default class DataMappingPlugin implements ILayerPlugin {
|
||||||
filterData = layer.processData(filterData);
|
filterData = layer.processData(filterData);
|
||||||
const encodeData = this.mapping(layer, attributes, filterData, undefined);
|
const encodeData = this.mapping(layer, attributes, filterData, undefined);
|
||||||
layer.setEncodedData(encodeData);
|
layer.setEncodedData(encodeData);
|
||||||
|
|
||||||
|
if (dataArray.length === 0 && layer.encodeDataLength === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// 对外暴露事件
|
// 对外暴露事件
|
||||||
layer.emit('dataUpdate', null);
|
layer.emit('dataUpdate', null);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapping(
|
private mapping(
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
IModel,
|
IModel,
|
||||||
ITexture2D,
|
ITexture2D,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { generateColorRamp, getMask, IColorRamp } from '@antv/l7-utils';
|
import { getMask,getDefaultDomain } from '@antv/l7-utils';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { IRasterLayerStyleOptions } from '../../core/interface';
|
import { IRasterLayerStyleOptions } from '../../core/interface';
|
||||||
import { RasterImageTriangulation } from '../../core/triangulation';
|
import { RasterImageTriangulation } from '../../core/triangulation';
|
||||||
|
@ -14,22 +14,21 @@ import rasterVert from '../shaders/raster_2d_vert.glsl';
|
||||||
export default class RasterModel extends BaseModel {
|
export default class RasterModel extends BaseModel {
|
||||||
protected texture: ITexture2D;
|
protected texture: ITexture2D;
|
||||||
protected colorTexture: ITexture2D;
|
protected colorTexture: ITexture2D;
|
||||||
private rampColors: any;
|
|
||||||
public getUninforms() {
|
public getUninforms() {
|
||||||
const {
|
const {
|
||||||
opacity = 1,
|
opacity = 1,
|
||||||
clampLow = true,
|
clampLow = true,
|
||||||
clampHigh = true,
|
clampHigh = true,
|
||||||
noDataValue = -9999999,
|
noDataValue = -9999999,
|
||||||
domain = [0, 1],
|
domain,
|
||||||
rampColors,
|
rampColors,
|
||||||
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
||||||
this.colorTexture = this.layer.textureService.getColorTexture(rampColors);
|
const newdomain = domain ||getDefaultDomain(rampColors)
|
||||||
|
this.colorTexture = this.layer.textureService.getColorTexture(rampColors,newdomain);
|
||||||
return {
|
return {
|
||||||
u_opacity: opacity || 1,
|
u_opacity: opacity || 1,
|
||||||
u_texture: this.texture,
|
u_texture: this.texture,
|
||||||
u_domain: domain,
|
u_domain: newdomain,
|
||||||
u_clampLow: clampLow,
|
u_clampLow: clampLow,
|
||||||
u_clampHigh: typeof clampHigh !== 'undefined' ? clampHigh : clampLow,
|
u_clampHigh: typeof clampHigh !== 'undefined' ? clampHigh : clampLow,
|
||||||
u_noDataValue: noDataValue,
|
u_noDataValue: noDataValue,
|
||||||
|
@ -123,17 +122,4 @@ export default class RasterModel extends BaseModel {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateColorTexture() {
|
|
||||||
const { createTexture2D } = this.rendererService;
|
|
||||||
const {
|
|
||||||
rampColors,
|
|
||||||
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
|
||||||
const imageData = generateColorRamp(rampColors as IColorRamp);
|
|
||||||
this.colorTexture = createTexture2D({
|
|
||||||
data: imageData.data,
|
|
||||||
width: imageData.width,
|
|
||||||
height: imageData.height,
|
|
||||||
flipY: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
IModelUniform,
|
IModelUniform,
|
||||||
ITexture2D,
|
ITexture2D,
|
||||||
} from '@antv/l7-core';
|
} from '@antv/l7-core';
|
||||||
import { getMask } from '@antv/l7-utils';
|
import { getMask,getDefaultDomain } from '@antv/l7-utils';
|
||||||
import BaseModel from '../../core/BaseModel';
|
import BaseModel from '../../core/BaseModel';
|
||||||
import { IRasterLayerStyleOptions } from '../../core/interface';
|
import { IRasterLayerStyleOptions } from '../../core/interface';
|
||||||
import { RasterImageTriangulation } from '../../core/triangulation';
|
import { RasterImageTriangulation } from '../../core/triangulation';
|
||||||
|
@ -21,20 +21,21 @@ import {
|
||||||
clampLow = true,
|
clampLow = true,
|
||||||
clampHigh = true,
|
clampHigh = true,
|
||||||
noDataValue = -9999999,
|
noDataValue = -9999999,
|
||||||
domain = [0, 1],
|
domain,
|
||||||
rampColors,
|
rampColors,
|
||||||
colorTexture
|
colorTexture
|
||||||
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
||||||
|
const newdomain = domain ||getDefaultDomain(rampColors)
|
||||||
let texture:ITexture2D | undefined = colorTexture;
|
let texture:ITexture2D | undefined = colorTexture;
|
||||||
if(!colorTexture) {
|
if(!colorTexture) {
|
||||||
texture = this.layer.textureService.getColorTexture(rampColors) as ITexture2D;
|
texture = this.layer.textureService.getColorTexture(rampColors,newdomain) as ITexture2D;
|
||||||
} else {
|
} else {
|
||||||
this.layer.textureService.setColorTexture(colorTexture,rampColors)
|
this.layer.textureService.setColorTexture(colorTexture,rampColors,newdomain)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
u_opacity: opacity || 1,
|
u_opacity: opacity || 1,
|
||||||
u_texture: this.texture,
|
u_texture: this.texture,
|
||||||
u_domain: domain,
|
u_domain: newdomain,
|
||||||
u_clampLow: clampLow,
|
u_clampLow: clampLow,
|
||||||
u_clampHigh: typeof clampHigh !== 'undefined' ? clampHigh : clampLow,
|
u_clampHigh: typeof clampHigh !== 'undefined' ? clampHigh : clampLow,
|
||||||
u_noDataValue: noDataValue,
|
u_noDataValue: noDataValue,
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
import {
|
|
||||||
AttributeType,
|
|
||||||
gl,
|
|
||||||
IEncodeFeature,
|
|
||||||
IModel,
|
|
||||||
ITexture2D,
|
|
||||||
} from '@antv/l7-core';
|
|
||||||
import { getMask } from '@antv/l7-utils';
|
|
||||||
import BaseModel from '../../core/BaseModel';
|
|
||||||
import { IRasterLayerStyleOptions } from '../../core/interface';
|
|
||||||
import { RasterImageTriangulation } from '../../core/triangulation';
|
|
||||||
import rasterFrag from '../shaders/raster_2d_frag.glsl';
|
|
||||||
import rasterVert from '../shaders/raster_2d_vert.glsl';
|
|
||||||
export default class RasterModel extends BaseModel {
|
|
||||||
protected texture: ITexture2D;
|
|
||||||
public getUninforms() {
|
|
||||||
const { createTexture2D } = this.rendererService;
|
|
||||||
const {
|
|
||||||
colorTexture = createTexture2D({
|
|
||||||
data: [],
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
flipY: false,
|
|
||||||
}),
|
|
||||||
opacity = 1,
|
|
||||||
clampLow = true,
|
|
||||||
clampHigh = true,
|
|
||||||
noDataValue = -9999999,
|
|
||||||
domain = [0, 1],
|
|
||||||
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
|
||||||
|
|
||||||
return {
|
|
||||||
u_opacity: opacity || 1,
|
|
||||||
u_texture: this.texture,
|
|
||||||
u_domain: domain,
|
|
||||||
u_clampLow: clampLow,
|
|
||||||
u_clampHigh: typeof clampHigh !== 'undefined' ? clampHigh : clampLow,
|
|
||||||
u_noDataValue: noDataValue,
|
|
||||||
u_colorTexture: colorTexture,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async initModels(): Promise<IModel[]> {
|
|
||||||
const {
|
|
||||||
mask = false,
|
|
||||||
maskInside = true,
|
|
||||||
} = this.layer.getLayerConfig() as IRasterLayerStyleOptions;
|
|
||||||
const source = this.layer.getSource();
|
|
||||||
const { createTexture2D } = this.rendererService;
|
|
||||||
const parserDataItem = source.data.dataArray[0];
|
|
||||||
this.texture = createTexture2D({
|
|
||||||
data: parserDataItem.data,
|
|
||||||
width: parserDataItem.width,
|
|
||||||
height: parserDataItem.height,
|
|
||||||
format: gl.LUMINANCE,
|
|
||||||
type: gl.FLOAT,
|
|
||||||
});
|
|
||||||
|
|
||||||
const model = await this.layer
|
|
||||||
.buildLayerModel({
|
|
||||||
moduleName: 'rasterTileImageData',
|
|
||||||
vertexShader: rasterVert,
|
|
||||||
fragmentShader: rasterFrag,
|
|
||||||
triangulation: RasterImageTriangulation,
|
|
||||||
depth: { enable: false },
|
|
||||||
stencil: getMask(mask, maskInside),
|
|
||||||
})
|
|
||||||
return [model]
|
|
||||||
}
|
|
||||||
|
|
||||||
public async buildModels():Promise<IModel[]> {
|
|
||||||
return await this.initModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
public clearModels(): void {
|
|
||||||
this.texture?.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected registerBuiltinAttributes() {
|
|
||||||
this.styleAttributeService.registerStyleAttribute({
|
|
||||||
name: 'uv',
|
|
||||||
type: AttributeType.Attribute,
|
|
||||||
descriptor: {
|
|
||||||
name: 'a_Uv',
|
|
||||||
buffer: {
|
|
||||||
usage: gl.DYNAMIC_DRAW,
|
|
||||||
data: [],
|
|
||||||
type: gl.FLOAT,
|
|
||||||
},
|
|
||||||
size: 2,
|
|
||||||
update: (
|
|
||||||
feature: IEncodeFeature,
|
|
||||||
featureIdx: number,
|
|
||||||
vertex: number[],
|
|
||||||
) => {
|
|
||||||
return [vertex[3], vertex[4]];
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ void main() {
|
||||||
else if ((!u_clampLow && value < u_domain[0]) || (!u_clampHigh && value > u_domain[1]))
|
else if ((!u_clampLow && value < u_domain[0]) || (!u_clampHigh && value > u_domain[1]))
|
||||||
gl_FragColor = vec4(0, 0, 0, 0);
|
gl_FragColor = vec4(0, 0, 0, 0);
|
||||||
else {
|
else {
|
||||||
|
|
||||||
float normalisedValue =(value - u_domain[0]) / (u_domain[1] -u_domain[0]);
|
float normalisedValue =(value - u_domain[0]) / (u_domain[1] -u_domain[0]);
|
||||||
vec4 color = texture2D(u_colorTexture,vec2(normalisedValue, 0));
|
vec4 color = texture2D(u_colorTexture,vec2(normalisedValue, 0));
|
||||||
gl_FragColor = color;
|
gl_FragColor = color;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { ILayerAttributesOption } from '@antv/l7-core';
|
import { ILayerAttributesOption } from '@antv/l7-core';
|
||||||
// import RasterLayer from './layers/RasterDataLayer';
|
|
||||||
import RasterLayer from '../../raster'
|
import RasterLayer from '../../raster'
|
||||||
import Tile from './Tile';
|
import Tile from './Tile';
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { ILayerAttributesOption, ITexture2D } from '@antv/l7-core';
|
||||||
import RasterLayer from '../../raster'
|
import RasterLayer from '../../raster'
|
||||||
import { IRasterLayerStyleOptions } from '../../core/interface';
|
import { IRasterLayerStyleOptions } from '../../core/interface';
|
||||||
import Tile from './Tile';
|
import Tile from './Tile';
|
||||||
|
import { getDefaultDomain } from '@antv/l7-utils';
|
||||||
|
|
||||||
const DEFAULT_COLOR_TEXTURE_OPTION = {
|
const DEFAULT_COLOR_TEXTURE_OPTION = {
|
||||||
positions: [0, 1],
|
positions: [0, 1],
|
||||||
|
@ -12,9 +13,10 @@ export default class RasterTile extends Tile {
|
||||||
private colorTexture: ITexture2D;
|
private colorTexture: ITexture2D;
|
||||||
public async initTileLayer(): Promise<void> {
|
public async initTileLayer(): Promise<void> {
|
||||||
const attributes = this.parent.getLayerAttributeConfig();
|
const attributes = this.parent.getLayerAttributeConfig();
|
||||||
const layerOptions = this.getLayerOptions();
|
const layerOptions = this.getLayerOptions() ;
|
||||||
const sourceOptions = this.getSourceOption();
|
const sourceOptions = this.getSourceOption();
|
||||||
this.colorTexture = this.parent.textureService.getColorTexture((layerOptions as unknown as IRasterLayerStyleOptions).rampColors)
|
const {rampColors,domain} = this.getLayerOptions() as unknown as IRasterLayerStyleOptions;
|
||||||
|
this.colorTexture = this.parent.textureService.getColorTexture(rampColors,domain);
|
||||||
const layer = new RasterLayer({
|
const layer = new RasterLayer({
|
||||||
...layerOptions,
|
...layerOptions,
|
||||||
colorTexture: this.colorTexture,
|
colorTexture: this.colorTexture,
|
||||||
|
@ -57,8 +59,8 @@ export default class RasterTile extends Tile {
|
||||||
*/
|
*/
|
||||||
public styleUpdate(...arg: any): void {
|
public styleUpdate(...arg: any): void {
|
||||||
|
|
||||||
const { rampColors = DEFAULT_COLOR_TEXTURE_OPTION } = arg;
|
const { rampColors = DEFAULT_COLOR_TEXTURE_OPTION, domain} = arg as IRasterLayerStyleOptions;
|
||||||
this.colorTexture = this.parent.textureService.getColorTexture(rampColors)
|
this.colorTexture = this.parent.textureService.getColorTexture(rampColors,domain || getDefaultDomain(rampColors))
|
||||||
this.layers.forEach(layer => layer.style({ colorTexture: this.colorTexture }));
|
this.layers.forEach(layer => layer.style({ colorTexture: this.colorTexture }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import BaseLayer from '../../../core/BaseLayer';
|
|
||||||
import { IRasterLayerStyleOptions } from '../../../core/interface';
|
|
||||||
import RasterModel from '../../../raster/models/rasterTile';
|
|
||||||
import RasterRgbModel from '../../../raster/models/rasterRgb';
|
|
||||||
|
|
||||||
export default class RasterTiffLayer extends BaseLayer<
|
|
||||||
Partial<IRasterLayerStyleOptions>
|
|
||||||
> {
|
|
||||||
public type: string = 'RasterLayer';
|
|
||||||
public async buildModels() {
|
|
||||||
const model = this.getModel();
|
|
||||||
this.layerModel = new model(this);
|
|
||||||
await this.initLayerModels();
|
|
||||||
}
|
|
||||||
|
|
||||||
public getModel() {
|
|
||||||
const type = this.getModelType();
|
|
||||||
return type === 'rasterRgb' ? RasterRgbModel :RasterModel;
|
|
||||||
}
|
|
||||||
public getModelType():string {
|
|
||||||
return this.layerSource.parser.type === 'rasterRgb' ? 'rasterRgb' : 'raster'
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getDefaultConfig() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -98,6 +98,10 @@ export default class ReglTexture2D implements ITexture2D {
|
||||||
this.height = height;
|
this.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getSize(): [number, number] {
|
||||||
|
return [this.width, this.height];
|
||||||
|
}
|
||||||
|
|
||||||
public destroy() {
|
public destroy() {
|
||||||
if (!this.isDestroy) {
|
if (!this.isDestroy) {
|
||||||
this.texture?.destroy();
|
this.texture?.destroy();
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
### rampColors 颜色色带
|
||||||
|
- type 类型 支持 `linear','quantize','custom','cat'
|
||||||
|
- colors 颜色数组
|
||||||
|
- positions 数据分段区间,可选,quantize 不需要设置 position,position 为原始数据值
|
||||||
|
|
||||||
|
⚠️ 2.13 新增特性
|
||||||
|
|
||||||
|
#### cat 枚举类型色带
|
||||||
|
|
||||||
|
枚举类型色带只支持 0 -255 的整数类型,positions 用来设置枚举
|
||||||
|
```tsx
|
||||||
|
{
|
||||||
|
type:'cat',
|
||||||
|
colors:['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00'],
|
||||||
|
positions:[1,20,101,102,200],
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### quantize 等间距分类色带
|
||||||
|
|
||||||
|
等间距只根据数据的区间 domain 进行均匀分段,如 domain [0,10000],如果分 5 段,每段间距 2000。
|
||||||
|
等间距不需要设置 positions,只需要设置colors,根据colors 的长度设置分段数
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
rampColors: {
|
||||||
|
type:'quantize',
|
||||||
|
colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac']
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### linear 线性连续色带
|
||||||
|
|
||||||
|
linear 为现有连续类型的加强版,positions 支持设置源数据,不需要转换成 0-1
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
rampColors: {
|
||||||
|
type:'linear',
|
||||||
|
colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'],
|
||||||
|
positions [0,200,1000,4000,8000]
|
||||||
|
}
|
||||||
|
|
||||||
|
⚠️ 兼容 2.13.0 之前版本,未设置type 时,position 值域为 0-1。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
#### custom 自定义分段色带
|
||||||
|
|
||||||
|
自定义分段色带区别等间距色带,用户自定义分段间隔。
|
||||||
|
自定义 positions 的长度需要比 colors 的长度多1个,同时poisitions
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
rampColors: {
|
||||||
|
type:'custom',
|
||||||
|
colors: ['#f0f9e8','#bae4bc','#7bccc4','#43a2ca','#0868ac'],
|
||||||
|
positions [0,200,1000,4000,8000,10000]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
||||||
|
|
||||||
|
⚠️ colors, positions 的长度要相同
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
layer.style({
|
||||||
|
rampColors: {
|
||||||
|
colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'],
|
||||||
|
positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0],
|
||||||
|
},
|
||||||
|
});
|
|
@ -19,20 +19,5 @@ layer.style({
|
||||||
| noDataValue | `number` | 不会显示的值 | `-9999999` |
|
| noDataValue | `number` | 不会显示的值 | `-9999999` |
|
||||||
| rampColors | `IRampColors` | 值域映射颜色的色带 | `/` |
|
| rampColors | `IRampColors` | 值域映射颜色的色带 | `/` |
|
||||||
|
|
||||||
#### rampColors
|
|
||||||
|
|
||||||
- colors 颜色数组
|
<embed src="@/docs/api/raster_layer/common/rampcolors.md"></embed>
|
||||||
- positions 数据区间
|
|
||||||
|
|
||||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
|
||||||
|
|
||||||
⚠️ colors, positions 的长度要相同
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
layer.style({
|
|
||||||
rampColors: {
|
|
||||||
colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'],
|
|
||||||
positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
|
@ -17,20 +17,4 @@ layer.style({
|
||||||
| noDataValue | `number` | 不会显示的值 | `-9999999` |
|
| noDataValue | `number` | 不会显示的值 | `-9999999` |
|
||||||
| rampColors | `IRampColors` | 值域映射颜色的色带 | `/` |
|
| rampColors | `IRampColors` | 值域映射颜色的色带 | `/` |
|
||||||
|
|
||||||
#### rampColors
|
<embed src="@/docs/api/raster_layer/common/rampcolors.md"></embed>
|
||||||
|
|
||||||
- colors 颜色数组
|
|
||||||
- positions 数据区间
|
|
||||||
|
|
||||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
|
||||||
|
|
||||||
⚠️ colors, positions 的长度要相同
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
layer.style({
|
|
||||||
rampColors: {
|
|
||||||
colors: ['#FF4818', '#F7B74A', '#FFF598', '#91EABC', '#2EA9A1', '#206C7C'],
|
|
||||||
positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ order: 0
|
||||||
- L7 本身内部没有提供栅格数据格式, 需要将外部的栅格数据文件解析后或者提供解析方法做传入、如 `tiff`、`lerc`。
|
- L7 本身内部没有提供栅格数据格式, 需要将外部的栅格数据文件解析后或者提供解析方法做传入、如 `tiff`、`lerc`。
|
||||||
- 栅格图层除了支持简单渲染之外还支持栅格数据的多波段计算,可以用于绘制遥感彩色影像。
|
- 栅格图层除了支持简单渲染之外还支持栅格数据的多波段计算,可以用于绘制遥感彩色影像。
|
||||||
|
|
||||||
### 直接绘制
|
### 数据绘制
|
||||||
|
|
||||||
我们可以直接在外部计算出栅格的波段数据后传给栅格图层使用。
|
我们可以直接在外部计算出栅格的波段数据后传给栅格图层使用。
|
||||||
|
|
||||||
|
|
|
@ -67,13 +67,13 @@ layer.on('legend:color', (ev) => console.log(ev));
|
||||||
|
|
||||||
### legend:size
|
### legend:size
|
||||||
|
|
||||||
数据映射更新,图例发生变化,color 大小改变
|
数据映射更新,图例发生变化,size 大小改变
|
||||||
参数 option
|
参数 option
|
||||||
- type 映射通道、图例类型
|
- type 映射通道、图例类型
|
||||||
- attr 映射实例
|
- attr 映射实例
|
||||||
|
|
||||||
```js
|
```js
|
||||||
layer.on('legend:color', (ev) => console.log(ev));
|
layer.on('legend:size', (ev) => console.log(ev));
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,6 @@
|
||||||
"title": "雷达图",
|
"title": "雷达图",
|
||||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*JDO-R5XU7xwAAAAAAAAAAAAAARQnAQ"
|
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*JDO-R5XU7xwAAAAAAAAAAAAAARQnAQ"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"filename": "light.js",
|
|
||||||
"title": "夜光图",
|
|
||||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*xznhSJFEAXYAAAAAAAAAAAAAARQnAQ"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"filename": "image.js",
|
"filename": "image.js",
|
||||||
"title": "图片",
|
"title": "图片",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
---
|
---
|
||||||
title: 栅格图层
|
title: 图片栅格
|
||||||
order: 0
|
order: 0
|
||||||
---
|
---
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
---
|
---
|
||||||
title: 数据栅格
|
title: 多波段
|
||||||
order: 0
|
order: 0
|
||||||
---
|
---
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// https://gw.alipayobjects.com/zos/antvdemo/assets/2019_clip/ndvi_201905.tif
|
||||||
|
import { RasterLayer, Scene } from '@antv/l7';
|
||||||
|
import { GaodeMap } from '@antv/l7-maps';
|
||||||
|
import * as GeoTIFF from 'geotiff';
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
map: new GaodeMap({
|
||||||
|
center: [121.268, 30.3628],
|
||||||
|
zoom: 3,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
async function getTiffData() {
|
||||||
|
const response = await fetch(
|
||||||
|
'https://gw.alipayobjects.com/os/rmsportal/XKgkjjGaAzRyKupCBiYW.dat',
|
||||||
|
);
|
||||||
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
return arrayBuffer;
|
||||||
|
}
|
||||||
|
scene.on('loaded', async () => {
|
||||||
|
const tiffdata = await getTiffData();
|
||||||
|
const tiff = await GeoTIFF.fromArrayBuffer(tiffdata);
|
||||||
|
const image = await tiff.getImage();
|
||||||
|
const width = image.getWidth();
|
||||||
|
const height = image.getHeight();
|
||||||
|
const values = await image.readRasters();
|
||||||
|
|
||||||
|
const layer = new RasterLayer();
|
||||||
|
layer
|
||||||
|
.source(values[0], {
|
||||||
|
parser: {
|
||||||
|
type: 'raster',
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.style({
|
||||||
|
opacity: 1,
|
||||||
|
clampLow: false,
|
||||||
|
clampHigh: false,
|
||||||
|
domain: [0, 10000],
|
||||||
|
rampColors: {
|
||||||
|
type:'custom',
|
||||||
|
colors: ['#b2182b','#d6604d','#f4a582','#fddbc7','#f7f7f7','#d1e5f0','#92c5de','#4393c3','#2166ac'],
|
||||||
|
positions: [0, 50, 200, 500, 2000, 3000, 4000, 5000, 8000,10000],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
scene.addLayer(layer)
|
||||||
|
});
|
|
@ -0,0 +1,50 @@
|
||||||
|
// https://gw.alipayobjects.com/zos/antvdemo/assets/2019_clip/ndvi_201905.tif
|
||||||
|
import { RasterLayer, Scene } from '@antv/l7';
|
||||||
|
import { GaodeMap } from '@antv/l7-maps';
|
||||||
|
import * as GeoTIFF from 'geotiff';
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
map: new GaodeMap({
|
||||||
|
center: [121.268, 30.3628],
|
||||||
|
zoom: 3,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
async function getTiffData() {
|
||||||
|
const response = await fetch(
|
||||||
|
'https://gw.alipayobjects.com/os/rmsportal/XKgkjjGaAzRyKupCBiYW.dat',
|
||||||
|
);
|
||||||
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
return arrayBuffer;
|
||||||
|
}
|
||||||
|
scene.on('loaded', async () => {
|
||||||
|
const tiffdata = await getTiffData();
|
||||||
|
const tiff = await GeoTIFF.fromArrayBuffer(tiffdata);
|
||||||
|
const image = await tiff.getImage();
|
||||||
|
const width = image.getWidth();
|
||||||
|
const height = image.getHeight();
|
||||||
|
const values = await image.readRasters();
|
||||||
|
|
||||||
|
const layer = new RasterLayer();
|
||||||
|
layer
|
||||||
|
.source(values[0], {
|
||||||
|
parser: {
|
||||||
|
type: 'raster',
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
extent: [73.482190241, 3.82501784112, 135.106618732, 57.6300459963],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.style({
|
||||||
|
opacity: 1,
|
||||||
|
clampLow: false,
|
||||||
|
clampHigh: false,
|
||||||
|
domain: [0, 10000],
|
||||||
|
rampColors: {
|
||||||
|
type:'quantize', // 等间距 不需要设置 position
|
||||||
|
colors: ['#b2182b','#d6604d','#f4a582','#fddbc7','#f7f7f7','#d1e5f0','#92c5de','#4393c3','#2166ac'],
|
||||||
|
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
scene.addLayer(layer)
|
||||||
|
});
|
|
@ -49,8 +49,9 @@ async function addLayer() {
|
||||||
domain: [ 0, 90 ],
|
domain: [ 0, 90 ],
|
||||||
nodataValue: 0,
|
nodataValue: 0,
|
||||||
rampColors: {
|
rampColors: {
|
||||||
colors: [ 'rgba(92,58,16,0)', 'rgba(92,58,16,0)', '#fabd08', '#f1e93f', '#f1ff8f', '#fcfff7' ],
|
type:'linear', // 2.13.0 及以后版本支持
|
||||||
positions: [ 0, 0.05, 0.1, 0.25, 0.5, 1.0 ]
|
colors: ['rgba(92,58,16,0)','rgba(92,58,16,0)', '#fabd08', '#f1e93f', '#f1ff8f', '#fcfff7' ],
|
||||||
|
positions: [0,3, 9, 22.5, 45, 90 ]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// https://gw.alipayobjects.com/zos/antvdemo/assets/2019_clip/ndvi_201905.tif
|
||||||
|
import { RasterLayer, Scene } from '@antv/l7';
|
||||||
|
import { GaodeMap } from '@antv/l7-maps';
|
||||||
|
import * as GeoTIFF from 'geotiff';
|
||||||
|
const scene = new Scene({
|
||||||
|
id: 'map',
|
||||||
|
map: new GaodeMap({
|
||||||
|
style: 'dark',
|
||||||
|
center: [ 105, 37.5 ],
|
||||||
|
zoom: 2.5
|
||||||
|
})
|
||||||
|
});
|
||||||
|
scene.on('loaded', () => {
|
||||||
|
addLayer();
|
||||||
|
});
|
||||||
|
async function getTiffData() {
|
||||||
|
const response = await fetch(
|
||||||
|
'https://gw.alipayobjects.com/zos/antvdemo/assets/light_clip/lightF182013.tiff'
|
||||||
|
);
|
||||||
|
const arrayBuffer = await response.arrayBuffer();
|
||||||
|
const tiff = await GeoTIFF.fromArrayBuffer(arrayBuffer);
|
||||||
|
const image = await tiff.getImage();
|
||||||
|
const width = image.getWidth();
|
||||||
|
const height = image.getHeight();
|
||||||
|
const values = await image.readRasters();
|
||||||
|
return {
|
||||||
|
data: values[0],
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addLayer() {
|
||||||
|
const tiffdata = await getTiffData();
|
||||||
|
|
||||||
|
const layer = new RasterLayer({});
|
||||||
|
layer
|
||||||
|
.source(tiffdata.data, {
|
||||||
|
parser: {
|
||||||
|
type: 'raster',
|
||||||
|
width: tiffdata.width,
|
||||||
|
height: tiffdata.height,
|
||||||
|
extent: [ 73.4821902409999979, 3.8150178409999995, 135.1066187319999869, 57.6300459959999998 ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.style({
|
||||||
|
clampLow: false,
|
||||||
|
clampHigh: false,
|
||||||
|
domain: [ 0, 90 ],
|
||||||
|
nodataValue: 0,
|
||||||
|
rampColors: {
|
||||||
|
positions: [ 0, 0.05, 0.1, 0.25, 0.5, 1.0 ],// 数据需要换成 0-1
|
||||||
|
colors: ['rgba(92,58,16,0)','rgba(92,58,16,0)', '#fabd08', '#f1e93f', '#f1ff8f', '#fcfff7' ],
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
scene.addLayer(layer);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"title": {
|
||||||
|
"zh": "单波段数据栅格",
|
||||||
|
"en": "Gallery"
|
||||||
|
},
|
||||||
|
"demos": [
|
||||||
|
|
||||||
|
{
|
||||||
|
"filename": "light_default.js",
|
||||||
|
"title": "夜光图-默认线性",
|
||||||
|
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*xznhSJFEAXYAAAAAAAAAAAAAARQnAQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "light.js",
|
||||||
|
"title": "夜光图-线性色带",
|
||||||
|
"screenshot": "https://gw.alipayobjects.com/mdn/rms_816329/afts/img/A*xznhSJFEAXYAAAAAAAAAAAAAARQnAQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "dem.js",
|
||||||
|
"title": "高程图-自定义色带",
|
||||||
|
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*_RtOTrYOOrUAAAAAAAAAAAAADmJ7AQ/original"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "dem_quantize.js",
|
||||||
|
"title": "高程图-等间距色带",
|
||||||
|
"screenshot": "https://mdn.alipayobjects.com//huamei_qa8qxu/afts/img/A*DT1HQbl4JKMAAAAAAAAAAAAADmJ7AQ/original"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Raster Data Map
|
||||||
|
order: 0
|
||||||
|
---
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: 单波段
|
||||||
|
order: 0
|
||||||
|
---
|
|
@ -4,56 +4,33 @@ import * as GeoTIFF from 'geotiff';
|
||||||
|
|
||||||
const colorList = [
|
const colorList = [
|
||||||
'#419bdf', // Water
|
'#419bdf', // Water
|
||||||
'#419bdf',
|
|
||||||
|
|
||||||
'#397d49', // Tree
|
'#358221', // Tree
|
||||||
'#397d49',
|
|
||||||
|
|
||||||
'#88b053', // Grass
|
'#88b053', // Grass
|
||||||
'#88b053',
|
|
||||||
|
|
||||||
'#7a87c6', // vegetation
|
'#7a87c6', // vegetation
|
||||||
'#7a87c6',
|
|
||||||
|
|
||||||
'#e49635', // Crops
|
'#e49635', // Crops
|
||||||
'#e49635',
|
|
||||||
|
|
||||||
'#dfc35a', // shrub
|
'#dfc35a', // shrub
|
||||||
'#dfc35a',
|
|
||||||
|
|
||||||
'#c4281b', // Built Area
|
|
||||||
'#c4281b',
|
|
||||||
|
|
||||||
'#a59b8f', // Bare ground
|
'#ED022A', // Built Area
|
||||||
'#a59b8f',
|
|
||||||
|
|
||||||
'#a8ebff', // Snow
|
|
||||||
'#a8ebff',
|
|
||||||
|
|
||||||
'#616161', // Clouds
|
'#EDE9E4', // Bare ground
|
||||||
'#616161'
|
|
||||||
|
|
||||||
|
'#F2FAFF', // Snow
|
||||||
|
|
||||||
|
'#C8C8C8', // Clouds
|
||||||
];
|
];
|
||||||
const positions = [
|
const positions = [
|
||||||
0.0,
|
1,2,3,4,5,6,7,8,9,10,11,
|
||||||
0.1,
|
|
||||||
0.1,
|
|
||||||
0.2,
|
|
||||||
0.2,
|
|
||||||
0.3,
|
|
||||||
0.3,
|
|
||||||
0.4,
|
|
||||||
0.4,
|
|
||||||
0.5,
|
|
||||||
0.5,
|
|
||||||
0.6,
|
|
||||||
0.6,
|
|
||||||
0.7,
|
|
||||||
0.7,
|
|
||||||
0.8,
|
|
||||||
0.8,
|
|
||||||
0.9,
|
|
||||||
0.9,
|
|
||||||
1.0
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const scene = new Scene({
|
const scene = new Scene({
|
||||||
|
@ -97,9 +74,10 @@ scene.on('loaded', () => {
|
||||||
|
|
||||||
layer.source(tileSource)
|
layer.source(tileSource)
|
||||||
.style({
|
.style({
|
||||||
domain: [ 0.001, 11.001 ],
|
domain: [ 0, 255],// 枚举类型domain 必须为0-255
|
||||||
clampLow: false,
|
clampLow: false,
|
||||||
rampColors: {
|
rampColors: {
|
||||||
|
type:'cat',
|
||||||
colors: colorList,
|
colors: colorList,
|
||||||
positions
|
positions
|
||||||
}
|
}
|
||||||
|
@ -115,7 +93,7 @@ const wrap = document.getElementById('map');
|
||||||
const legend = document.createElement('div');
|
const legend = document.createElement('div');
|
||||||
|
|
||||||
const data = [];
|
const data = [];
|
||||||
for (let i = 0; i < colorList.length; i += 2) {
|
for (let i = 0; i < colorList.length; i += 1) {
|
||||||
data.push({
|
data.push({
|
||||||
color: colorList[i],
|
color: colorList[i],
|
||||||
text: [
|
text: [
|
||||||
|
@ -129,7 +107,7 @@ for (let i = 0; i < colorList.length; i += 2) {
|
||||||
'Bare ground',
|
'Bare ground',
|
||||||
'Snow',
|
'Snow',
|
||||||
'Clouds'
|
'Clouds'
|
||||||
][i / 2]
|
][i]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const strArr = [];
|
const strArr = [];
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import * as d3 from 'd3-color';
|
import * as d3 from 'd3-color';
|
||||||
|
import { Context } from 'vm';
|
||||||
import { $window, isMini } from './mini-adapter';
|
import { $window, isMini } from './mini-adapter';
|
||||||
export interface IColorRamp {
|
export interface IColorRamp {
|
||||||
|
type?: 'cat' | 'linear' | 'quantize' | 'custom'
|
||||||
positions: number[];
|
positions: number[];
|
||||||
colors: string[];
|
colors: string[];
|
||||||
weights?: number[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isColor(str: any) {
|
export function isColor(str: any) {
|
||||||
|
@ -51,6 +52,7 @@ export interface IImagedata {
|
||||||
height: number;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 连续型 老版本兼容
|
||||||
export function generateColorRamp(
|
export function generateColorRamp(
|
||||||
colorRamp: IColorRamp,
|
colorRamp: IColorRamp,
|
||||||
): ImageData | IImagedata {
|
): ImageData | IImagedata {
|
||||||
|
@ -60,17 +62,6 @@ export function generateColorRamp(
|
||||||
canvas.height = 1;
|
canvas.height = 1;
|
||||||
let data = null;
|
let data = null;
|
||||||
|
|
||||||
if (colorRamp.weights) {
|
|
||||||
// draw enum color
|
|
||||||
let count = 0;
|
|
||||||
colorRamp.weights.map((w, index) => {
|
|
||||||
const color = colorRamp.colors[index] || 'rgba(0, 0, 0, 0)';
|
|
||||||
const stop = count + w;
|
|
||||||
ctx.fillStyle = color;
|
|
||||||
ctx.fillRect(count * 256, 0, stop * 256, 1);
|
|
||||||
count = stop;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// draw linear color
|
// draw linear color
|
||||||
const gradient = ctx.createLinearGradient(0, 0, 256, 1);
|
const gradient = ctx.createLinearGradient(0, 0, 256, 1);
|
||||||
|
|
||||||
|
@ -82,7 +73,7 @@ export function generateColorRamp(
|
||||||
}
|
}
|
||||||
ctx.fillStyle = gradient;
|
ctx.fillStyle = gradient;
|
||||||
ctx.fillRect(0, 0, 256, 1);
|
ctx.fillRect(0, 0, 256, 1);
|
||||||
}
|
|
||||||
|
|
||||||
if (!isMini) {
|
if (!isMini) {
|
||||||
data = ctx.getImageData(0, 0, 256, 1).data;
|
data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
|
@ -108,3 +99,149 @@ export function generateColorRamp(
|
||||||
return { data, width: 256, height: 1 };
|
return { data, width: 256, height: 1 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 连续型 Position 支持设置原始数据
|
||||||
|
export function generateLinearRamp(
|
||||||
|
colorRamp: IColorRamp,
|
||||||
|
domain: [number, number],
|
||||||
|
): ImageData | IImagedata {
|
||||||
|
let canvas = $window.document.createElement('canvas');
|
||||||
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
|
canvas.width = 256;
|
||||||
|
canvas.height = 1;
|
||||||
|
// draw linear color
|
||||||
|
const gradient = ctx.createLinearGradient(0, 0, 256, 1);
|
||||||
|
const step = domain[1] - domain[0];
|
||||||
|
|
||||||
|
for (let i = 0; i < colorRamp.colors.length; ++i) {
|
||||||
|
const value = Math.max((colorRamp.positions[i] - domain[0]) / step,0);
|
||||||
|
console.log(value)
|
||||||
|
gradient.addColorStop(value, colorRamp.colors[i]);
|
||||||
|
}
|
||||||
|
ctx.fillStyle = gradient;
|
||||||
|
ctx.fillRect(0, 0, 256, 1);
|
||||||
|
const data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
|
const imageData = toIEIMageData(ctx, data);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
canvas = null;
|
||||||
|
// @ts-ignore
|
||||||
|
ctx = null;
|
||||||
|
return imageData
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 枚举类型
|
||||||
|
export function generateCatRamp(
|
||||||
|
colorRamp: IColorRamp,
|
||||||
|
): ImageData | IImagedata {
|
||||||
|
|
||||||
|
let canvas = $window.document.createElement('canvas');
|
||||||
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
|
canvas.width = 256;
|
||||||
|
canvas.height = 1;
|
||||||
|
const imageData = ctx.createImageData(256, 1);
|
||||||
|
imageData.data.fill(0);
|
||||||
|
colorRamp.positions.forEach((p: number, index: number) => {
|
||||||
|
const colorArray = rgb2arr(colorRamp.colors[index])
|
||||||
|
imageData.data[p * 4 + 0] = colorArray[0] * 255;
|
||||||
|
imageData.data[p * 4 + 1] = colorArray[1] * 255;
|
||||||
|
imageData.data[p * 4 + 2] = colorArray[2] * 255;
|
||||||
|
imageData.data[p * 4 + 3] = colorArray[3] * 255;
|
||||||
|
})
|
||||||
|
// @ts-ignore
|
||||||
|
canvas = null;
|
||||||
|
// @ts-ignore
|
||||||
|
ctx = null;
|
||||||
|
return imageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等间距
|
||||||
|
export function generateQuantizeRamp(
|
||||||
|
colorRamp: IColorRamp,
|
||||||
|
): ImageData | IImagedata {
|
||||||
|
let canvas = $window.document.createElement('canvas');
|
||||||
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
|
ctx.globalAlpha = 1.0
|
||||||
|
canvas.width = 256;
|
||||||
|
canvas.height = 1;
|
||||||
|
const step = 256 / colorRamp.colors.length;// TODO 精度问题
|
||||||
|
// draw linear color
|
||||||
|
for (let i = 0; i < colorRamp.colors.length; i++) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
|
||||||
|
ctx.strokeStyle = colorRamp.colors[i];
|
||||||
|
ctx.moveTo(i * step, 0); // positioned at 50,25
|
||||||
|
ctx.lineTo((i + 1) * step, 0);
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
|
// 使用 createImageData 替代 new ImageData、兼容 IE11
|
||||||
|
const imageData = toIEIMageData(ctx, data);
|
||||||
|
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
canvas = null;
|
||||||
|
// @ts-ignore
|
||||||
|
ctx = null;
|
||||||
|
return imageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义间距
|
||||||
|
|
||||||
|
export function generateCustomRamp(
|
||||||
|
colorRamp: IColorRamp,
|
||||||
|
domain: [number, number],
|
||||||
|
): ImageData | IImagedata {
|
||||||
|
|
||||||
|
let canvas = $window.document.createElement('canvas');
|
||||||
|
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||||
|
ctx.globalAlpha = 1.0
|
||||||
|
canvas.width = 256;
|
||||||
|
canvas.height = 1;
|
||||||
|
const step = domain[1] - domain[0];
|
||||||
|
if(colorRamp.positions.length - colorRamp.colors.length !==1) {
|
||||||
|
console.warn('positions 的数字个数应当比 colors 的样式多一个,poisitions 的首尾值一般为数据的最大最新值')
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < colorRamp.colors.length; i++) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
ctx.strokeStyle = colorRamp.colors[i];
|
||||||
|
ctx.moveTo((colorRamp.positions[i] - domain[0]) / step * 255, 0); // positioned at 50,25
|
||||||
|
ctx.lineTo((colorRamp.positions[i + 1]- domain[0]) / step * 255, 0);
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
}
|
||||||
|
const data = ctx.getImageData(0, 0, 256, 1).data;
|
||||||
|
const imageData = toIEIMageData(ctx, data);
|
||||||
|
// @ts-ignore
|
||||||
|
canvas = null;
|
||||||
|
// @ts-ignore
|
||||||
|
ctx = null;
|
||||||
|
return imageData;
|
||||||
|
}
|
||||||
|
function toIEIMageData(ctx: Context, data: Uint8ClampedArray) {
|
||||||
|
const imageData = ctx.createImageData(256, 1);
|
||||||
|
for (let i = 0; i < imageData.data.length; i += 4) {
|
||||||
|
imageData.data[i + 0] = data[i + 0];
|
||||||
|
imageData.data[i + 1] = data[i + 1];
|
||||||
|
imageData.data[i + 2] = data[i + 2];
|
||||||
|
imageData.data[i + 3] = data[i + 3];
|
||||||
|
}
|
||||||
|
return imageData
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefaultDomain(rampColors:IColorRamp) {
|
||||||
|
switch (rampColors.type) {
|
||||||
|
case 'cat' :
|
||||||
|
return [0,255]
|
||||||
|
default:
|
||||||
|
[0,1]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import earcut from 'earcut';
|
||||||
import { calculateCentroid } from '../geo';
|
import { calculateCentroid } from '../geo';
|
||||||
import ExtrudePolyline from './extrude_polyline';
|
import ExtrudePolyline from './extrude_polyline';
|
||||||
import { IEncodeFeature } from './interface';
|
import { IEncodeFeature } from './interface';
|
||||||
|
const LATMAX = 85.0511287798;
|
||||||
export function LineTriangulation(feature: IEncodeFeature) {
|
export function LineTriangulation(feature: IEncodeFeature) {
|
||||||
const { coordinates, originCoordinates, version } = feature;
|
const { coordinates, originCoordinates, version } = feature;
|
||||||
// let path = coordinates as number[][][] | number[][];
|
// let path = coordinates as number[][][] | number[][];
|
||||||
|
@ -91,9 +91,17 @@ export function polygonFillTriangulation(feature: IEncodeFeature) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function project_mercator(x: number, y: number) {
|
function project_mercator(x: number, y: number) {
|
||||||
|
let y1 = y;
|
||||||
|
if (y > LATMAX) {
|
||||||
|
y1 = LATMAX;
|
||||||
|
}
|
||||||
|
if (y < -LATMAX) {
|
||||||
|
y1 = -LATMAX;
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
(Math.PI * x) / 180 + Math.PI,
|
(Math.PI * x) / 180 + Math.PI,
|
||||||
Math.PI - Math.log(Math.tan(Math.PI * 0.25 + ((Math.PI * y) / 180) * 0.5)),
|
Math.PI - Math.log(Math.tan(Math.PI * 0.25 + ((Math.PI * y1) / 180) * 0.5)),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue