function-type
function-type是一种表达式,用于定义一个函数类型,函数参数是Feature的properties和地图的zoom级别,返回任意类型的值。
function-type用于在symbol上定义动态的样式属性,即能根据不同的Feature和zoom级别,设置不同的样式。
基于mapbox原function-type(BSD-3Clauses协议)实现。
function-type底层基于Object.defineProperty实现,本质就是在get方法里动态返回对应的值
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: {
stops: [
[1, 4],
[20, 20],
],
property: "count",
base: 1,
type: "exponential",
defalut: 15,
},
markerHeight: 15,
},
});
属性值
- stops:Array 必填(除了identity函数),一组输入值,用于生成一个输出值(类型为数字,数组,布尔值或字符串)
json
{
"stops": [
[1, 4], //stop0
[20, 20], //stop1
[30, 40] //stop2
]
}
TIP
stops里数组的含义:
[
[区间开始的值,对应的值]
[区间开始的值,对应的值]
[区间开始的值,对应的值]
...
]
WARNING
注意:
- 区间的组成规则:相邻的两个stop组成一个区间以上面的例子,组成的区间和值域如下:
区间 值域 备注 [1,20] [4,20] [20,30] [20,40] - 即相邻的stop的他们的stop[0]组成区间,stop[1]组成值域
- 从而我们可以得到 区间的数量=stops.length-1
- 区间的值必须是数字,值域的类型不一定是数字
- property:String 可选,属性名。如果设置了property,则会读取feature的属性作为输入值,如果不设置,则会用map的zoom作为输入值。
json
{
"stops": [
[1, 4],
[20, 20]
],
"property": "count"
}
- base:Number,可选,默认为1。 插值计算的基础值,用于控制插值的增加速率。base不为1时,插值计算为非线性,base越高,则插值增长得越快。而base为1时,则插值为线性插值。
json
{
"stops": [
[1, 4],
[20, 20]
],
"property": "count",
"base":1
- type:String,可选,默认为"exponential"。函数类型,可选的值: "identity", "exponential", "interval", or "categorical"
type | 描述 | 备注 |
---|---|---|
exponential | 通过stops和base,插值计算出结果,要求输入值必须为数值类型 | 值域的值必须是数字,因为要插值,只有数字才能被插值 |
identity | 把输入的property值直接作为输出值,必须定义property | 值域的值可以是数字,字符串,布尔等 |
interval | 用stops把输入值划分为几个区间来定义各自的输出值,即落在某个区间的输入值都输出同一个输出值 | 值域的值可以是数字,字符串,布尔等 |
categorical | 输入值必须等于stops中某个值时,则输出相应的输出值,就是key:value | 值域的值可以是数字,字符串,布尔等 |
color-interpolate | 颜色插值,会根据颜色区间自动进行渐变色的获取 | 值域的值必须是颜色,比如'red','#fff'等 |
json
{
"stops": [
[1, 4],
[20, 20]
],
"property": "count",
"base": 1,
"type": "exponential"
}
- default:默认值,当从数据的properties里拿不到值时就采用这个默认值作为输入值
json
{
"stops": [
[1, 4],
[20, 20]
],
"property": "count",
"base": 1,
"type": "exponential",
"defalut": 15
}
WARNING
默认值表示数据的输入的默认值,而不是函数的返回值,以上面的代码为例,当count的值为null,这时采用count=15 作为输入条件
举例
这里我们以动态设置marker的样式为例:
exponential
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: {
stops: [
[1, 4],
[15, 20],
[20, 50],
],
property: "count",
base: 1,
type: "exponential",
defalut: 15,
},
markerHeight: 15,
},
});
从代码里我们可以看到:
- 从图形数据属性count来动态设置图形的宽度
- count的值为5,那么将会在 [1,15]这个区间进行插值,来动态计算markerWidth的值
identity
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: {
property: "count",
type: "identity",
},
markerHeight: 15,
},
});
从代码里我们可以看到:
- 从图形数据属性count来直接获取markerWidth的值
interval
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: {
stops: [
[1, 4],
[15, 20],
[20, 50],
],
property: "count",
type: "interval",
defalut: 15,
},
markerHeight: 15,
},
});
从代码里我们可以看到:
- 从图形数据属性count来获取对应的markerWidth
- type=interval表示区间获取,注意和exponential区分,exponential是插值
- 当count的值在[1,15]之间,那么他们的获取的值都是一样的,同理在[15,20]之间的count他们获取的值也一样
WARNING
注意输入的值没有达到下个区间时,一律采用当前区间的值,比如count=5,count=8,那么对应的值一律在[1,4]这个数据项 ,当count=15是就属于[15,20]数据项了
categorical
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: {
stops: [
[1, 4],
[15, 20],
[20, 50],
],
property: "count",
type: "categorical",
},
markerHeight: 15,
},
});
从代码里我们可以看到:
- 从图形数据属性count来获取对应的markerWidth
- type=categorical表示count的值,注意这时就没有区间的概念了,当且仅当count为 [1,15,20]时,才能获取值
- 所以categorical和枚举是一样的
这个例子里我们演示了不同的分类使用不同的图标
js
const funtype = {
stops: [
["1", "./../assets/icon/daxiao.png"],
["2", "./../assets/icon/dianyan.png"],
["3", "./../assets/icon/fadai.png"],
["4", "./../assets/icon/jingya.png"],
["5", "./../assets/icon/qushi.png"],
],
property: "type",
type: "categorical",
};
points.forEach((point) => {
console.log(point.getProperties());
point.setSymbol({
markerWidth: 22,
// markerType: 'ellipse',
markerFile: funtype,
markerHeight: 22,
});
});
layer.addGeometry(points);
color-interpolate
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: 2,
markerHeight: 2,
markerType: "ellipse",
markerFill: {
type: "color-interpolate",
property: "count",
stops: [
[1, "green"],
[10, "yellow"],
[20, "red"],
],
},
markerLineWidth: 0,
},
});
从代码里我们可以看到:
- 从图形数据属性count来获取对应的markerFill
- 当count的值在区间[1,10] 之间会自动计算[green,yellow]之间的渐变色的, 在[10,20]之间同理计算[yellow,red]之间的渐变色
- 注意,取色只能在区间里,这个没有默认值,即:当count< 1 时也采用 green, 当count>20是采用red
省略property属性
js
const point = new maptalks.Marker([0, 0], {
properties: {
count: 5,
},
symbol: {
markerWidth: {
stops: [
[1, 4],
[15, 20],
[20, 50],
],
base: 1,
type: "exponential",
},
markerHeight: 15,
},
});
从代码里我们可以看到:
- 没有填写property属性,这时将读取地址的map.getZoom()值作为参考
- 当地图zoom=1时,值为4,zoom=15时值为20,中间的自动插值,即随着地图的放大点的宽度越来越大
- 其他的type也是同理,区别就是一个从图形的propreties读取值,一个是读取地图的zoom