diff --git a/dev-demos/bugs/polygon/demos/polygon.tsx b/dev-demos/bugs/polygon/demos/polygon.tsx index abe71ce99f..be47c6c891 100644 --- a/dev-demos/bugs/polygon/demos/polygon.tsx +++ b/dev-demos/bugs/polygon/demos/polygon.tsx @@ -2530,6 +2530,9 @@ export default () => { // 'rgb(8,81,156)' // ] // ) + .scale('num',{ + type:'quantile' + }) .color("num", ["#E8F1FF", "#A8BDEC", "#688DE4", "#3461CA", "#23396E"]) .shape("fill") .select({ @@ -2539,7 +2542,7 @@ export default () => { .style({ opacity: 1 }); - + // 默认高亮选中北京 chinaPolygonLayer.on("add", () => { setTimeout(() => { @@ -2567,6 +2570,14 @@ export default () => { scene.addLayer(chinaPolygonLayer); scene.addLayer(layer2); + setTimeout(()=>{ + chinaPolygonLayer.scale('num',{ + type:'quantize' + }) + // chinaPolygonLayer.color('num',['#ffffb2','#fed976','#feb24c','#fd8d3c','#f03b20','#bd0026']) + scene.render() + console.log('render') + },3000) }); fetch( "https://gw.alipayobjects.com/os/bmw-prod/c4a6aa9d-8923-4193-a695-455fd8f6638c.json" // 标注数据 diff --git a/dev-demos/bugs/polygon/demos/scale.tsx b/dev-demos/bugs/polygon/demos/scale.tsx index f50098aae1..96e258e1b6 100644 --- a/dev-demos/bugs/polygon/demos/scale.tsx +++ b/dev-demos/bugs/polygon/demos/scale.tsx @@ -243,7 +243,6 @@ const data = { } ] } -console.log(data); export default () => { useEffect(() => { const scene = new Scene({ diff --git a/dev-demos/draw/demo/drawpolygon.tsx b/dev-demos/draw/demo/drawpolygon.tsx new file mode 100644 index 0000000000..f7699d176d --- /dev/null +++ b/dev-demos/draw/demo/drawpolygon.tsx @@ -0,0 +1,41 @@ +import { Scene } from '@antv/l7'; +import { DrawPolygon } from '@antv/l7-draw'; +import { Map } from '@antv/l7-maps'; +import React, { useEffect, useState } from 'react'; + +const id = String(Math.random()); + +const Demo: React.FC = () => { + const [, setLineDrawer] = useState(null); + + useEffect(() => { + const scene = new Scene({ + id, + map: new Map({ + center: [120.151634, 30.244831], + pitch: 0, + style: 'dark', + zoom: 10, + }), + }); + scene.on('mousedown', () => { + console.log('mousedown'); + }); + + scene.on('loaded', () => { + const drawer = new DrawPolygon(scene, { + // liveUpdate: true, + }); + setLineDrawer(drawer); + drawer.enable(); + }); + }, []); + + return ( +
+
+
+ ); +}; + +export default Demo; diff --git a/dev-demos/draw/index.md b/dev-demos/draw/line_area.md similarity index 87% rename from dev-demos/draw/index.md rename to dev-demos/draw/line_area.md index 49bd9a7afa..6029fe4375 100644 --- a/dev-demos/draw/index.md +++ b/dev-demos/draw/line_area.md @@ -3,7 +3,7 @@ title: 展示距离和面积 order: 3 group: path: /polygon - title: 绘制面 + title: 图形绘制 order: 3 --- diff --git a/dev-demos/draw/polygon.md b/dev-demos/draw/polygon.md new file mode 100644 index 0000000000..1a64562d04 --- /dev/null +++ b/dev-demos/draw/polygon.md @@ -0,0 +1,9 @@ +--- +title: 绘制面 +order: 3 +group: + path: /polygon + order: 3 +--- + + diff --git a/dev-demos/gallery/scale/index.md b/dev-demos/gallery/scale/index.md index 12e0018aef..cd6448609a 100644 --- a/dev-demos/gallery/scale/index.md +++ b/dev-demos/gallery/scale/index.md @@ -15,7 +15,7 @@ Range 和 domain 是 Scale 中非常重要的两个参数 | 分类 | cat、timeCat | | 常量 | identity | -在使用 `L7` 开发过程中默认情况下不需要进行度量的配置,因为 `G2` 代码内部已经根据数据的形式对度量进行了假设,其计算过程如下: +在使用 `L7` 开发过程中默认情况下不需要进行度量的配置,因为 `L7` 代码内部已经根据数据的形式对度量进行了假设,其计算过程如下: 查看用户是否制定了对应字段的数据类型 (`type`) 如果没有,判断字段的第一条数据的字段类型 diff --git a/packages/core/src/services/layer/IStyleAttributeService.ts b/packages/core/src/services/layer/IStyleAttributeService.ts index 74663318bb..9ad3a78a4a 100644 --- a/packages/core/src/services/layer/IStyleAttributeService.ts +++ b/packages/core/src/services/layer/IStyleAttributeService.ts @@ -194,6 +194,7 @@ export interface IStyleAttributeService { registerStyleAttribute( options: Partial, ): IStyleAttribute; + updateScaleAttribute(scale: IScaleOptions):void; updateStyleAttribute( attributeName: string, attributeOptions: Partial, diff --git a/packages/core/src/services/layer/StyleAttributeService.ts b/packages/core/src/services/layer/StyleAttributeService.ts index 206c109537..4b1067c209 100644 --- a/packages/core/src/services/layer/StyleAttributeService.ts +++ b/packages/core/src/services/layer/StyleAttributeService.ts @@ -9,6 +9,7 @@ import { IRendererService } from '../renderer/IRendererService'; import { ILayer, IWorkerOption } from './ILayerService'; import { IAttributeScale, + IScaleOptions, IEncodeFeature, IStyleAttribute, IStyleAttributeInitializationOptions, @@ -70,13 +71,24 @@ export default class StyleAttributeService implements IStyleAttributeService { return attributeToUpdate; } + public updateScaleAttribute(scaleOption: IScaleOptions) { + this.attributes.forEach((attr:IStyleAttribute)=>{ + const name = attr.name; + const field = attr.scale?.field as string; + if(scaleOption[name] || (field && scaleOption[field])) { // 字段类型和映射类型 + attr.needRescale = true; + attr.needRemapping = true; + attr.needRegenerateVertices = true; + } + }) + + } + public updateStyleAttribute( attributeName: string, options: Partial, updateOptions?: Partial, ) { - - let attributeToUpdate = this.getLayerStyleAttribute(attributeName); if (!attributeToUpdate) { attributeToUpdate = this.registerStyleAttribute({ diff --git a/packages/layers/src/core/BaseLayer.ts b/packages/layers/src/core/BaseLayer.ts index aa90f710a0..14feb807d5 100644 --- a/packages/layers/src/core/BaseLayer.ts +++ b/packages/layers/src/core/BaseLayer.ts @@ -672,6 +672,11 @@ export default class BaseLayer } else { this.scaleOptions[field] = cfg; } + if (this.styleAttributeService) { + const scaleOptions = isObject(field) ? field : { [field]: cfg }; + this.styleAttributeService.updateScaleAttribute(scaleOptions); + } + return this; } @@ -1103,7 +1108,6 @@ export default class BaseLayer public getScaleOptions() { return this.scaleOptions; } - public encodeDataLength: number = 0; public setEncodedData(encodedData: IEncodeFeature[]) { this.encodedData = encodedData; diff --git a/packages/site/docs/api/base_layer/base.zh.md b/packages/site/docs/api/base_layer/base.zh.md index dd831f1a25..10542885fc 100644 --- a/packages/site/docs/api/base_layer/base.zh.md +++ b/packages/site/docs/api/base_layer/base.zh.md @@ -14,6 +14,7 @@ L7 Layer 接口设计遵循图形语法,所有图层都继承于基类(baseL ```javascript const layer = new BaseLayer(option) // option - 传入构造函数的参数对象,提供 layer 的初始状态 .source(...) // 传入图层需要的数据以及相关的解析器 + .filter() // 数据过滤方法 .shape(...) // 为图层指定具体的形状,如:circle/triangle 等 .color(...) // 指定图层的颜色配置 .texture(...) // 指定图层引用的纹理 diff --git a/packages/site/docs/common/layer/layer_encode.md b/packages/site/docs/common/layer/layer_encode.md index b74fb1c0a7..c5a3f291a6 100644 --- a/packages/site/docs/common/layer/layer_encode.md +++ b/packages/site/docs/common/layer/layer_encode.md @@ -1,5 +1,5 @@ -### source +### source 数据 设置图层数据以及解析配置 `source(data, config)`。 @@ -38,14 +38,63 @@ layer.source(data, { ], }); ``` +### cluster -### scale(field: string, scaleConfig: IScaleConfig) +我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 +#### getClusters(zoom: number): IFeatureCollection +获取指定缩放等级的聚合数据 + +- `zoom` 缩放等级 + +#### getClustersLeaves(id: string): IFeatureCollection + +根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 + +- `id` 聚合节点的 `id` + + +```ts +const source = layer.getSource(); +source.getClustersLeaves(id); +layer.on('click', (e) => { + console.log(source.getClustersLeaves(e.feature.cluster_id)); +}); + +``` + + +## scale 数据度量 + +Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale,并支持位置、形状、大小和颜色编码的映射。 + +在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: + +查看用户是否设置了 Scale,如果没有: + +判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: + +认为是常量为固定值 + +如果是数字则为 'linear'; + +如果是字符串类型 'cat'; + + +### scale + +![Scale 详细介绍](https://mp.weixin.qq.com/s/QyD1_ypu0PDwMxEz45v6Jg) + +参数: (field: string, scaleOptions: IscaleOptions) - `field` 指定 source 中传入的数据中用于映射的字段名 -- `scaleConfig` 列定义配置,对象类型 +- `scaleOptions` 列定义配置,对象类型 + - type scale 类型 + - unknown 未匹配颜色 可选 默认透明 + - domain 值域 可选 + ```javascript -interface IScaleConfig { +interface IscaleOptions { type: ScaleTypeName; domain?: any[]; ... @@ -59,19 +108,23 @@ layer.color('id', ['#f00', '#ff0']) }); ``` -### ScaleTypeName +#### 类型 -`scale` 的类型可以分为 `3` 类 `11` 种,不同 `Scale` 的差异在于 `domain->range` 的转换方法的不同。 -`range` 和 `domain` 是 `Scale` 中非常重要的两个参数。 + +Range 和 domain 是 Scale 中非常重要的两个参数 + +domain: 地图数据值的定义区间 +range:视觉值的区间 +不同Scale 的差异在于 domain->range 的转换方法的不同 - domain: 地图数据值的定义区间 - range:视觉值的区间定义 -| 数据类型 | 度量类型 | -| -------- | ------- | -| 连续 | linear、log、pow、time、sequential、quantize、quantile、threshold | -| 分类 | cat、time | -| 常量 | identity | +|数据类|度量类型| +|-----|------| +| 连续 | linear、log、pow | +| 连续分类 | quantize quantile,threshold,diverging | +| 分类 枚举 | cat | #### Cat @@ -102,7 +155,18 @@ layer.color('t', ['red', 'white', 'blue']); #### identify -常量度量 某个字段是不变的常量。 +数据值和映射值相同 +比如数据中value 字段记录了每个要素的颜色,数值既为要映射的结果值s + +``` +// 设置为 identify +layer.scale('value', { type: 'identify' }); + +// 或者 + +layer.scale('value'); // L7 能够自动推断为 identify + +``` #### linear @@ -131,58 +195,33 @@ layer.color('t', ['red', 'white', 'blue']); 1000 => "blue ``` -#### diverging || Sequential -用于返回给定的颜色数组的统一非有理 B-spline 插值器函数,该数组将转换为RGB颜色。 +#### diverging -```js -const scaleColors = d3interpolate.interpolateRgbBasis(colors); -``` +离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 -#### IScaleConfig -```js -interface IScaleConfig { - type: ScaleTypeName; - domain?: any[]; - range?: any[]; - neutral?: number; - field?: string; - unknown?: string; - ticks?: any[]; - nice?: boolean; - clamp?: boolean; - format?: () => any; -} -``` - -### cluster - -我们在使用 `cluster` 配置聚合图之后就可以使用一些聚合方法来获取对应参数。 -#### getClusters(zoom: number): IFeatureCollection - -获取指定缩放等级的聚合数据 - -- `zoom` 缩放等级 - -#### getClustersLeaves(id: string): IFeatureCollection - -根据 `id` 获取聚合节点的数据,每个聚合节点会有一个唯一 `ID`。 - -- `id` 聚合节点的 `id` - -```javascript -const source = layer.getSource(); -source.getClustersLeaves(id); -layer.on('click', (e) => { - console.log(source.getClustersLeaves(e.feature.cluster_id)); -}); -``` ## 视觉编码方法 可视化编码是将数据转换为可视形式的过程,L7 目前支持形状,大小,颜色 3 种视觉通道,你可以指定数据字段,为不同要素设置不同的图形属性。 案例 +### filter + +数据过滤方法,支持回调函数,将数据映射为true | false, 结果为true 时可见 + +```ts + +pointLayer.size('type', (type) => { + // 回调函数 + if (type === 'a') { + return false; + } + return true ; +}); +``` + + ### size 将数据值映射到图形的大小上的方法,size 方法具体的参数使用可以查看对应图层的详细文档 @@ -250,12 +289,16 @@ layer.color('type*value', (type, value) => { #### color(value) 参数:`value` :string + 只支持接收一个参数,value 可以是: - 映射至颜色属性的数据源字段名,如果数据源中不存在这个字段名的话,则按照常量进行解析,这个时候会使用 L7 默认提供的颜色。 - 也可以直接指定某一个具体的颜色值 color,如 '#fff', 'white','rgba(255,0,0,0.5)' ,rgb(255,0,1) 等。 +如果数据为映射到颜色,默认为透明色不显示,如果需要设置该颜色,需要在scale 中设置 + + 示例 ```javascript @@ -274,7 +317,11 @@ layer.color('white'); // 指定颜色 colors 的参数有以下情况:  如果为空,即未指定颜色的数组,那么使用内置的全局的颜色;如果需要指定颜色,则需要以数组格式传入,那么分类的颜色按照数组中的颜色确定。 ```javascript -layer.color('name'); // 使用默认的颜色 +layer.scale('name',{ + type:'quantile' + unknown:'#ccc' // 设置无效颜色 +}) +layer.color('name'); // 使用identity layer.color('name', ['red', 'blue']); // 使用传入的指定颜色 ``` diff --git a/packages/site/docs/common/layer/layer_texture.md b/packages/site/docs/common/layer/layer_texture.md index 9ce4b4e2f5..4d187d08e7 100644 --- a/packages/site/docs/common/layer/layer_texture.md +++ b/packages/site/docs/common/layer/layer_texture.md @@ -1,4 +1,4 @@ -### 纹理方法 +### texture 目前只在线图层上支持了纹理方法 diff --git a/packages/site/docs/common/layer/layer_update.md b/packages/site/docs/common/layer/layer_update.md index 4f55c1093f..09e4e9e318 100644 --- a/packages/site/docs/common/layer/layer_update.md +++ b/packages/site/docs/common/layer/layer_update.md @@ -2,21 +2,39 @@ 如果已经添加了图层,需要修改图层显示样式可以再次调用图形映射方法,然后调用 `scene.render()`更新渲染即可 -### 样式更新 +### scale 更新 + +重新调用scale 方法 + +```tsx +layer.scale('value',{ + type:'quantile' +}) +scene.render(); +``` + +### 数据映射 + +重新调用 color/size/filter/shape等方法 ```javascript layer.color('blue'); layer.size(10); -layer.style({}); + scene.render(); ``` -### shape 更新 -在在某些场景下切换 shape 的时候,我们需要重新构建图层元素的顶点构造。这意味着我们简单的改变当前图层的单一属性就达到更新图层的目的。 -L7 已经为某些图层的 shape 切换做了额外的处理,如 PointLayer 的 "circle" 切换 "cylinder" 等,具体哪些图层盒支持直接切换则需要用户查阅具体图层的文档。 +### layer.style -🌟 在不支持直接切换 shape 的时候建议重新创建图层 +```javascript +layer.style({ + opacity:1 + +}); + +scene.render(); +``` ### setData(data, option?: {}) diff --git a/packages/site/docs/tutorial/scale.en.md b/packages/site/docs/tutorial/scale.en.md new file mode 100644 index 0000000000..bd04b67789 --- /dev/null +++ b/packages/site/docs/tutorial/scale.en.md @@ -0,0 +1,5 @@ +--- +title: Scale +order: 1 +--- + \ No newline at end of file diff --git a/packages/site/docs/tutorial/scale.zh.md b/packages/site/docs/tutorial/scale.zh.md new file mode 100644 index 0000000000..1ad106c7f2 --- /dev/null +++ b/packages/site/docs/tutorial/scale.zh.md @@ -0,0 +1,212 @@ +--- +title: Scale 度量 +order: 2 +--- + + +## Scale 简介 + +Scale 度量是用于将地图数据值(数字、日期、类别等数据)转成视觉变量(颜色、大小、形状)。Scale 是数据可视化的基本元素,因为它们决定了数据视觉编码的方式。L7 目前支持连续、离散、枚举类型等常用的 Scale。 + +![L7 Scale](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*AOIvTpmPOmgAAAAAAAAAAAAADmJ7AQ/original) + +## Scale 中的两个重要概念: + +Range 和 Domain + +Domain: 地图数据值的定义区间 + +Range:视觉值的区间定义 + + + +不同 Scale 的差异在于 Domain-> Range 的转换方法不同 + +|数据类|度量类型| +|----|------| +| 连续 | linear、log、pow | +| 连续分类 | quantize quantile,threshold,diverging | +| 分类 枚举| cat | + + +## L7 Scale + +在使用 L7 过程中,默认情况下不需要进行 Scale 的配置,因为 L7 会根据数据类型对 scale 推断,推断过程如下: + +查看用户是否设置了 Scale,如果没有: + +判断字段的第一条数据的字段类型,如果数据中不存在对应的字段: + +认为是常量为固定值 + +如果是数字则为 'linear'; + +如果是字符串类型 'cat'; + +## Cat 枚举 + +Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。在 L7 如果判断字段的值为字符串,将认为是 Cat 类型并自动获取类型的唯一值,设置为 domain 。这样三种作物就会被一一映射成对应的颜色。 + +```tsx + +const data = [ + { + type:'A', + x: 110, + y:30 + }, + { + type:'B', + x: 110, + y:32 + }, + { + type:'C', + x: 110, + y:31 + } + ,{ + type:'D', + x: 111, + y:33 + }, + ,{ + type:'E', + x: 112, + y:30 + } + ,{ + type:'F', + x: 110, + y:30 + } +] +layer.color('type',['red','white','blue','yellow']) +``` + +如上面的代码所示,图层没有设置 Scale, L7 根据第一个数据"A"的类型 ,推断为枚举类型。同时取出该字段的去重后的所有值 ['A','B','C','D','E','F'] 设置为 scale 的 domain, 那么 range 就是对应的颜色 ['red','white','blue','yellow']。 + +![L7 scale Cat映射](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*rO53SYNk8hgAAAAAAAAAAAAADmJ7AQ/original) + +如果不设置 domain,L7 内部会自动计算 domain,domain 顺序跟数据顺序相关。如果希望固定domain 可自己设置 domain。domain 数值 和 range数值 一一对应。 + +``` + +layer.scale('type', { + type: 'cat', + domain: ['B', 'A', 'C', 'D'], +}); +layer.color('type', ['red', 'white', 'blue', 'yellow']); + +``` + +layer.scale('type', { + type: 'cat', + domain: ['B', 'A', 'C', 'D'], +}); +layer.color('type', ['red', 'white', 'blue', 'yellow']); +``` +![L7 Cat ](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*kyP2RpUXdGUAAAAAAAAAAAAADmJ7AQ/original) + +## Linear 连续线性 + +线性是连续数据的映射方法,数据和视觉值是通过线性方法计算的。如数据范围domain [0,1000] 线性映射到 range [red,blue] 渐变色,就是依据线性函完成一一转换。 + +![L7 Scale 线性]('https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*Z_rGRr-jgI0AAAAAAAAAAAAADmJ7AQ/original') + +```tsx +layer.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']) +``` +对于连续型 +数据 L7 默认会设置为 linear, domain为数据的min、max值。颜色会根据 range 颜色生成渐变色。linear +默认可不设置 domain 区间 + +``` +layer.scale('value', { + type: 'linear', + domain: [5, 100], // 可定义domain,也可以不设置,自定根据数据计算 +}); +``` + +## quantize 连续等间距 + +等间距分类会根据属性值范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量。 + +![L7 Scale 连续等间距](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*YmwwQ5L-d7QAAAAAAAAAAAAADmJ7AQ/original) + +等间距分类只与数据 mix、max 有关,如果没有设置 domain,将自动计算数据的 min、max 进行分段,分段个数依据 range 颜色的个数。等间距会出现空类,而且每个分类要素分布不均匀。 + +```tsx +layer.color('type', ['red', 'white', 'blue', 'yellow']); +``` +你也可以自定义 domain + +```ts + +layer.scale('value', { + type: 'quantize', + domain: [5, 100], +}); + +layer.color('type', ['red', 'white', 'blue', 'yellow']); + +``` +![L7 scale quantize](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*N61_Q6-U7jIAAAAAAAAAAAAADmJ7AQ/original) + +## quantile 连续等分位 + +等分位要求每个分类区间都含有相等数量的要素。分位数为每个分类分配相等数量数据值,不存在空类,也不存在值过多或过少的类。 + +![L7 scale quantile](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2SFpSLRD3yYAAAAAAAAAAAAADmJ7AQ/original) + +等分位与数据的分布相关,需要拿到全量数据才能计算,因此等分位的 scale 不能单独设置 domain,只能自动计算。 + +```tsx + +layer.scale('value', { + type: 'quantile', +}); + +layer.color('value', ['red', 'white', 'blue', 'yellow']); +``` + +![L7 Scale quantile](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*EMcjSrYe1l0AAAAAAAAAAAAADmJ7AQ/original) + + +## threshold 自定义分类 + + +自定义分类可以设定任意分类区间映射到对于视觉变量。domain 仍然是连续的,并根据提供的domain 进行分类。range 属性必须有 N+1 个元素,其中 N 是 domain 的个数。 + +threshold 为自定义分段,在使用时必须为 Scale 设置 domain, domain可以依据需求任意设置。 + +```tsx +layer.scale('rate', { + type: 'threshold', + domain: [3, 6, 8, 10], + }) + .color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']) + +``` + +![ L7 Scale threshold](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*e1YyRKELsjwAAAAAAAAAAAAADmJ7AQ/original) + + +## diverging 离散分类 + +离散分类通常与两种相反的色调一起使用,以显示从负值到中心到正值的变化。这些类型的地图显示了彼此相关的值的大小。 + +![L7 diverging](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*8anRRLJNu6YAAAAAAAAAAAAADmJ7AQ/original) + + +diverging 如果没有设置 domain 会自动根据数据计算min、middle、max 三个值作为domain。range 至少需要设置三个颜色,形成双极色带。 + +```ts +layer.scale('rate', { + type: 'diverging' + domain: [3, 6, 8, 10], // the input domain and output range of a diverging scal + }) + .color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']) +``` + +![L7 scale diverging](https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4rcDQIRdRdEAAAAAAAAAAAAADmJ7AQ/original) \ No newline at end of file