Merge pull request #316 from antvis/District

District
This commit is contained in:
@thinkinggis 2020-05-10 21:46:02 +08:00 committed by GitHub
commit 6120d0904d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 126014 additions and 6292 deletions

View File

@ -17,6 +17,17 @@ jobs:
# 注意替换为你的 Gitee 目标仓库地址
destination-repo: 'git@gitee.com:antv-l7/antv-l7.git'
- name: 🔁 Sync to Gitee
uses: wearerequired/git-mirror-action@master
env:
# 注意在 Settings->Secrets 配置 GITEE_RSA_PRIVATE_KEY
SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }}
with:
# 注意替换为你的 GitHub 源仓库地址
source-repo: 'git@github.com:antvis/L7.git'
# 注意替换为你的 Gitee 目标仓库地址
destination-repo: 'git@gitee.com:antv/L7.git'
- name: ✅ Build Gitee Pages
uses: yanglbme/gitee-pages-action@master
with:

1
.gitignore vendored
View File

@ -80,3 +80,4 @@ packages/l7/package_bak.json
stories/Test
packages/draw/node_modules/@turf
packages/district/src/data

27500
.storybook/antd.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
// tslint:disable-next-line:no-submodule-imports
// import '!style-loader!css-loader!sass-loader!./iframe.scss';
import { addParameters, configure } from '@storybook/react';
import { create } from '@storybook/theming';

View File

@ -1,3 +1,4 @@
const path = require("path");
module.exports = ({ config }) => {
// config.module.rules.push({
@ -12,24 +13,23 @@ module.exports = ({ config }) => {
// options: { inline: true, fallback: false }
// }
// });
config.module.rules =[];
config.module.rules.push(
{
config.module.rules.push({
test: /\.(ts|tsx)$/,
loader: require.resolve('awesome-typescript-loader'),
});
config.module.rules.push({
test: /\.stories\.tsx?$/,
// loaders: [
// {
// loader: require.resolve('@storybook/addon-storysource/loader'),
// options: { parser: 'typescript' },
// },
// ],
config.module.rules.push(
{
test: /.css$/,
use: ["style-loader", "css-loader", 'sass-loader'],
enforce: 'pre',
},{
test: /\.stories\.css?$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.stories\.svg$/,
@ -37,7 +37,7 @@ module.exports = ({ config }) => {
}
);
config.resolve.extensions.push('.ts', '.tsx', '.js', '.glsl');
config.resolve.extensions.push('.ts', '.tsx', 'css', '.js', '.glsl');
return config;
};

View File

@ -28,7 +28,7 @@ module.exports = api => {
{
extensions: [
// 由于使用了 TS 的 resolveJsonModule 选项JSON 可以直接引入,不需要当作纯文本
// '.json',
'.pbf',
'.glsl'
]
}
@ -95,7 +95,7 @@ module.exports = api => {
{
extensions: [
// 由于使用了 TS 的 resolveJsonModule 选项JSON 可以直接引入,不需要当作纯文本
// '.json',
'.json',
'.glsl'
]
}

View File

@ -379,6 +379,14 @@ scene.removeLayer(layer);
scene.exportMap('png');
```
### destroy
scene 销毁方法,离开页面,或者不需要使用地图可以调用
```
scene.destroy();
```
## 事件
### on

View File

@ -91,6 +91,7 @@
"react-docgen-typescript-loader": "^3.1.0",
"react-dom": "^16.13.1",
"react-i18next": "^11.0.1",
"react-scripts": "^3.4.1",
"rimraf": "^3.0.2",
"rollup": "^1.27.14",
"rollup-plugin-analyzer": "^3.2.2",
@ -103,7 +104,6 @@
"rollup-pluginutils": "^2.8.2",
"sass-loader": "^8.0.2",
"style-loader": "^1.0.0",
"three": "0.115.0",
"styled-components": "^3.4.6",
"stylelint": "^9.5.0",
"stylelint-config-recommended": "^2.1.0",
@ -111,6 +111,7 @@
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.3.2",
"svg-inline-loader": "^0.8.0",
"three": "0.115.0",
"ts-jest": "^24.0.2",
"tslint": "^5.11.0",
"tslint-config-prettier": "^1.15.0",
@ -130,7 +131,7 @@
"site:clean": "gatsby clean",
"site:deploy": "yarn run site:build && gh-pages -d public",
"site:publish": "gh-pages -d public",
"lint:fix": "prettier --write docs/api/**/*.md docs/api/*.md packages/**/*.{spec,story}.ts{,x} stories/**/**/*.tsx *.md",
"lint:fix": "prettier --write docs/api/**/*.md docs/api/*.md packages/**/*.ts{,x} packages/**/*.{spec,story}.ts{,x} stories/**/**/*.tsx *.md",
"lint:examples": "eslint examples/**/**/*.js --fix",
"prebuild": "run-p tsc lint",
"build": "yarn clean && lerna run build",
@ -138,8 +139,8 @@
"build:declarations": "lerna exec --stream --no-bail 'tsc --project ./tsconfig.build.json'",
"fix": "run-p -c 'lint:ts-* --fix'",
"lint:css": "stylelint 'packages/**/*.js{,x}'",
"lint:ts-prod": "tslint --config tslint.prod.json 'packages/**/*.ts{,x}'",
"lint:ts-test": "tslint --config tslint.test.json 'packages/**/*.{spec,story}.ts{,x}'",
"lint:ts-prod": "tslint --fix --config tslint.prod.json 'packages/**/*.ts{,x}'",
"lint:ts-test": "tslint --fix --config tslint.test.json 'packages/**/*.{spec,story}.ts{,x}'",
"lint:ts": "run-p -c lint:ts-*",
"lint": "run-p -c lint:*",
"commit": "git-cz",

View File

@ -457,11 +457,11 @@
display: block;
padding: 8px;
}
.l7-control-layers label input[type="radio"], input[type="checkbox"]{
.l7-control-layers label input[type="radio"],
.l7-control-layers label input[type="checkbox"] {
width: 14px;
height: 14px;
margin: 0;
vertical-align: middle;
}
.l7-control-layers-separator {
height: 0;

View File

@ -0,0 +1,11 @@
# `district`
> TODO: description
## Usage
```
const district = require('district');
// TODO: DEMONSTRATE API
```

View File

@ -0,0 +1,9 @@
import BaseLayer from '../src/layer/baseLayer';
describe('baseLayer', () => {
it('set option', () => {
const option = {
adcode: [],
};
// const layer = new BaseLayer(null, option);
});
});

View File

@ -0,0 +1,62 @@
{
"name": "@antv/l7-district",
"version": "2.2.3",
"description": "L7 district moudules",
"keywords": [],
"author": "thinkinggis <lzx199065@gmail.com>",
"license": "ISC",
"main": "lib/index.js",
"module": "es/index.js",
"unpkg": "dist/l7-district.js",
"types": "es/index.d.ts",
"sideEffects": true,
"files": [
"dist",
"lib",
"es",
"README.md"
],
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/antvis/L7.git"
},
"scripts": {
"tsc": "tsc --project tsconfig.build.json",
"clean": "rimraf dist; rimraf es; rimraf lib;",
"build": "run-p build:*",
"build:cjs": "BABEL_ENV=cjs babel src --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:esm": "BABEL_ENV=esm babel src --root-mode upward --out-dir es --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"watch": "BABEL_ENV=cjs babel src --watch --root-mode upward --out-dir lib --source-maps --extensions .ts,.tsx --delete-dir-on-start --no-comments",
"build:cdn": "node_modules/.bin/rollup -c",
"test": "jest"
},
"dependencies": {
"@antv/l7": "^2.2.3",
"@babel/runtime": "^7.7.7",
"@turf/circle": "^6.0.1",
"@turf/distance": "^6.0.1",
"@turf/helpers": "^6.1.4",
"@turf/midpoint": "^5.1.5",
"@turf/turf": "^5.1.6",
"geobuf": "^3.0.1",
"lodash": "^4.6.2",
"eventemitter3": "^4.0.0",
"pbf": "^3.2.1"
},
"peerDependencies": {
"@antv/l7": "^2.2.3"
},
"bugs": {
"url": "https://github.com/antvis/L7/issues"
},
"homepage": "https://github.com/antvis/L7#readme",
"devDependencies": {
"postcss": "^7.0.27",
"postcss-url": "^8.0.0",
"rollup": "^2.3.3",
"rollup-plugin-less": "^1.1.2"
}
}

View File

@ -0,0 +1,51 @@
import pkg from './package.json';
import typescript from 'rollup-plugin-typescript';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import buble from 'rollup-plugin-buble';
import postcss from 'rollup-plugin-postcss';
import { terser } from 'rollup-plugin-terser';
import url from 'postcss-url';
export default {
input: './src/index.ts',
plugins: [
// less(),
typescript({
exclude: 'node_modules/**',
typescript: require('typescript')
}),
resolve({
preferBuiltins: false
}),
postcss({
plugins: [
url({ url: 'inline' })
]
}),
commonjs({
namedExports: {
eventemitter3: [ 'EventEmitter' ],
lodash: [ 'merge', 'clone' ]
}
}),
buble({
transforms: { generator: false }
}),
terser()
],
external: [
'@antv/l7'
],
output: [
{
format: 'umd',
name: 'L7.District',
file: pkg.unpkg,
sourcemap: true,
globals: {
'@antv/l7': 'L7'
}
}
]
};

View File

@ -0,0 +1,128 @@
// tslint:disable-next-line:no-submodule-imports
import merge from 'lodash/merge';
let DataConfig: { [key: string]: any } = {
world: {
fill: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/21bdf832-1dfc-4cae-92d1-aa8d156df40f.bin',
},
line: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/76914518-e04c-42c9-8c4b-1ae71aabb024.bin',
},
label: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/90c51eb3-04d7-402f-bd05-95e4bd27dd62.bin',
parser: {
type: 'geojson',
},
},
nationalBoundaries: {
type: 'json',
url:
'//gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
},
},
country: {
CHN: {
1: {
fill: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
},
line: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/70ec087e-c48a-4b76-8825-6452f17bae7a.bin',
},
provinceLine: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
label: {
type: 'json',
url:
'//gw.alipayobjects.com/os/bmw-prod/36832a45-68f8-4b51-b006-9dec71f92a23.json',
},
},
2: {
fill: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/561e2cfe-9460-42d1-a2f8-3fd2e1274c52.bin',
},
line: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
cityLine: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
provinceLine: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
},
3: {
fill: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/516b2703-d692-44e6-80dd-b3f5df0186e7.bin',
},
line: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
},
countryLine: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/bc97875a-90f2-42c0-a62c-43d2efd7460d.bin',
},
cityLine: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/8bfbfe7e-bd0e-4bbe-84d8-629f4dc7abc4.bin',
},
provinceLine: {
type: 'pbf',
url:
'//gw.alipayobjects.com/os/bmw-prod/778ad7ba-5a3f-4ed6-a94a-b8ab8acae9d6.bin',
},
},
nationalBoundaries: {
type: 'json',
url:
'//gw.alipayobjects.com/os/bmw-prod/ee493a41-0558-4c0e-bee6-520276c4f1a8.json',
},
nationalBoundaries2: {
type: 'json',
url:
'//gw.alipayobjects.com/os/bmw-prod/f2189cc4-662b-4358-8573-36f0f918b7ca.json',
},
island: {
type: 'json',
url:
'//gw.alipayobjects.com/os/bmw-prod/fe49b393-1147-4769-94ed-70471f4ff15d.json',
},
},
},
province: {
110000: '',
},
};
function setDataConfig(config: any) {
DataConfig = merge(DataConfig, config);
}
export { setDataConfig, DataConfig };

View File

@ -0,0 +1,16 @@
import { setDataConfig } from './config';
import CityLayer from './layer/city';
import CountryLayer from './layer/country';
import CountyLayer from './layer/county';
import DrillDownLayer from './layer/drillDown';
import ProvinceLayer from './layer/province';
import WorldLayer from './layer/world';
export {
WorldLayer,
CountryLayer,
ProvinceLayer,
CityLayer,
CountyLayer,
DrillDownLayer,
setDataConfig,
};

View File

@ -0,0 +1,194 @@
import {
ILayer,
IPopup,
LineLayer,
PointLayer,
PolygonLayer,
Popup,
Scene,
StyleAttrField,
} from '@antv/l7';
import { EventEmitter } from 'eventemitter3';
// @ts-ignore
import geobuf from 'geobuf';
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
// @ts-ignore
import Pbf from 'pbf';
import { IDistrictLayerOption } from './interface';
export default class BaseLayer extends EventEmitter {
public fillLayer: ILayer;
public lineLayer: ILayer;
public labelLayer: ILayer;
protected scene: Scene;
protected options: IDistrictLayerOption;
protected layers: ILayer[] = [];
private popup: IPopup;
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
super();
this.scene = scene;
this.options = merge({}, this.getDefaultOption(), option);
}
public destroy() {
this.layers.forEach((layer) => this.scene.removeLayer(layer));
this.layers.length = 0;
}
public show() {
this.layers.forEach((layer) => layer.show());
}
public hide() {
this.layers.forEach((layer) => layer.hide());
}
protected async fetchData(data: { url: string; type: string }) {
if (data.type === 'pbf') {
const buffer = await (await fetch(data.url)).arrayBuffer();
const geojson = geobuf.decode(new Pbf(buffer));
return geojson;
} else {
return (await fetch(data.url)).json();
}
}
protected getDefaultOption(): IDistrictLayerOption {
return {
zIndex: 0,
depth: 1,
adcode: [],
label: {
enable: true,
color: '#000',
field: 'name',
size: 8,
stroke: '#fff',
strokeWidth: 2,
textAllowOverlap: true,
opacity: 1,
},
fill: {
scale: null,
field: null,
values: '#fff',
},
autoFit: true,
stroke: '#d95f0e',
strokeWidth: 0.6,
cityStroke: 'rgba(255,255,255,0.6)',
cityStrokeWidth: 0.6,
countyStrokeWidth: 0.6,
provinceStrokeWidth: 0.6,
provinceStroke: '#fff',
countyStroke: 'rgba(255,255,255,0.6)',
coastlineStroke: '#4190da',
coastlineWidth: 1,
nationalStroke: 'gray',
nationalWidth: 1,
popup: {
enable: true,
triggerEvent: 'mousemove',
Html: (properties: any) => {
return `${properties.name}`;
},
},
};
}
protected addFillLayer(fillCountry: any) {
// 添加省份填充
const { popup, data = [], fill, autoFit } = this.options;
const fillLayer = new PolygonLayer({
autoFit,
}).source(fillCountry, {
transforms:
data.length === 0
? []
: [
{
type: 'join',
sourceField: 'name', // data1 对应字段名
targetField: 'name', // data 对应字段名 绑定到的地理数据
data,
},
],
});
fill.field
? fillLayer.color(fill.field, fill.values)
: fillLayer.color(fill.values as string);
if (fill.scale) {
fillLayer.scale('color', {
type: 'quantile',
field: fill.field as string,
});
}
fillLayer
.shape('fill')
.active({
color: 'rgba(0,0,255,0.3)',
})
.style({
opacity: 1,
});
this.fillLayer = fillLayer;
this.layers.push(fillLayer);
this.scene.addLayer(fillLayer);
if (popup.enable) {
this.addPopup();
}
this.emit('loaded');
}
protected addFillLine(provinceLine: any) {
const { stroke, strokeWidth, zIndex } = this.options;
const layer2 = new LineLayer({
zIndex: zIndex + 1,
})
.source(provinceLine)
.color(stroke)
.size(strokeWidth)
.style({
opacity: 1,
});
this.scene.addLayer(layer2);
this.layers.push(layer2);
this.lineLayer = layer2;
}
protected addLabelLayer(labelData: any, type: string = 'json') {
const { label, zIndex } = this.options;
const labelLayer = new PointLayer({
zIndex: zIndex + 2,
})
.source(labelData, {
parser: {
type,
coordinates: 'center',
},
})
.color(label.color as StyleAttrField)
.shape(label.field as StyleAttrField, 'text')
.size(10)
.style({
opacity: label.opacity,
stroke: label.stroke,
strokeWidth: label.strokeWidth,
textAllowOverlap: label.textAllowOverlap,
});
this.scene.addLayer(labelLayer);
this.layers.push(labelLayer);
this.labelLayer = labelLayer;
}
protected addPopup() {
const { popup } = this.options;
this.fillLayer.on('mousemove', (e) => {
this.popup = new Popup({
closeButton: false,
})
.setLnglat(e.lngLat)
.setHTML(popup.Html ? popup.Html(e.feature.properties) : '');
this.scene.addPopup(this.popup);
});
}
}

View File

@ -0,0 +1,49 @@
import {
ILayer,
LineLayer,
PointLayer,
PolygonLayer,
Scene,
StyleAttrField,
} from '@antv/l7';
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
import { adcodeType, IDistrictLayerOption } from './interface';
import ProvinceLayer from './province';
export interface IProvinceLayerOption extends IDistrictLayerOption {
adcode: adcodeType;
}
export default class CityLayer extends ProvinceLayer {
protected getDefaultOption(): IProvinceLayerOption {
const config = super.getDefaultOption();
return merge({}, config, {
adcode: ['110000'],
depth: 3,
});
}
protected filterData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.features.filter((fe: any) => {
const code = fe.properties.adcode_cit;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return { type: 'FeatureCollection', features };
}
protected filterLabelData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.filter((fe: any) => {
const code = fe.adcode_cit;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return features;
}
}

View File

@ -0,0 +1,176 @@
import {
ILayer,
LineLayer,
PointLayer,
PolygonLayer,
Scene,
StyleAttrField,
} from '@antv/l7';
import { DataConfig } from '../config';
import BaseLayer from './baseLayer';
import { IDistrictLayerOption } from './interface';
export default class CountryLayer extends BaseLayer {
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
super(scene, option);
const { depth } = this.options;
this.loadData().then(([fillData, fillLabel]) => {
this.addFillLayer(fillData);
if (fillLabel && this.options.label?.enable) {
this.addLabelLayer(fillLabel);
}
});
const countryConfig = DataConfig.country.CHN[depth];
this.addProvinceLine(countryConfig.provinceLine);
if (depth === 2 * 1) {
this.addCityBorder(countryConfig.cityLine);
}
if (depth === 3 * 1) {
this.addCountryBorder(countryConfig.countryLine);
}
}
// 国界,省界
protected async addProvinceLine(cfg: any) {
const lineData = await this.fetchData(cfg);
const border1 = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type === '1' || type === '4';
});
const borderFc = {
type: 'FeatureCollection',
features: border1,
};
const nationalBorder = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type !== '1' && type !== '4';
});
const nationalFc = {
type: 'FeatureCollection',
features: nationalBorder,
};
this.addNationBorder(nationalFc, borderFc);
}
// 国界,省界
protected addFillLine(lineData: any) {
const border1 = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type === '1' || type === '4';
});
const borderFc = {
type: 'FeatureCollection',
features: border1,
};
const nationalBorder = lineData.features.filter((feature: any) => {
const type = feature.properties.type;
return type !== '1' && type !== '4';
});
const nationalFc = {
type: 'FeatureCollection',
features: nationalBorder,
};
this.addNationBorder(nationalFc, borderFc);
}
private async loadData() {
const { depth } = this.options;
const countryConfig = DataConfig.country.CHN[depth];
const fillData = await this.fetchData(countryConfig.fill);
const fillLabel = countryConfig.label
? await this.fetchData(countryConfig.label)
: null;
return [fillData, fillLabel];
}
// 省级行政区划
private async addNationBorder(boundaries: any, boundaries2: any) {
const {
nationalStroke,
nationalWidth,
coastlineStroke,
coastlineWidth,
stroke,
strokeWidth,
zIndex,
} = this.options;
// 添加国界线
const lineLayer = new LineLayer({
zIndex: zIndex + 1,
})
.source(boundaries)
.size('type', (v: string) => {
if (v === '3') {
return strokeWidth;
} else if (v === '2') {
return coastlineWidth;
} else if (v === '0') {
return nationalWidth;
} else {
return '#fff';
}
})
.shape('line')
.color('type', (v: string) => {
if (v === '3') {
return stroke;
} else if (v === '2') {
return coastlineStroke;
} else if (v === '0') {
return nationalStroke;
} else {
return '#fff';
}
});
// 添加未定国界
const lineLayer2 = new LineLayer({
zIndex: zIndex + 1,
})
.source(boundaries2)
.size(nationalWidth)
.shape('line')
.color('gray')
.style({
lineType: 'dash',
dashArray: [2, 2],
});
this.scene.addLayer(lineLayer);
this.scene.addLayer(lineLayer2);
this.layers.push(lineLayer, lineLayer2);
}
// 省级边界
private async addCityBorder(cfg: any) {
const border1 = await this.fetchData(cfg);
const { cityStroke, cityStrokeWidth } = this.options;
const cityline = new LineLayer({
zIndex: 2,
})
.source(border1)
.color(cityStroke)
.size(cityStrokeWidth)
.style({
opacity: 0.5,
});
this.scene.addLayer(cityline);
this.layers.push(cityline);
}
// 县级边界
private async addCountryBorder(cfg: any) {
// const bordConfig = DataConfig.country.CHN[3];
const border1 = await this.fetchData(cfg);
const { countyStrokeWidth, countyStroke } = this.options;
const cityline = new LineLayer({
zIndex: 2,
})
.source(border1)
.color(countyStroke)
.size(countyStrokeWidth)
.style({
opacity: 0.5,
});
this.scene.addLayer(cityline);
this.layers.push(cityline);
}
}

View File

@ -0,0 +1,41 @@
import { Scene } from '@antv/l7';
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
import { adcodeType, IDistrictLayerOption } from './interface';
import ProvinceLayer from './province';
export interface IProvinceLayerOption extends IDistrictLayerOption {
adcode: adcodeType;
}
export default class CityLayer extends ProvinceLayer {
protected getDefaultOption(): IProvinceLayerOption {
const config = super.getDefaultOption();
return merge({}, config, {
adcode: ['110100'],
depth: 3,
});
}
protected filterData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.features.filter((fe: any) => {
const code = fe.properties.adcode;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return { type: 'FeatureCollection', features };
}
protected filterLabelData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.filter((fe: any) => {
const code = fe.adcode;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return features;
}
}

View File

@ -0,0 +1,37 @@
import { Scene } from '@antv/l7';
import CityLayer from './city';
import CountryLayer from './country';
import { IDistrictLayerOption } from './interface';
import ProvinceLayer from './province';
export default class DrillDownLayer {
private provinceLayer: ProvinceLayer;
private cityLayer: CityLayer;
private countryLayer: CountryLayer;
constructor(scene: Scene, option: Partial<IDistrictLayerOption>) {
const cfg = this.getDefaultOption();
this.countryLayer = new CountryLayer(scene, option);
this.provinceLayer = new ProvinceLayer(scene, cfg.city);
// this.cityLayer = new CityLayer(scene);
// this.provinceLayer.hide();
// this.cityLayer.hide();
this.countryLayer.on('loaded', () => {
this.addProvinceEvent();
});
}
public getDefaultOption() {
return {
province: {},
city: {
adcode: '',
},
county: {
adcode: [],
},
};
}
public addProvinceEvent() {
// this.countryLayer.fillLayer.on('click', (e: any) => {
// });
}
}

View File

@ -0,0 +1,43 @@
import { ScaleTypeName, StyleAttributeOption } from '@antv/l7';
export interface ILabelOption {
enable: boolean;
color: string;
field: string;
size: number;
stroke: string;
strokeWidth: number;
textAllowOverlap: boolean;
opacity: number;
}
export type adcodeType = string[] | string | number | number[];
export interface IDistrictLayerOption {
zIndex: number;
data?: Array<{ [key: string]: any }>;
adcode: adcodeType;
depth: 0 | 1 | 2 | 3;
label: Partial<ILabelOption>;
fill: Partial<{
scale: ScaleTypeName | null;
field: string | null;
values: StyleAttributeOption;
}>;
autoFit: boolean;
stroke: string;
strokeWidth: number;
provinceStroke: string;
cityStroke: string;
provinceStrokeWidth: number;
cityStrokeWidth: number;
countyStroke: string;
countyStrokeWidth: number;
coastlineStroke: string;
coastlineWidth: number;
nationalStroke: string;
nationalWidth: number;
popup: Partial<{
enable: boolean;
triggerEvent: 'mousemove' | 'click';
Html: (properties: any) => string;
}>;
}

View File

@ -0,0 +1,126 @@
import {
ILayer,
LineLayer,
PointLayer,
PolygonLayer,
Scene,
StyleAttrField,
} from '@antv/l7';
// tslint:disable-next-line: no-submodule-imports
import merge from 'lodash/merge';
import { DataConfig } from '../config';
import BaseLayer from './baseLayer';
import { adcodeType, IDistrictLayerOption } from './interface';
export interface IProvinceLayerOption extends IDistrictLayerOption {
adcode: adcodeType;
}
export default class ProvinceLayer extends BaseLayer {
private fillData: any;
private lineData: any;
private labelData: any;
constructor(scene: Scene, option: Partial<IProvinceLayerOption> = {}) {
super(scene, option);
this.addProvinceFillLayer();
this.addProvinceLineLayer();
}
// 通过adcode 更新
public updateDistrict(adcode: adcodeType) {
if (!adcode && Array.isArray(adcode) && adcode.length === 0) {
this.hide();
return;
}
const fillData = this.filterData(this.fillData, adcode);
const lineData = this.filterData(this.lineData, adcode);
const labelData = this.filterLabelData(this.labelData, adcode);
this.fillLayer.setData(fillData);
this.lineLayer.setData(lineData);
this.labelLayer.setData(labelData);
this.show();
}
// 更新渲染数据
public updateData() {
return 'update data';
}
protected getDefaultOption(): IProvinceLayerOption {
const config = super.getDefaultOption();
return merge({}, config, {
adcode: ['110000'],
depth: 2,
label: {
field: 'NAME_CHN',
textAllowOverlap: false,
},
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props: any) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
}
protected filterData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.features.filter((fe: any) => {
const code = fe.properties.adcode_pro;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return { type: 'FeatureCollection', features };
}
protected filterLabelData(data: any, adcode: adcodeType) {
const adcodeArray = Array.isArray(adcode) ? adcode : [adcode];
const features = data.filter((fe: any) => {
const code = fe.adcode_pro;
return (
adcodeArray.indexOf(code) !== -1 ||
adcodeArray.indexOf('' + code) !== -1
);
});
return features;
}
private async addProvinceFillLayer() {
const { depth, adcode } = this.options as IProvinceLayerOption;
const countryConfig = DataConfig.country.CHN[depth];
const fillData = await this.fetchData(countryConfig.fill);
this.labelData = fillData.features.map((feature: any) => {
return {
...feature.properties,
center: [feature.properties.x, feature.properties.y],
};
});
const data = this.filterData(fillData, adcode);
const labelData = this.filterLabelData(this.labelData, adcode);
this.fillData = fillData;
this.addFillLayer(data);
this.addLabelLayer(labelData);
}
private async addProvinceLineLayer() {
const { depth, adcode } = this.options as IProvinceLayerOption;
const countryConfig = DataConfig.country.CHN[depth];
const fillData = await this.fetchData(countryConfig.line);
const data = this.filterData(fillData, adcode);
this.lineData = fillData;
this.addFillLine(data);
}
}

View File

@ -0,0 +1,111 @@
import {
ILayer,
LineLayer,
PointLayer,
PolygonLayer,
Scene,
StyleAttrField,
} from '@antv/l7';
import { DataConfig } from '../config';
import BaseLayer from './baseLayer';
import { IDistrictLayerOption } from './interface';
export default class WorldLayer extends BaseLayer {
constructor(scene: Scene, option: Partial<IDistrictLayerOption> = {}) {
super(scene, option);
this.loadData().then(([fillData, lineData, fillLabel]) => {
// this.addWorldBorder(border1, border2, island);
this.addFillLayer(fillData);
this.addFillLine(lineData);
if (this.options.label?.enable) {
this.addLabelLayer(fillLabel, 'geojson');
}
});
}
public addFillLine(data: any) {
// 未定国界
const bord1 = data.features.filter((feature: any) => {
return (
feature.properties.type === '10' ||
feature.properties.type === '1' ||
feature.properties.type === '11'
);
});
const bordFc = {
type: 'FeatureCollection',
features: bord1,
};
const nationalBorder = data.features.filter((feature: any) => {
return (
feature.properties.type !== '10' &&
feature.properties.type !== '1' &&
feature.properties.type !== '11'
);
});
const nationalFc = {
type: 'FeatureCollection',
features: nationalBorder,
};
this.addNationBorder(nationalFc, bordFc);
}
private async loadData() {
const countryConfig = DataConfig.world;
const fillData = await this.fetchData(countryConfig.fill);
const lineData = await this.fetchData(countryConfig.line);
const fillLabel = await this.fetchData(countryConfig.label);
return [fillData, lineData, fillLabel];
}
private addNationBorder(boundaries: any, boundaries2: any) {
const {
nationalStroke,
nationalWidth,
coastlineStroke,
coastlineWidth,
zIndex,
} = this.options;
// 添加国界线
const lineLayer = new LineLayer({
zIndex: zIndex + 1,
})
.source(boundaries)
.size(0.6)
.color('type', (v: string) => {
if (v === '0') {
return 'rgb(99,100, 99)'; // 中国国界线
} else if (v === '2') {
return 'rgb(0,136, 191)'; // 中国海岸线
} else if (v === '9') {
return 'rgb(0,136, 191)'; // 国外海岸线
} else if (v === '7') {
return '#9ecae1'; // 国外国界
} else {
return '#9ecae1';
}
});
// 添加未定国界
const lineLayer2 = new LineLayer({
zIndex: zIndex + 1,
})
.source(boundaries2)
.size(nationalWidth)
.shape('line')
.color('type', (v: string) => {
if (v === '1') {
return 'rgb(99,100, 99)';
} else {
return '#9ecae1';
}
})
.style({
lineType: 'dash',
dashArray: [2, 2],
});
this.scene.addLayer(lineLayer);
this.scene.addLayer(lineLayer2);
this.layers.push(lineLayer, lineLayer2);
}
}

View File

@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"declarationDir": "./es",
"rootDir": "./src",
"baseUrl": "./"
},
"include": ["./src"]
}

View File

@ -42,6 +42,7 @@
"@turf/helpers": "^6.1.4",
"@turf/midpoint": "^5.1.5",
"@turf/turf": "^5.1.6",
"eventemitter3": "^4.0.0",
"lodash": "^4.6.2"
},
"bugs": {

View File

@ -16,10 +16,10 @@ export function computeMiter(
export function computeNormal(out: vec2, dir: vec2) {
return vec2.set(out, -dir[1], dir[0]);
}
export function direction(out: vec2, a: vec2, b: vec2) {
const a1 = aProjectFlat([a[0], a[1]]) as [number, number];
const b1 = aProjectFlat([b[0], b[1]]) as [number, number];
vec2.sub(out, a1, b1);
export function direction(out: vec2, a: [number, number], b: [number, number]) {
// const a1 = aProjectFlat([a[0], a[1]]) as [number, number];
// const b1 = aProjectFlat([b[0], b[1]]) as [number, number];
vec2.sub(out, a, b);
vec2.normalize(out, out);
return out;
}
@ -47,9 +47,7 @@ function addNext(
miters.push(length);
}
function lineSegmentDistance(end: vec2, start: vec2) {
const a1 = aProjectFlat([start[0], start[1]]);
const b1 = aProjectFlat([end[0], end[1]]);
function lineSegmentDistance(b1: vec2, a1: vec2) {
const dx = a1[0] - b1[0];
const dy = a1[1] - b1[1];
return Math.sqrt(dx * dx + dy * dy);
@ -110,11 +108,14 @@ export default function(
}
}
let d = 0;
const flatCur = aProjectFlat([cur[0], cur[1]]) as [number, number];
const flatLast = aProjectFlat([last[0], last[1]]) as [number, number];
if (isDash) {
const lineDistance = lineSegmentDistance(cur, last);
const lineDistance = lineSegmentDistance(flatCur, flatLast);
d = lineDistance + attrDistance[attrDistance.length - 1];
}
direction(lineA, cur, last);
direction(lineA, flatCur, flatLast);
if (!lineNormal) {
lineNormal = vec2.create();
computeNormal(lineNormal, lineA);
@ -136,8 +137,9 @@ export default function(
attrIndex.push(index + 1, index + 2, index + 3);
count += 2;
} else {
const flatNext = aProjectFlat([next[0], next[1]]) as [number, number];
// get unit dir of next line
direction(lineB, next, cur);
direction(lineB, flatNext, flatCur);
// stores tangent & miter
let miterLen = computeMiter(

View File

@ -331,7 +331,7 @@ export default class AMapService
amapLoaded = true;
plugin.push('Map3D');
this.loadAMapScript(
`https://webapi.amap.com/maps?v=${AMAP_VERSION}&key=${token}&plugin=${plugin.join(
`//webapi.amap.com/maps?v=${AMAP_VERSION}&key=${token}&plugin=${plugin.join(
',',
)}`,
).then(() => {

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,6 @@ export default function geoJSON(
data: FeatureCollection<Geometries, Properties>,
cfg?: IParserCFG,
): IParserData {
rewind(data, true); // 设置地理多边形方向 If clockwise is true, the outer ring is clockwise, otherwise it is counterclockwise.
const resultData: IParseDataItem[] = [];
const featureKeys: IFeatureKey = {};
data.features = data.features.filter((item: Feature) => {
@ -34,6 +33,7 @@ export default function geoJSON(
geometry.coordinates.length > 0
);
});
rewind(data, true); // 设置地理多边形方向 If clockwise is true, the outer ring is clockwise, otherwise it is counterclockwise.
if (data.features.length === 0) {
return {
dataArray: [],

View File

@ -56,7 +56,7 @@ export default class Source extends EventEmitter {
constructor(data: any, cfg?: ISourceCFG) {
super();
this.rawData = cloneDeep(data);
// this.rawData = cloneDeep(data);
this.originData = data;
if (cfg) {
if (cfg.parser) {
@ -89,7 +89,7 @@ export default class Source extends EventEmitter {
public setData(data: any) {
this.rawData = data;
this.originData = cloneDeep(data);
this.originData = data;
this.init();
this.emit('update');
}
@ -137,11 +137,18 @@ export default class Source extends EventEmitter {
}
public getFeatureById(id: number): unknown {
const { type = 'geojson' } = this.parser;
if (type === 'geojson' && !this.cluster && this.transforms.length === 0) {
// TODO 聚合图层返回聚合和后的数据
return id < this.originData.features.length
if (type === 'geojson' && !this.cluster) {
const feature =
id < this.originData.features.length
? this.originData.features[id]
: 'null';
if (this.transforms.length !== 0) {
const item = this.data.dataArray.find((dataItem: IParseDataItem) => {
return dataItem._id === id;
});
feature.properties = item;
}
return feature;
} else {
return id < this.data.dataArray.length ? this.data.dataArray[id] : 'null';
}

View File

@ -169,7 +169,7 @@ export function aProjectFlat(lnglat: number[]) {
d = 0.5;
x = scale * (a * x + b);
y = scale * (c * y + d);
return [parseInt(x.toString(), 10), parseInt(y.toString(), 10)];
return [Math.floor(x), Math.floor(y)];
}
export function unProjectFlat(px: number[]): [number, number] {
const a = 0.5 / Math.PI;

View File

@ -0,0 +1,66 @@
import { Scene } from '@antv/l7';
import { CountryLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import * as React from 'react';
export default class Country extends React.Component {
// @ts-ignore
private scene: Scene;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
const Layer = new CountryLayer(scene, {
data: [],
depth: 1,
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,351 @@
import { Scene } from '@antv/l7';
import { CountryLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import * as React from 'react';
export default class Country extends React.Component {
// @ts-ignore
private scene: Scene;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 1,
maxZoom: 4,
}),
});
const data = [
{
name: '湖北',
confirm: 16678,
suspect: 0,
heal: 533,
dead: 479,
},
{
name: '广东',
confirm: 895,
suspect: 0,
heal: 37,
dead: 0,
},
{
name: '浙江',
confirm: 895,
suspect: 0,
heal: 65,
dead: 0,
},
{
name: '河南',
confirm: 764,
suspect: 0,
heal: 41,
dead: 2,
},
{
name: '湖南',
confirm: 661,
suspect: 0,
heal: 35,
dead: 0,
},
{
name: '江西',
confirm: 548,
suspect: 0,
heal: 27,
dead: 0,
},
{
name: '安徽',
confirm: 530,
suspect: 0,
heal: 20,
dead: 0,
},
{
name: '重庆',
confirm: 376,
suspect: 0,
heal: 15,
dead: 2,
},
{
name: '江苏',
confirm: 341,
suspect: 0,
heal: 13,
dead: 0,
},
{
name: '山东',
confirm: 307,
suspect: 0,
heal: 13,
dead: 0,
},
{
name: '四川',
confirm: 301,
suspect: 0,
heal: 23,
dead: 1,
},
{
name: '北京',
confirm: 253,
suspect: 0,
heal: 24,
dead: 1,
},
{
name: '上海',
confirm: 243,
suspect: 0,
heal: 15,
dead: 1,
},
{
name: '福建',
confirm: 205,
suspect: 0,
heal: 7,
dead: 0,
},
{
name: '黑龙江',
confirm: 190,
suspect: 0,
heal: 7,
dead: 2,
},
{
name: '陕西',
confirm: 165,
suspect: 0,
heal: 6,
dead: 0,
},
{
name: '广西',
confirm: 150,
suspect: 0,
heal: 10,
dead: 0,
},
{
name: '河北',
confirm: 135,
suspect: 0,
heal: 4,
dead: 1,
},
{
name: '云南',
confirm: 124,
suspect: 0,
heal: 5,
dead: 0,
},
{
name: '海南',
confirm: 91,
suspect: 0,
heal: 4,
dead: 1,
},
{
name: '辽宁',
confirm: 81,
suspect: 0,
heal: 3,
dead: 0,
},
{
name: '山西',
confirm: 81,
suspect: 0,
heal: 4,
dead: 0,
},
{
name: '天津',
confirm: 69,
suspect: 0,
heal: 2,
dead: 1,
},
{
name: '贵州',
confirm: 64,
suspect: 0,
heal: 8,
dead: 0,
},
{
name: '甘肃',
confirm: 57,
suspect: 0,
heal: 4,
dead: 0,
},
{
name: '吉林',
confirm: 54,
suspect: 0,
heal: 1,
dead: 0,
},
{
name: '内蒙古',
confirm: 42,
suspect: 0,
heal: 3,
dead: 0,
},
{
name: '宁夏',
confirm: 34,
suspect: 0,
heal: 1,
dead: 0,
},
{
name: '新疆',
confirm: 32,
suspect: 0,
heal: 0,
dead: 0,
},
{
name: '香港',
confirm: 18,
suspect: 0,
heal: 0,
dead: 1,
},
{
name: '青海',
confirm: 17,
suspect: 0,
heal: 3,
dead: 0,
},
{
name: '台湾',
confirm: 11,
suspect: 0,
heal: 0,
dead: 0,
},
{
name: '澳门',
confirm: 10,
suspect: 0,
heal: 0,
dead: 0,
},
{
name: '西藏',
confirm: 1,
suspect: 0,
heal: 0,
dead: 0,
},
];
scene.on('loaded', () => {
const Layer = new CountryLayer(scene, {
data,
depth: 1,
fill: {
scale: 'quantile',
field: 'confirm',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
});
});
this.scene = scene;
const scene2 = new Scene({
id: 'map2',
logoVisible: false,
map: new Mapbox({
center: [113.60540108435657, 12.833692637803168],
pitch: 0,
style: 'blank',
zoom: 1.93,
minZoom: 0,
maxZoom: 3,
interactive: false,
}),
});
scene2.on('loaded', () => {
const Layer2 = new CountryLayer(scene2, {
data,
label: {
enable: false,
},
popup: {
enable: false,
},
autoFit: false,
fill: {
scale: 'quantile',
field: 'confirm',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
});
});
}
public render() {
return (
<>
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
<div
id="map2"
style={{
position: 'absolute',
height: '125px',
width: '98px',
right: '100px',
bottom: '20px',
border: '1px solid #333',
}}
/>
</>
);
}
}

View File

@ -0,0 +1,101 @@
import { Scene } from '@antv/l7';
import { CityLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { Cascader } from 'antd';
import * as React from 'react';
export default class Country extends React.Component {
public state = {
options: [],
};
// @ts-ignore
private scene: Scene;
private cityLayer: CityLayer;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const res = await fetch(
'https://gw.alipayobjects.com/os/bmw-prod/551e3ca6-6dad-421b-a8b4-b225e47f73ca.json',
);
const options = await res.json();
this.setState({
options,
});
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
this.cityLayer = new CityLayer(scene, {
data: [],
adcode: ['110100'],
depth: 3,
label: {
field: 'NAME_CHN',
textAllowOverlap: false,
},
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<>
<Cascader
style={{
width: 200,
zIndex: 2,
position: 'absolute',
right: '10px',
top: '10px',
}}
options={this.state.options}
defaultValue={['110000', '110100']}
onChange={this.handleProvinceChange}
placeholder="Please select"
/>
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
</>
);
}
private handleProvinceChange = (value: string[]) => {
this.cityLayer.updateDistrict([value[1]]);
};
}

View File

@ -0,0 +1,70 @@
import { Scene } from '@antv/l7';
import { CountryLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import * as React from 'react';
export default class Country extends React.Component {
// @ts-ignore
private scene: Scene;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
const Layer = new CountryLayer(scene, {
data: [],
depth: 2,
stroke: '#fff',
coastlineWidth: 0.5,
nationalWidth: 0.5,
fill: {
// scale: 'quantile',
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,71 @@
import { Scene } from '@antv/l7';
import { CountryLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import * as React from 'react';
export default class Country extends React.Component {
// @ts-ignore
private scene: Scene;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
const Layer = new CountryLayer(scene, {
data: [],
depth: 3,
stroke: '#fff',
strokeWidth: 1,
coastlineWidth: 0.5,
nationalWidth: 0.5,
fill: {
// scale: 'quantile',
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,100 @@
import { Scene } from '@antv/l7';
import { CountyLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { Cascader } from 'antd';
import * as React from 'react';
export default class Country extends React.Component {
public state = {
options: [],
};
// @ts-ignore
private scene: Scene;
private countyLayer: CountyLayer;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const res = await fetch(
'https://gw.alipayobjects.com/os/bmw-prod/04de56cc-5998-4f7e-9ad3-e87e9ac5fd39.json',
);
const options = await res.json();
this.setState({
options,
});
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
this.countyLayer = new CountyLayer(scene, {
data: [],
adcode: ['110101'],
depth: 3,
label: {
field: 'NAME_CHN',
},
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<>
<Cascader
style={{
width: 200,
zIndex: 2,
position: 'absolute',
right: '10px',
top: '10px',
}}
options={this.state.options}
defaultValue={['110000', '110100', '110101']}
onChange={this.handleProvinceChange}
placeholder="Please select"
/>
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
</>
);
}
private handleProvinceChange = (value: string[]) => {
this.countyLayer.updateDistrict([value[2]]);
};
}

View File

@ -0,0 +1,73 @@
import { Scene } from '@antv/l7';
import { DrillDownLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import { Cascader } from 'antd';
import * as React from 'react';
export default class Country extends React.Component {
public state = {
options: [],
};
// @ts-ignore
private scene: Scene;
private drillDown: DrillDownLayer;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'dark',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
this.scene = scene;
this.drillDown = new DrillDownLayer(scene, {
data: [],
depth: 1,
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
}
public render() {
return (
<>
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
</>
);
}
}

View File

@ -0,0 +1,244 @@
import { Scene } from '@antv/l7';
import { ProvinceLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
// tslint:disable-next-line:no-submodule-imports
import { Select } from 'antd';
import * as React from 'react';
const { Option } = Select;
const ProvinceData = [
{
NAME_CHN: '云南省',
adcode: 530000,
},
{
NAME_CHN: '黑龙江省',
adcode: 230000,
},
{
NAME_CHN: '贵州省',
adcode: 520000,
},
{
NAME_CHN: '北京市',
adcode: 110000,
},
{
NAME_CHN: '河北省',
adcode: 130000,
},
{
NAME_CHN: '山西省',
adcode: 140000,
},
{
NAME_CHN: '吉林省',
adcode: 220000,
},
{
NAME_CHN: '宁夏回族自治区',
adcode: 640000,
},
{
NAME_CHN: '辽宁省',
adcode: 210000,
},
{
NAME_CHN: '海南省',
adcode: 460000,
},
{
NAME_CHN: '内蒙古自治区',
adcode: 150000,
},
{
NAME_CHN: '天津市',
adcode: 120000,
},
{
NAME_CHN: '新疆维吾尔自治区',
adcode: 650000,
},
{
NAME_CHN: '上海市',
adcode: 310000,
},
{
NAME_CHN: '陕西省',
adcode: 610000,
},
{
NAME_CHN: '甘肃省',
adcode: 620000,
},
{
NAME_CHN: '安徽省',
adcode: 340000,
},
{
NAME_CHN: '香港特别行政区',
adcode: 810000,
},
{
NAME_CHN: '广东省',
adcode: 440000,
},
{
NAME_CHN: '河南省',
adcode: 410000,
},
{
NAME_CHN: '湖南省',
adcode: 430000,
},
{
NAME_CHN: '江西省',
adcode: 360000,
},
{
NAME_CHN: '四川省',
adcode: 510000,
},
{
NAME_CHN: '广西壮族自治区',
adcode: 450000,
},
{
NAME_CHN: '江苏省',
adcode: 320000,
},
{
NAME_CHN: '澳门特别行政区',
adcode: 820000,
},
{
NAME_CHN: '浙江省',
adcode: 330000,
},
{
NAME_CHN: '山东省',
adcode: 370000,
},
{
NAME_CHN: '青海省',
adcode: 630000,
},
{
NAME_CHN: '重庆市',
adcode: 500000,
},
{
NAME_CHN: '福建省',
adcode: 350000,
},
{
NAME_CHN: '湖北省',
adcode: 420000,
},
{
NAME_CHN: '西藏自治区',
adcode: 540000,
},
{
NAME_CHN: '台湾省',
adcode: 710000,
},
];
export default class Country extends React.Component {
public state = {
province: '110000',
};
// @ts-ignore
private scene: Scene;
private provinceLayer: ProvinceLayer;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 3,
minZoom: 3,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
const { province } = this.state;
this.provinceLayer = new ProvinceLayer(scene, {
data: [],
adcode: [],
depth: 3,
label: {
field: 'NAME_CHN',
textAllowOverlap: false,
},
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
popup: {
enable: true,
Html: (props) => {
return `<span>${props.NAME_CHN}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<>
<Select
defaultValue="北京市"
style={{
width: 120,
zIndex: 2,
position: 'absolute',
right: '10px',
top: '10px',
}}
onChange={this.handleProvinceChange}
>
{ProvinceData.map((province, i) => {
return (
<Option key={i} value={province.adcode}>
{province.NAME_CHN}
</Option>
);
})}
</Select>
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
</>
);
}
private handleProvinceChange = (value: string) => {
this.setState({
province: value,
});
this.provinceLayer.updateDistrict([value]);
};
}

View File

@ -0,0 +1,71 @@
import { Scene } from '@antv/l7';
import { WorldLayer } from '@antv/l7-district';
import { GaodeMap, Mapbox } from '@antv/l7-maps';
import * as React from 'react';
export default class Country extends React.Component {
// @ts-ignore
private scene: Scene;
public componentWillUnmount() {
this.scene.destroy();
}
public async componentDidMount() {
const scene = new Scene({
id: 'map',
map: new Mapbox({
center: [116.2825, 39.9],
pitch: 0,
style: 'blank',
zoom: 0,
minZoom: 0,
maxZoom: 10,
}),
});
scene.on('loaded', () => {
const Layer = new WorldLayer(scene, {
data: [],
fill: {
field: 'NAME_CHN',
values: [
'#feedde',
'#fdd0a2',
'#fdae6b',
'#fd8d3c',
'#e6550d',
'#a63603',
],
},
stroke: '#ccc',
label: {
enable: false,
textAllowOverlap: false,
field: 'Short_Name_ZH',
},
popup: {
enable: false,
Html: (props) => {
return `<span>${props.Short_Name_ZH}</span>`;
},
},
});
});
this.scene = scene;
}
public render() {
return (
<div
id="map"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}}
/>
);
}
}

View File

@ -0,0 +1,23 @@
import { storiesOf } from '@storybook/react';
require('./../assets/css/antd.css');
import * as React from 'react';
import City from './Layer/city';
import Country from './Layer/Country';
import Country2 from './Layer/Country2';
import CountryCity from './Layer/country_city';
import CountryCounty from './Layer/country_county';
import County from './Layer/county';
import DrillDown from './Layer/drillDown';
import Province from './Layer/province';
import World from './Layer/world';
storiesOf('行政区划', module)
.add('世界地图', () => <World />)
.add('中国地图', () => <Country />)
.add('中国地图市级', () => <CountryCity />)
.add('中国地图县级', () => <CountryCounty />)
.add('中国地图附图', () => <Country2 />)
.add('县级地图', () => <County />)
.add('市级地图', () => <City />)
.add('上钻下取', () => <DrillDown />)
.add('省级地图', () => <Province />);

27500
stories/assets/css/antd.css Normal file

File diff suppressed because it is too large Load Diff

1549
yarn.lock

File diff suppressed because it is too large Load Diff