mirror of https://gitee.com/antv-l7/antv-l7
feat: 新增 rampcolors 枚举色
This commit is contained in:
parent
c188238b70
commit
c0a0a98036
|
@ -52,15 +52,12 @@ export default () => {
|
|||
.shape('linearline')
|
||||
.style({
|
||||
rampColors: {
|
||||
colors: [
|
||||
'#FF4818',
|
||||
'#F7B74A',
|
||||
'#FFF598',
|
||||
'#91EABC',
|
||||
'#2EA9A1',
|
||||
'#206C7C',
|
||||
],
|
||||
weights: [0.1, 0.1, 0.1, 0.1, 0.1, 0.5],
|
||||
c1: '#FF4818',
|
||||
c2: '#F7B74A',
|
||||
c3: '#FFF598',
|
||||
c4: '#91EABC',
|
||||
c5: '#2EA9A1',
|
||||
c6: [0.5, 1, '#206C7C']
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -3,59 +3,7 @@ import { GaodeMap } from '@antv/l7-maps';
|
|||
import React, { useEffect } from 'react';
|
||||
import * as GeoTIFF from 'geotiff';
|
||||
|
||||
const colorList = [
|
||||
'#419bdf', // Water
|
||||
'#419bdf',
|
||||
|
||||
'#397d49', // Tree
|
||||
'#397d49',
|
||||
|
||||
'#88b053', // Grass
|
||||
'#88b053',
|
||||
|
||||
'#7a87c6', // vegetation
|
||||
'#7a87c6',
|
||||
|
||||
'#e49635', // Crops
|
||||
'#e49635',
|
||||
|
||||
'#dfc35a', // shrub
|
||||
'#dfc35a',
|
||||
|
||||
'#c4281b', // Built Area
|
||||
'#c4281b',
|
||||
|
||||
'#a59b8f', // Bare ground
|
||||
'#a59b8f',
|
||||
|
||||
'#a8ebff', // Snow
|
||||
'#a8ebff',
|
||||
|
||||
'#616161', // Clouds
|
||||
'#616161'
|
||||
];
|
||||
const positions = [
|
||||
0.0,
|
||||
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 () => {
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -103,10 +51,18 @@ export default () => {
|
|||
domain: [ 0.001, 11.001 ],
|
||||
clampLow: false,
|
||||
rampColors: {
|
||||
colors: colorList,
|
||||
positions
|
||||
// colors: ['#f00', '#f00'],
|
||||
// positions: [0, 1]
|
||||
// colors: colorList,
|
||||
// positions
|
||||
// 'Water': '#419bdf',
|
||||
// 'Tree': '#397d49',
|
||||
// 'Grass': '#88b053',
|
||||
// 'vegetation': '#7a87c6',
|
||||
// 'Crops': '#e49635',
|
||||
// 'shrub': '#dfc35a',
|
||||
// 'Built Area': '#c4281b',
|
||||
// 'Bare ground': '#a59b8f',
|
||||
// 'Snow': '#a8ebff',
|
||||
// 'Clouds': '#616161',
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -6,7 +6,11 @@ import {
|
|||
TYPES,
|
||||
} from '@antv/l7-core';
|
||||
|
||||
import { generateColorRamp, IColorRamp } from '@antv/l7-utils';
|
||||
import {
|
||||
generateColorRamp,
|
||||
generateColorRampKey,
|
||||
IColorRamp,
|
||||
} from '@antv/l7-utils';
|
||||
|
||||
export default class TextureService implements ITextureService {
|
||||
private layer: ILayer;
|
||||
|
@ -22,13 +26,14 @@ export default class TextureService implements ITextureService {
|
|||
}
|
||||
public getColorTexture(colorRamp: IColorRamp) {
|
||||
// TODO 支持传入图片
|
||||
const currentkey = this.getTextureKey(colorRamp);
|
||||
if (this.key === currentkey) {
|
||||
const currentKey = generateColorRampKey(colorRamp);
|
||||
|
||||
if (this.key === currentKey) {
|
||||
return this.colorTexture;
|
||||
} else {
|
||||
this.createColorTexture(colorRamp);
|
||||
}
|
||||
this.key = currentkey;
|
||||
this.key = currentKey;
|
||||
return this.colorTexture;
|
||||
}
|
||||
|
||||
|
@ -46,15 +51,11 @@ export default class TextureService implements ITextureService {
|
|||
}
|
||||
|
||||
public setColorTexture(texture: ITexture2D, colorRamp: IColorRamp) {
|
||||
this.key = this.getTextureKey(colorRamp);
|
||||
this.key = generateColorRampKey(colorRamp);
|
||||
this.colorTexture = texture;
|
||||
}
|
||||
|
||||
public destroy() {
|
||||
this.colorTexture?.destroy();
|
||||
}
|
||||
|
||||
private getTextureKey(colorRamp: IColorRamp): string {
|
||||
return `${colorRamp.colors.join('_')}_${colorRamp.positions.join('_')}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,36 +51,13 @@ layer.animate(true);
|
|||
|
||||
```js
|
||||
const rampColors = {
|
||||
colors: [
|
||||
'#3288bd',
|
||||
'#66c2a5',
|
||||
'#abdda4',
|
||||
'#e6f598',
|
||||
'#fee08b',
|
||||
'#fdae61',
|
||||
'#f46d43',
|
||||
'#d53e4f',
|
||||
],
|
||||
positions: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1.0],
|
||||
0.0: '#c6dbef',
|
||||
0.1: '#9ecae1',
|
||||
0.2: '#6baed6',
|
||||
0.3: '#4292c6',
|
||||
0.4: '#2171b5',
|
||||
0.5: '#084594',
|
||||
};
|
||||
```
|
||||
|
||||
#### rampColors
|
||||
|
||||
- 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],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
[在线案例](/examples/wind/basic#wind)
|
||||
|
|
|
@ -35,12 +35,14 @@ layer.style({
|
|||
|
||||
#### rampColors
|
||||
|
||||
- colors 颜色数组
|
||||
- positions 数据区间
|
||||
1. 连续色带,根据 `colors` 和 `positions` 设置色带。
|
||||
|
||||
- `colors` 颜色数组
|
||||
- `positions` 数据区间
|
||||
|
||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
||||
|
||||
⚠️ colors, positions 的长度要相同
|
||||
⚠️ `colors`, `positions` 的长度要相同。
|
||||
|
||||
```javascript
|
||||
layer.style({
|
||||
|
@ -51,6 +53,76 @@ layer.style({
|
|||
});
|
||||
```
|
||||
|
||||
2. 枚举色带
|
||||
枚举模式下色带不再是连续的,而是分段的,同时用户可以选择直接传入颜色或者指定具体的分布。
|
||||
|
||||
- 直接传入
|
||||
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: '#f00',
|
||||
c2: '#ff0',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
c1 和 c2 平均分布,前一半色带为 #f00,后一半为 #ff0。
|
||||
|
||||
- 指定具体的分布
|
||||
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: [0.3, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
c1 和 c2 三七分布,前三色带为 #f00,后七为 #ff0。
|
||||
|
||||
- 混合使用
|
||||
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: '#0f0',
|
||||
c3: [0.7, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
在混合使用的情况下,使用直接传入方式指定的色值会填满空隙,上面的分布 c1:c2:c3 为 3:4:3
|
||||
|
||||
- 默认色
|
||||
当用户仅指定部分色值分布或者使用错误的颜色值时,其余色值用默认色进行填充,可以动过 default 指定默认色,未指定时默认色为 #fff。
|
||||
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
},
|
||||
});
|
||||
|
||||
// => 上面的写法在内部会被默认填充
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#fff' // 等价写法
|
||||
},
|
||||
});
|
||||
|
||||
layer.style({
|
||||
rampColors: {
|
||||
default: '#ff0', // 指定默认填充色
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#ff0' // 等价写法
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### hexagon
|
||||
|
||||
绘制蜂窝热力图。
|
||||
|
|
|
@ -21,12 +21,13 @@ layer.style({
|
|||
|
||||
#### rampColors
|
||||
|
||||
- colors 颜色数组
|
||||
- positions 数据区间
|
||||
1. 连续色带,根据 `colors` 和 `positions` 设置色带。
|
||||
- `colors` 颜色数组
|
||||
- `positions` 数据区间
|
||||
|
||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
||||
|
||||
⚠️ colors, positions 的长度要相同
|
||||
⚠️ `colors`, `positions` 的长度要相同。
|
||||
|
||||
```javascript
|
||||
layer.style({
|
||||
|
@ -35,4 +36,66 @@ layer.style({
|
|||
positions: [0, 0.2, 0.4, 0.6, 0.8, 1.0],
|
||||
},
|
||||
});
|
||||
```
|
||||
2. 枚举色带
|
||||
枚举模式下色带不再是连续的,而是分段的,同时用户可以选择直接传入颜色或者指定具体的分布。
|
||||
|
||||
- 直接传入
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: '#f00',
|
||||
c2: '#ff0'
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 平均分布,前一半色带为 #f00,后一半为 #ff0。
|
||||
|
||||
- 指定具体的分布
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: [0.3, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 三七分布,前三色带为 #f00,后七为 #ff0。
|
||||
|
||||
- 混合使用
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: '#0f0',
|
||||
c3: [0.7, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
在混合使用的情况下,使用直接传入方式指定的色值会填满空隙,上面的分布 c1:c2:c3 为 3:4:3
|
||||
|
||||
- 默认色
|
||||
当用户仅指定部分色值分布或者使用错误的颜色值时,其余色值用默认色进行填充,可以动过 default 指定默认色,未指定时默认色为 #fff。
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
},
|
||||
});
|
||||
|
||||
// => 上面的写法在内部会被默认填充
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#fff' // 等价写法
|
||||
},
|
||||
});
|
||||
|
||||
layer.style({
|
||||
rampColors: {
|
||||
default: '#ff0', // 指定默认填充色
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#ff0' // 等价写法
|
||||
},
|
||||
});
|
||||
```
|
|
@ -19,12 +19,13 @@ layer.style({
|
|||
|
||||
#### rampColors
|
||||
|
||||
- colors 颜色数组
|
||||
- positions 数据区间
|
||||
1. 连续色带,根据 `colors` 和 `positions` 设置色带。
|
||||
- `colors` 颜色数组
|
||||
- `positions` 数据区间
|
||||
|
||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
||||
|
||||
⚠️ colors, positions 的长度要相同
|
||||
⚠️ `colors`, `positions` 的长度要相同。
|
||||
|
||||
```javascript
|
||||
layer.style({
|
||||
|
@ -34,3 +35,65 @@ layer.style({
|
|||
},
|
||||
});
|
||||
```
|
||||
2. 枚举色带
|
||||
枚举模式下色带不再是连续的,而是分段的,同时用户可以选择直接传入颜色或者指定具体的分布。
|
||||
|
||||
- 直接传入
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: '#f00',
|
||||
c2: '#ff0'
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 平均分布,前一半色带为 #f00,后一半为 #ff0。
|
||||
|
||||
- 指定具体的分布
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: [0.3, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 三七分布,前三色带为 #f00,后七为 #ff0。
|
||||
|
||||
- 混合使用
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: '#0f0',
|
||||
c3: [0.7, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
在混合使用的情况下,使用直接传入方式指定的色值会填满空隙,上面的分布 c1:c2:c3 为 3:4:3
|
||||
|
||||
- 默认色
|
||||
当用户仅指定部分色值分布或者使用错误的颜色值时,其余色值用默认色进行填充,可以动过 default 指定默认色,未指定时默认色为 #fff。
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
},
|
||||
});
|
||||
|
||||
// => 上面的写法在内部会被默认填充
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#fff' // 等价写法
|
||||
},
|
||||
});
|
||||
|
||||
layer.style({
|
||||
rampColors: {
|
||||
default: '#ff0', // 指定默认填充色
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#ff0' // 等价写法
|
||||
},
|
||||
});
|
||||
```
|
||||
|
|
|
@ -23,12 +23,13 @@ ps:rgb 多通道栅格不支持
|
|||
|
||||
#### rampColors
|
||||
|
||||
- colors 颜色数组
|
||||
- positions 数据区间
|
||||
1. 连续色带,根据 `colors` 和 `positions` 设置色带。
|
||||
- `colors` 颜色数组
|
||||
- `positions` 数据区间
|
||||
|
||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
||||
|
||||
⚠️ colors, positions 的长度要相同
|
||||
⚠️ `colors`, `positions` 的长度要相同。
|
||||
|
||||
```javascript
|
||||
layer.style({
|
||||
|
@ -38,6 +39,68 @@ layer.style({
|
|||
},
|
||||
});
|
||||
```
|
||||
2. 枚举色带
|
||||
枚举模式下色带不再是连续的,而是分段的,同时用户可以选择直接传入颜色或者指定具体的分布。
|
||||
|
||||
- 直接传入
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: '#f00',
|
||||
c2: '#ff0'
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 平均分布,前一半色带为 #f00,后一半为 #ff0。
|
||||
|
||||
- 指定具体的分布
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: [0.3, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 三七分布,前三色带为 #f00,后七为 #ff0。
|
||||
|
||||
- 混合使用
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: '#0f0',
|
||||
c3: [0.7, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
在混合使用的情况下,使用直接传入方式指定的色值会填满空隙,上面的分布 c1:c2:c3 为 3:4:3
|
||||
|
||||
- 默认色
|
||||
当用户仅指定部分色值分布或者使用错误的颜色值时,其余色值用默认色进行填充,可以动过 default 指定默认色,未指定时默认色为 #fff。
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
},
|
||||
});
|
||||
|
||||
// => 上面的写法在内部会被默认填充
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#fff' // 等价写法
|
||||
},
|
||||
});
|
||||
|
||||
layer.style({
|
||||
rampColors: {
|
||||
default: '#ff0', // 指定默认填充色
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#ff0' // 等价写法
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
ps:⚠️ color, position 的长度要相同,rgb 多通道栅格不支持
|
||||
|
||||
|
|
|
@ -100,12 +100,13 @@ layer.size('weight', [0, 1]);
|
|||
|
||||
#### rampColors
|
||||
|
||||
1. 连续色带,根据 `colors` 和 `positions` 设置色带。
|
||||
- `colors` 颜色数组
|
||||
- `positions` 数据区间
|
||||
|
||||
配置值域映射颜色的色带,值域的范围为 `[0 - 1]`, 对应的我们需要为每一个 `position` 位置设置一个颜色值。
|
||||
|
||||
⚠️ colors, positions 的长度要相同
|
||||
⚠️ `colors`, `positions` 的长度要相同。
|
||||
|
||||
```javascript
|
||||
layer.style({
|
||||
|
@ -115,3 +116,65 @@ layer.style({
|
|||
},
|
||||
});
|
||||
```
|
||||
2. 枚举色带
|
||||
枚举模式下色带不再是连续的,而是分段的,同时用户可以选择直接传入颜色或者指定具体的分布。
|
||||
|
||||
- 直接传入
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: '#f00',
|
||||
c2: '#ff0'
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 平均分布,前一半色带为 #f00,后一半为 #ff0。
|
||||
|
||||
- 指定具体的分布
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: [0.3, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
c1 和 c2 三七分布,前三色带为 #f00,后七为 #ff0。
|
||||
|
||||
- 混合使用
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
c2: '#0f0',
|
||||
c3: [0.7, 1.0, '#ff0']
|
||||
},
|
||||
});
|
||||
```
|
||||
在混合使用的情况下,使用直接传入方式指定的色值会填满空隙,上面的分布 c1:c2:c3 为 3:4:3
|
||||
|
||||
- 默认色
|
||||
当用户仅指定部分色值分布或者使用错误的颜色值时,其余色值用默认色进行填充,可以动过 default 指定默认色,未指定时默认色为 #fff。
|
||||
```js
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
},
|
||||
});
|
||||
|
||||
// => 上面的写法在内部会被默认填充
|
||||
layer.style({
|
||||
rampColors: {
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#fff' // 等价写法
|
||||
},
|
||||
});
|
||||
|
||||
layer.style({
|
||||
rampColors: {
|
||||
default: '#ff0', // 指定默认填充色
|
||||
c1: [0, 0.3 '#f00'],
|
||||
defaultFill: '#ff0' // 等价写法
|
||||
},
|
||||
});
|
||||
```
|
||||
|
|
|
@ -33,28 +33,6 @@ const colorList = [
|
|||
'#616161', // Clouds
|
||||
'#616161'
|
||||
];
|
||||
const positions = [
|
||||
0.0,
|
||||
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({
|
||||
id: 'map',
|
||||
|
@ -100,8 +78,16 @@ scene.on('loaded', () => {
|
|||
domain: [ 0.001, 11.001 ],
|
||||
clampLow: false,
|
||||
rampColors: {
|
||||
colors: colorList,
|
||||
positions
|
||||
'Water': '#419bdf',
|
||||
'Tree': '#397d49',
|
||||
'Grass': '#88b053',
|
||||
'vegetation': '#7a87c6',
|
||||
'Crops': '#e49635',
|
||||
'shrub': '#dfc35a',
|
||||
'Built Area': '#c4281b',
|
||||
'Bare ground': '#a59b8f',
|
||||
'Snow': '#a8ebff',
|
||||
'Clouds': '#616161',
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
import {
|
||||
generateColorRamp,
|
||||
generateColorRampKey,
|
||||
formatCategory,
|
||||
IColorRamp,
|
||||
} from '../src/color';
|
||||
const colors = [
|
||||
'#419bdf', // Water
|
||||
'#419bdf',
|
||||
|
||||
'#397d49', // Tree
|
||||
'#397d49',
|
||||
|
||||
'#88b053', // Grass
|
||||
'#88b053',
|
||||
|
||||
'#7a87c6', // vegetation
|
||||
'#7a87c6',
|
||||
|
||||
'#e49635', // Crops
|
||||
'#e49635',
|
||||
|
||||
'#dfc35a', // shrub
|
||||
'#dfc35a',
|
||||
|
||||
'#c4281b', // Built Area
|
||||
'#c4281b',
|
||||
|
||||
'#a59b8f', // Bare ground
|
||||
'#a59b8f',
|
||||
|
||||
'#a8ebff', // Snow
|
||||
'#a8ebff',
|
||||
|
||||
'#616161', // Clouds
|
||||
'#616161'
|
||||
];
|
||||
const positions = [
|
||||
0.0,
|
||||
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 rampColors = {
|
||||
'Water': '#419bdf',
|
||||
'Tree': '#397d49',
|
||||
'Grass': '#88b053',
|
||||
'vegetation': '#7a87c6',
|
||||
'Crops': '#e49635',
|
||||
'shrub': '#dfc35a',
|
||||
'Built Area': '#c4281b',
|
||||
'Bare ground': '#a59b8f',
|
||||
'Snow': '#a8ebff',
|
||||
'Clouds': '#616161',
|
||||
} as IColorRamp;
|
||||
describe('generateColorTexture', () => {
|
||||
it('key', () => {
|
||||
const key1 = generateColorRampKey(rampColors);
|
||||
const key2 = generateColorRampKey({
|
||||
colors,
|
||||
positions
|
||||
})
|
||||
|
||||
expect(key1).toEqual('#419bdf_#397d49_#88b053_#7a87c6_#e49635_#dfc35a_#c4281b_#a59b8f_#a8ebff_#616161_#616161_0_0.1_0.1_0.2_0.2_0.30000000000000004_0.30000000000000004_0.4_0.4_0.5_0.5_0.6000000000000001_0.6000000000000001_0.7000000000000001_0.7000000000000001_0.8_0.8_0.9_0.9_1_0.9_1');
|
||||
expect(key2).toEqual('#419bdf_#419bdf_#397d49_#397d49_#88b053_#88b053_#7a87c6_#7a87c6_#e49635_#e49635_#dfc35a_#dfc35a_#c4281b_#c4281b_#a59b8f_#a59b8f_#a8ebff_#a8ebff_#616161_#616161_0_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');
|
||||
});
|
||||
|
||||
it('texture', () => {
|
||||
const d1 = generateColorRamp({
|
||||
c1: '#f00',
|
||||
c2: '#ff0'
|
||||
})
|
||||
expect(d1.data.length).toEqual(1024);
|
||||
})
|
||||
|
||||
it('cat', () => {
|
||||
const list = formatCategory({
|
||||
water: '#f00',
|
||||
land: [0.2, 0.3, '#ff0'],
|
||||
land2: [0.35, 0.4, '#ddd'],
|
||||
wood: '#0f0',
|
||||
city: '#ccc',
|
||||
city2: [0.9, 0.95, '#0ff']
|
||||
})
|
||||
expect(list).toEqual([
|
||||
[ 0, 0.2, '#f00' ],
|
||||
[ 0.2, 0.3, '#ff0' ],
|
||||
[ 0.3, 0.35, null ],
|
||||
[ 0.35, 0.4, '#ddd' ],
|
||||
[ 0.4, 0.65, '#0f0' ],
|
||||
[ 0.65, 0.9, '#ccc' ],
|
||||
[ 0.9, 1, '#0ff' ]
|
||||
])
|
||||
})
|
||||
});
|
|
@ -1,9 +1,10 @@
|
|||
import * as d3 from 'd3-color';
|
||||
import { $window, isMini } from './mini-adapter';
|
||||
export interface IColorRamp {
|
||||
positions: number[];
|
||||
colors: string[];
|
||||
positions?: number[];
|
||||
colors?: string[];
|
||||
weights?: number[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export function isColor(str: any) {
|
||||
|
@ -51,39 +52,129 @@ export interface IImagedata {
|
|||
height: number;
|
||||
}
|
||||
|
||||
export function generateColorRamp(
|
||||
colorRamp: IColorRamp,
|
||||
): ImageData | IImagedata {
|
||||
let canvas = $window.document.createElement('canvas');
|
||||
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||
canvas.width = 256;
|
||||
canvas.height = 1;
|
||||
let data = null;
|
||||
enum ColorRampType {
|
||||
LINEAR = 'linear',
|
||||
CAT = 'cat'
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
type ColorCategory = [number, number, string];
|
||||
|
||||
function getColorRampType(colorRamp: IColorRamp) {
|
||||
if(colorRamp.colors && colorRamp.positions) {
|
||||
return ColorRampType.LINEAR;
|
||||
} else {
|
||||
// draw linear color
|
||||
const gradient = ctx.createLinearGradient(0, 0, 256, 1);
|
||||
return ColorRampType.CAT;
|
||||
}
|
||||
}
|
||||
|
||||
const min = colorRamp.positions[0];
|
||||
const max = colorRamp.positions[colorRamp.positions.length - 1];
|
||||
for (let i = 0; i < colorRamp.colors.length; ++i) {
|
||||
const value = (colorRamp.positions[i] - min) / (max - min);
|
||||
gradient.addColorStop(value, colorRamp.colors[i]);
|
||||
function isValid(category: any) {
|
||||
// valid category - [number, number, string?] || string
|
||||
if(typeof category === 'string') return true;
|
||||
if(Array.isArray(category) && category.length === 3) {
|
||||
return typeof category[0] === 'number' &&
|
||||
typeof category[1] === 'number' &&
|
||||
typeof category[2] === 'string'
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function formatCategory(colorRamp: IColorRamp) {
|
||||
/**
|
||||
* {
|
||||
* a: '#f00',
|
||||
* b: [0.2, 0.3, #ff0],
|
||||
* c: [0.3, 0.4, #0f0],
|
||||
* d: '#fff',
|
||||
* e: #0ff
|
||||
* }
|
||||
*/
|
||||
|
||||
const keywords = ['colors', 'position', 'default'];
|
||||
|
||||
/** categories
|
||||
* [
|
||||
* [0, 0.2 #f00],
|
||||
* [0.2, 0.3, #ff0],
|
||||
* [0.3, 0.4, #ff0],
|
||||
* [0.4, 1.0, #fff, #0ff]
|
||||
* ]
|
||||
*/
|
||||
const categories: any[]= [];
|
||||
let range = 0;
|
||||
Object.keys(colorRamp)
|
||||
.filter(key => keywords.indexOf(key) < 0)
|
||||
.filter(key => isValid(colorRamp[key]))
|
||||
.forEach((key) => {
|
||||
const category = colorRamp[key];
|
||||
const last = categories[categories.length - 1];
|
||||
if(Array.isArray(category)) {
|
||||
// category === [number, number, color]
|
||||
if(last) {
|
||||
if(last[1] === -1) {
|
||||
last[1] = category[0];
|
||||
} else if(last[1] < category[0]){
|
||||
categories.push([last[1], category[0], null])
|
||||
}
|
||||
}
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, 256, 1);
|
||||
range = category[1];
|
||||
categories.push(category);
|
||||
} else {
|
||||
// category === color
|
||||
if(last && last[1] === -1) {
|
||||
last.push(category)
|
||||
} else {
|
||||
categories.push([range, -1, category])
|
||||
}
|
||||
}
|
||||
return category
|
||||
})
|
||||
|
||||
// incase all raw color
|
||||
if(categories.length > 0) {
|
||||
categories[categories.length - 1][1] = 1;
|
||||
}
|
||||
|
||||
const validCategories: ColorCategory[] = [];
|
||||
categories.forEach(category => {
|
||||
const [start, end, ...colors] = category;
|
||||
const step = (end - start)/colors.length;
|
||||
colors.forEach((color: string, index: number) => {
|
||||
validCategories.push([start + index * step, start + (index + 1) * step, color])
|
||||
})
|
||||
})
|
||||
return validCategories;
|
||||
}
|
||||
|
||||
// draw cat color
|
||||
function drawCat(colorRamp: IColorRamp, ctx: CanvasRenderingContext2D) {
|
||||
// 色带未指定部分的默认颜色
|
||||
const defaultColor = colorRamp.default || '#fff';
|
||||
const canvasWidth = 256;
|
||||
const categories = formatCategory(colorRamp);
|
||||
categories.forEach(([start, end, color]) => {
|
||||
const drawColor = isColor(color) ? color : defaultColor;
|
||||
ctx.fillStyle = drawColor;
|
||||
ctx.fillRect(start * canvasWidth, 0, end * canvasWidth, 1);
|
||||
})
|
||||
}
|
||||
|
||||
// draw linear color
|
||||
function drawLinear(colorRamp: IColorRamp, ctx: CanvasRenderingContext2D) {
|
||||
const gradient = ctx.createLinearGradient(0, 0, 256, 1);
|
||||
const positions = colorRamp.positions as number[];
|
||||
const colors = colorRamp.colors as string[];
|
||||
const min = positions[0];
|
||||
const max = positions[positions.length - 1];
|
||||
for (let i = 0; i < colors.length; ++i) {
|
||||
const value = (positions[i] - min) / (max - min);
|
||||
gradient.addColorStop(value, colors[i]);
|
||||
}
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, 256, 1);
|
||||
}
|
||||
|
||||
function getColorData(ctx: CanvasRenderingContext2D) {
|
||||
let data = null;
|
||||
if (!isMini) {
|
||||
data = ctx.getImageData(0, 0, 256, 1).data;
|
||||
// 使用 createImageData 替代 new ImageData、兼容 IE11
|
||||
|
@ -94,17 +185,69 @@ export function generateColorRamp(
|
|||
imageData.data[i + 2] = data[i + 2];
|
||||
imageData.data[i + 3] = data[i + 3];
|
||||
}
|
||||
// @ts-ignore
|
||||
canvas = null;
|
||||
// @ts-ignore
|
||||
ctx = null;
|
||||
return imageData;
|
||||
} else {
|
||||
data = new Uint8ClampedArray(ctx.getImageData(0, 0, 256, 1).data);
|
||||
// @ts-ignore
|
||||
canvas = null;
|
||||
// @ts-ignore
|
||||
ctx = null;
|
||||
return { data, width: 256, height: 1 };
|
||||
}
|
||||
}
|
||||
|
||||
export function generateColorRampKey(colorRamp: IColorRamp) {
|
||||
const type = getColorRampType(colorRamp);
|
||||
switch(type) {
|
||||
case ColorRampType.CAT:
|
||||
const defaultColor = colorRamp.default || '#fff';
|
||||
const categories = formatCategory(colorRamp);
|
||||
const fields: string[] = [];
|
||||
const values: string[] = [];
|
||||
categories.forEach(category => {
|
||||
const start = category[0];
|
||||
const end = category[1];
|
||||
const color = category[2];
|
||||
fields.push(String(start));
|
||||
fields.push(String(end));
|
||||
const drawColor = isColor(color) ? color : defaultColor;
|
||||
values.push(drawColor)
|
||||
})
|
||||
if(categories.length > 0) {
|
||||
fields.push(String(categories[categories.length - 1][0]));
|
||||
fields.push(String(categories[categories.length - 1][1]));
|
||||
values.push(categories[categories.length - 1][2]);
|
||||
}
|
||||
return [...values, ...fields].join('_');
|
||||
case ColorRampType.LINEAR:
|
||||
return `${colorRamp?.colors?.join('_')}_${colorRamp?.positions?.join('_')}`;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* init color texture for data range
|
||||
* @param colorRamp
|
||||
* @returns
|
||||
*/
|
||||
export function generateColorRamp(
|
||||
colorRamp: IColorRamp,
|
||||
): ImageData | IImagedata {
|
||||
let canvas = $window.document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
||||
canvas.width = 256;
|
||||
canvas.height = 1;
|
||||
|
||||
const type = getColorRampType(colorRamp);
|
||||
switch(type) {
|
||||
case ColorRampType.CAT:
|
||||
drawCat(colorRamp, ctx);
|
||||
break;
|
||||
case ColorRampType.LINEAR:
|
||||
drawLinear(colorRamp, ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
const colorData = getColorData(ctx);
|
||||
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
canvas = null;
|
||||
return colorData;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue