docs: scale demo & IE 兼容 (#1304)

* docs: 增加demo,关闭 any lint

* docs: demo& ie 兼容问题

* chore: dev-build
This commit is contained in:
@thinkinggis 2022-08-23 20:20:32 +08:00 committed by GitHub
parent 1e9dfaa310
commit c7f0f03e3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 658 additions and 8 deletions

View File

@ -28,6 +28,7 @@ module.exports = {
'no-case-declarations': 0, 'no-case-declarations': 0,
'no-useless-catch': 0, 'no-useless-catch': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, '@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-explicit-any':0,
'prefer-rest-params':0, 'prefer-rest-params':0,
}, },
settings: { settings: {

View File

@ -12,6 +12,12 @@ export default defineConfig({
resolve: { resolve: {
includes: ['dev-demos'] includes: ['dev-demos']
}, },
polyfill: {
imports: [
'element-remove',
'babel-polyfill',
]
},
targets: { targets: {
chrome: 58, chrome: 58,
ie: 11, ie: 11,
@ -30,6 +36,7 @@ export default defineConfig({
extraBabelPresets:[ extraBabelPresets:[
'@babel/preset-typescript' '@babel/preset-typescript'
], ],
extraBabelIncludes: ['@umijs/preset-dumi','split-on-first','query-string','strict-uri-encode','copy-text-to-clipboard'],
extraBabelPlugins: [ extraBabelPlugins: [
[ [
'transform-import-css-l7' 'transform-import-css-l7'
@ -47,11 +54,15 @@ export default defineConfig({
'react-dom': 'window.ReactDOM', 'react-dom': 'window.ReactDOM',
antd: 'window.antd', antd: 'window.antd',
lodash: '_', lodash: '_',
fetch:"window.fetch"
}, },
links: ['https://gw.alipayobjects.com/os/lib/antd/4.16.13/dist/antd.css'], links: ['https://gw.alipayobjects.com/os/lib/antd/4.16.13/dist/antd.css'],
scripts: [ scripts: [
'https://gw.alipayobjects.com/os/lib/react/17.0.1/umd/react.development.js', 'https://gw.alipayobjects.com/os/lib/whatwg-fetch/3.6.2/dist/fetch.umd.js',
'https://gw.alipayobjects.com/os/lib/react-dom/17.0.1/umd/react-dom.development.js', 'https://gw.alipayobjects.com/os/lib/react/17.0.2/umd/react.profiling.min.js',
'https://gw.alipayobjects.com/os/lib/react-dom/17.0.2/umd/react-dom.profiling.min.js',
'https://gw.alipayobjects.com/os/lib/react/17.0.2/umd/react.production.min.js',
'https://gw.alipayobjects.com/os/lib/react-dom/17.0.2/umd/react-dom.production.min.js',
// 'https://gw.alipayobjects.com/os/lib/antd/4.16.13/dist/antd-with-locales.js', // 'https://gw.alipayobjects.com/os/lib/antd/4.16.13/dist/antd-with-locales.js',
'https://gw.alipayobjects.com/os/lib/antd/4.19.4/dist/antd.js', 'https://gw.alipayobjects.com/os/lib/antd/4.19.4/dist/antd.js',
/** lodash */ /** lodash */

View File

@ -1 +0,0 @@
### 经典demo 案例

View File

@ -0,0 +1,3 @@
### 枚举类型
<code src="./cat.tsx"></code>

View File

@ -0,0 +1,57 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.scale('rate', {
type: 'quantile',
})
.shape('fill')
.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494'])
.style({
opacity: 1,
});
scene.addLayer(layer);
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,2 @@
### 离散类型
<code src="./diverging.tsx"></code>

View File

@ -0,0 +1,66 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useEuropeData, addEuropeLayers } from './useLine';
export default () => {
const { geoData } = useEuropeData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({
autoFit: true,
})
.source(geoData.country, {
transforms: [
{
type: 'join',
sourceField: 'country',
targetField: 'NAME',
data: geoData.turnout,
},
],
})
// .scale('turnout', {
// type: 'quantize', // the input domain and output range of a diverging scale always has exactly three elements
// // domain: [40, 70, 90],
// })
.shape('fill')
.color('turnout', [
'#b2182b',
'#f9b393',
'#f8f6e9',
'#9fc7e0',
'#2166ac',
])
.style({
opacity: 1,
});
scene.addLayer(layer);
addEuropeLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,74 @@
## Scale 简介
Scale 度量是将地图数据值(数字、日期、类别等数据)转成视觉值(颜色、大小、形状)。尺度 Scale 是数据可视化的基本组成部分,因为它们决定了视觉编码的性质。 L7 目前支持连续、离散、枚举类型数据的Scale并支持位置、形状、大小和颜色编码的映射。
Range 和 domain 是 Scale 中非常重要的两个参数
- domain: 地图数据值的定义区间
- range视觉值的区间定义
不同Scale 的差异在于 domain->range 的转换方法的不同
| 数据类型 | 度量类型 |
| ---- | ---- |
| 连续 | linear、log、pow、time、quantize、quantile |
| 分类 | cat、timeCat |
| 常量 | identity |
在使用 L7 开发过程中默认情况下不需要进行度量的配置,因为 G2 代码内部已经根据数据的形式对度量进行了假设,其计算过程如下:
查看用户是否制定了对应字段的数据类型 type)
如果没有,判断字段的第一条数据的字段类型
如果数据中不存在对应的字段,则为 'identity'
如果是数字则为 'linear'
如果是字符串,判定是否是时间格式,如果是时间格式则为时间类型 'time',
否则是分类类型 'cat'
### Cat
Cat 指枚举类型,用于展示分类数据,比如农作物种植区分布图,水稻、玉米、大豆等不同类别需要映射为不同的颜色。
比如
domain = ['corn','rice',soybean']
range = ['red','white','blue']
三种作物会分别转成对应的颜色
### identify
常量度量 某个字段是不变的常量。
### Linear
线性是连续数据的映射方法,数据和视觉值是通过线性方法换算的。如数据值 1-100 线性映射到红到蓝的线下渐变色每个数字对应一个颜色
### Sequential
### quantize
相等间隔会将属性值的范围划分为若干个大小相等的子范围。相等间隔最适用于常见的数据范围,如百分比和温度。这种方法强调的是某个属性值相对于其他值的量
### quantile
每个类都含有相等数量的要素。分位数分类非常适用于呈线性分布的数据。分位数为每个类分配数量相等的数据值。不存在空类,也不存在值过多或过少的类。
由于使用“分位数”分类将要素以同等数量分组到每个类中,因此得到的地图往往具有误导性。可能会将相似的要素置于相邻的类中,或将值差异较大的要素置于相同类中。可通过增加类的数量将这种失真降至最低。
### threshold
他允许将域的任意子集(非统一段)映射到范围内的离散值。输入域仍然是连续的,并根据提供给域属性的一组阈值划分为多个切片。 range 属性必须有 N+1 个元素,其中 N 是域中提供的阈值边界数
手动设置间隔 Manual interval 手动设置分级分类区间,某些数据会有相应的业界标准,或者需要进行某种特殊的显示。如空气质量数据有严格数据分段标准
```
-1 => "red"
0 => "white"
0.5 => "white"
1.0 => "blue"
1000 => "blue
```
### diverging

View File

@ -0,0 +1,2 @@
### 连续线性
<code src="./linear.tsx"></code>

View File

@ -0,0 +1,54 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.shape('fill')
.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']) // '#b6e2b6', '#64c1c0', '#338cbb',
.style({
opacity: 1,
});
scene.addLayer(layer);
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,2 @@
### 等分位
<code src="./quantile.tsx"></code>

View File

@ -0,0 +1,57 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.scale('rate', {
type: 'quantile',
})
.shape('fill')
.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494'])
.style({
opacity: 1,
});
scene.addLayer(layer);
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,2 @@
### 等间距
<code src="./quantize.tsx"></code>

View File

@ -0,0 +1,57 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.scale('rate', {
type: 'quantize',
})
.shape('fill')
.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494']) // '#b6e2b6', '#64c1c0', '#338cbb',
.style({
opacity: 1,
});
scene.addLayer(layer);
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,2 @@
### 连续
<code src="./sequential.tsx"></code>

View File

@ -0,0 +1,57 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.scale('rate', {
type: 'sequential', // he input domain and output range of a sequential scale always has exactly two elements, and the output range is typically specified as an interpolator rather than an array of values.
})
.shape('fill')
.color('rate', ['#ffffcc', '#253494'])
.style({
opacity: 1,
});
scene.addLayer(layer);
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,3 @@
### 自定义分段
<code src="./threshold.tsx"></code>

View File

@ -0,0 +1,58 @@
import { PolygonLayer, Scene } from '@antv/l7';
import { Mapbox } from '@antv/l7-maps';
import React, { useEffect } from 'react';
import { useData, addLayers } from './useLine';
export default () => {
const { geoData } = useData();
useEffect(() => {
const scene = new Scene({
id: 'map',
map: new Mapbox({
pitch: 0,
style: 'light',
center: [-96, 37.8],
zoom: 3,
}),
});
if (geoData) {
const layer = new PolygonLayer({})
.source(geoData.county, {
transforms: [
{
type: 'join',
sourceField: 'id',
targetField: 'id',
data: geoData.unemploymentdata,
},
],
})
.scale('rate', {
type: 'threshold',
domain: [3, 6, 8, 10],
})
.shape('fill')
.color('rate', ['#ffffcc', '#b6e2b6', '#64c1c0', '#338cbb', '#253494'])
.style({
opacity: 1,
});
scene.addLayer(layer);
addLayers(geoData, scene, layer);
}
return () => {
scene.destroy();
};
}, [geoData]);
return (
<div
id="map"
style={{
height: '500px',
position: 'relative',
}}
/>
);
};

View File

@ -0,0 +1,143 @@
import { useEffect, useState } from 'react';
import { LineLayer, PolygonLayer } from '@antv/l7';
interface IData {
county: any;
state: any;
unemploymentdata: any;
}
interface IData2 {
country: any;
turnout: any;
}
export function useData() {
const [data, setData] = useState<IData | undefined>(undefined);
useEffect(() => {
Promise.all([
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/5c4c7e02-a796-4c09-baba-629a99c909aa.json',
).then((d) => d.json()),
// https://lab.isaaclin.cn/nCoV/api/area?latest=1
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/738993d1-cc7e-4630-a318-80d6452fd125.csv',
).then((d) => d.text()),
fetch(
' https://gw.alipayobjects.com/os/bmw-prod/d13721bf-f0c2-4897-b6e6-633e6e022c09.json',
).then((d) => d.json()),
]).then(([county, unemployment, state]) => {
const unemploymentdata = unemployment
.split('\n')
.slice(0)
.map((line) => {
const item = line.split(',');
return {
id: item[0],
state: item[1],
county: item[2],
rate: item[3] * 1,
};
});
setData({
county,
unemploymentdata,
state,
});
});
}, []);
return { geoData: data };
}
export function useEuropeData() {
const [data, setData] = useState<IData2 | undefined>(undefined);
useEffect(() => {
Promise.all([
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/01ff872b-99c6-4e41-bd3a-34c2134da597.json',
).then((d) => d.json()),
// https://lab.isaaclin.cn/nCoV/api/area?latest=1
fetch(
'https://gw.alipayobjects.com/os/bmw-prod/64124f12-e086-4fe6-a900-bd57b410af69.csv',
).then((d) => d.text()),
]).then(([country, turnoutData,]) => {
const turnout = turnoutData
.split('\n')
.slice(0)
.map((line) => {
const item = line.split(',');
return {
country: item[0],
turnout: item[1] *1,
};
});
setData({
country,
turnout,
});
});
}, []);
return { geoData: data };
}
export function addLayers(data: IData, scene, mainLayer) {
const linelayer = new PolygonLayer({})
.source(data.county)
.size(0.5)
.shape('line')
.color('#fff')
.style({
opacity: 1,
});
const stateLayer = new PolygonLayer({})
.source(data.state)
.size(1)
.shape('line')
.color('#fff')
.style({
opacity: 1,
});
scene.addLayer(linelayer);
scene.addLayer(stateLayer);
addhightLayer(scene, mainLayer)
}
export function addEuropeLayers(data: IData2, scene, mainLayer) {
const linelayer = new PolygonLayer({})
.source(data.country)
.size(0.5)
.shape('line')
.color('#fff')
.style({
opacity: 1,
});
scene.addLayer(linelayer);
addhightLayer(scene, mainLayer)
}
function addhightLayer(scene, mainLayer) {
const hightLayer = new LineLayer({
zIndex: 4, // 设置显示层级
name: 'hightlight',
})
.source({
type: 'FeatureCollection',
features: [],
})
.shape('line')
.size(0.8)
.color('#000')
.style({
opacity: 1,
});
scene.addLayer(hightLayer);
mainLayer.on('click', (feature) => {
hightLayer.setData({
type: 'FeatureCollection',
features: [feature.feature],
});
});
}

View File

@ -67,6 +67,7 @@
"babel-plugin-transform-inline-environment-variables": "^0.4.3", "babel-plugin-transform-inline-environment-variables": "^0.4.3",
"babel-plugin-transform-node-env-inline": "^0.4.3", "babel-plugin-transform-node-env-inline": "^0.4.3",
"babel-plugin-transform-postcss": "^0.3.0", "babel-plugin-transform-postcss": "^0.3.0",
"babel-polyfill": "^6.26.0",
"babel-preset-gatsby": "^1.12.0", "babel-preset-gatsby": "^1.12.0",
"babel-template": "^6.26.0", "babel-template": "^6.26.0",
"clean-webpack-plugin": "^3.0.0", "clean-webpack-plugin": "^3.0.0",
@ -79,6 +80,7 @@
"cz-conventional-changelog": "^3.0.2", "cz-conventional-changelog": "^3.0.2",
"dat.gui": "^0.7.2", "dat.gui": "^0.7.2",
"dumi": "^1.1.0", "dumi": "^1.1.0",
"element-remove": "^1.0.4",
"enzyme": "^3.6.0", "enzyme": "^3.6.0",
"enzyme-adapter-react-16": "^1.5.0", "enzyme-adapter-react-16": "^1.5.0",
"enzyme-to-json": "^3.0.0-beta6", "enzyme-to-json": "^3.0.0-beta6",
@ -176,9 +178,9 @@
"release-beta": "yarn run prerelease && lerna publish --dist-tag beta from-package --force-publish && yarn sync", "release-beta": "yarn run prerelease && lerna publish --dist-tag beta from-package --force-publish && yarn sync",
"release": "lerna publish from-package --force-publish && yarn sync", "release": "lerna publish from-package --force-publish && yarn sync",
"release-cdn": "antv-bin upload -n @antv/l7", "release-cdn": "antv-bin upload -n @antv/l7",
"test": "umi-test", "test": "npm run worker && umi-test",
"test-cover": "yarn run worker && umi-test --coverage", "test-cover": "npm run worker && umi-test --coverage",
"test-cover-viewer": "umi-test --coverage && cd coverage && http-server -p 6001 -o", "test-cover-viewer": "npm run worker && umi-test --coverage && cd coverage && http-server -p 6001 -o",
"test-live": "umi-test --watch", "test-live": "umi-test --watch",
"tsc": "tsc", "tsc": "tsc",
"watch": "yarn clean && yarn worker && lerna run watch --parallel", "watch": "yarn clean && yarn worker && lerna run watch --parallel",

View File

@ -109,7 +109,6 @@ export default class FeatureScalePlugin implements ILayerPlugin {
if (attribute.scale) { if (attribute.scale) {
// 创建Scale // 创建Scale
const attributeScale = attribute.scale; const attributeScale = attribute.scale;
const type = attribute.name;
attributeScale.names = this.parseFields(attribute!.scale!.field || []); attributeScale.names = this.parseFields(attribute!.scale!.field || []);
const scales: IStyleScale[] = []; const scales: IStyleScale[] = [];
// 为每个字段创建 Scale // 为每个字段创建 Scale

View File

@ -12,7 +12,6 @@ import {
IThreeRenderService, IThreeRenderService,
ThreeRenderServiceType, ThreeRenderServiceType,
} from './threeRenderService'; } from './threeRenderService';
const DEG2RAD = Math.PI / 180;
type ILngLat = [number, number]; type ILngLat = [number, number];
export default class ThreeJSLayer export default class ThreeJSLayer
extends BaseLayer<{ extends BaseLayer<{