├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .eslintignore ├── .eslintrc.cjs ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── node.js.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .releaserc ├── LICENSE ├── README.md ├── __mocks__ └── svg.js ├── jest.config.js ├── jest.setup.ts ├── package-lock.json ├── package.json ├── packages ├── charts │ ├── .gitignore │ ├── .umirc.ts │ ├── CHANGELOG.md │ ├── docs │ │ ├── api.md │ │ ├── bar-chart │ │ │ ├── basic.json │ │ │ ├── horizontal-bars.json │ │ │ ├── index.md │ │ │ ├── multiple-bars.json │ │ │ ├── stacked.json │ │ │ ├── with-line.json │ │ │ └── with-scatter.json │ │ ├── data │ │ │ ├── locales │ │ │ │ ├── en-US │ │ │ │ │ ├── china-cities.ts │ │ │ │ │ └── china-provinces.ts │ │ │ │ └── zh-CN │ │ │ │ │ └── world-countries.ts │ │ │ └── maps │ │ │ │ ├── README.md │ │ │ │ ├── china-cities.json │ │ │ │ ├── china-contour.json │ │ │ │ ├── china.json │ │ │ │ ├── province │ │ │ │ ├── anhui.json │ │ │ │ ├── aomen.json │ │ │ │ ├── beijing.json │ │ │ │ ├── chongqing.json │ │ │ │ ├── fujian.json │ │ │ │ ├── gansu.json │ │ │ │ ├── guangdong.json │ │ │ │ ├── guangxi.json │ │ │ │ ├── guizhou.json │ │ │ │ ├── hainan.json │ │ │ │ ├── hebei.json │ │ │ │ ├── heilongjiang.json │ │ │ │ ├── henan.json │ │ │ │ ├── hubei.json │ │ │ │ ├── hunan.json │ │ │ │ ├── jiangsu.json │ │ │ │ ├── jiangxi.json │ │ │ │ ├── jilin.json │ │ │ │ ├── liaoning.json │ │ │ │ ├── neimenggu.json │ │ │ │ ├── ningxia.json │ │ │ │ ├── qinghai.json │ │ │ │ ├── shandong.json │ │ │ │ ├── shanghai.json │ │ │ │ ├── shanxi.json │ │ │ │ ├── shanxi1.json │ │ │ │ ├── sichuan.json │ │ │ │ ├── taiwan.json │ │ │ │ ├── tianjin.json │ │ │ │ ├── xianggang.json │ │ │ │ ├── xinjiang.json │ │ │ │ ├── xizang.json │ │ │ │ ├── yunnan.json │ │ │ │ └── zhejiang.json │ │ │ │ └── world.json │ │ ├── echarts │ │ │ ├── index.md │ │ │ ├── loading.json │ │ │ └── option.json │ │ ├── funnel-chart │ │ │ └── index.md │ │ ├── index.md │ │ ├── line-chart │ │ │ ├── basic.json │ │ │ ├── index.md │ │ │ ├── multiple-lines.json │ │ │ └── multiple-yaxis.json │ │ ├── map-chart │ │ │ ├── basic.json │ │ │ └── index.md │ │ ├── pie-chart │ │ │ ├── basic.json │ │ │ ├── donut.json │ │ │ └── index.md │ │ ├── radar-chart │ │ │ ├── basic.json │ │ │ └── index.md │ │ ├── sankey-chart │ │ │ ├── basic.json │ │ │ └── index.md │ │ ├── scatter-chart │ │ │ └── index.md │ │ ├── tree-chart │ │ │ ├── basic.json │ │ │ └── index.md │ │ └── treemap-chart │ │ │ ├── basic.json │ │ │ └── index.md │ ├── package.json │ ├── src │ │ ├── ECharts.test.tsx │ │ ├── ECharts.tsx │ │ ├── assets │ │ │ └── chart-nodata.svg │ │ ├── charts │ │ │ ├── BarChart.tsx │ │ │ ├── FunnelChart.tsx │ │ │ ├── LineChart.tsx │ │ │ ├── MapChart.tsx │ │ │ ├── PieChart.tsx │ │ │ ├── RadarChart.tsx │ │ │ ├── SankeyChart.tsx │ │ │ ├── ScatterChart.tsx │ │ │ ├── TreeChart.tsx │ │ │ └── TreemapChart.tsx │ │ ├── components │ │ │ ├── DataZoom.test.tsx │ │ │ ├── DataZoom.ts │ │ │ ├── Dataset.test.tsx │ │ │ ├── Dataset.ts │ │ │ ├── Legend.test.tsx │ │ │ ├── Legend.ts │ │ │ ├── Radar.test.tsx │ │ │ ├── Radar.ts │ │ │ ├── Tooltip.test.tsx │ │ │ ├── Tooltip.ts │ │ │ ├── VisualMap.test.tsx │ │ │ ├── VisualMap.ts │ │ │ ├── XAxis.test.tsx │ │ │ ├── XAxis.ts │ │ │ ├── YAxis.test.tsx │ │ │ └── YAxis.ts │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── series │ │ │ ├── Bars.test.tsx │ │ │ ├── Bars.ts │ │ │ ├── Funnel.test.tsx │ │ │ ├── Funnel.ts │ │ │ ├── Line.test.tsx │ │ │ ├── Line.ts │ │ │ ├── Map.test.tsx │ │ │ ├── Map.ts │ │ │ ├── Pie.test.tsx │ │ │ ├── Pie.ts │ │ │ ├── RadarLine.test.tsx │ │ │ ├── RadarLine.ts │ │ │ ├── Sankey.test.tsx │ │ │ ├── Sankey.ts │ │ │ ├── Scatter.test.tsx │ │ │ ├── Scatter.ts │ │ │ ├── Tree.test.tsx │ │ │ ├── Tree.ts │ │ │ ├── Treemap.test.tsx │ │ │ └── Treemap.ts │ │ ├── svgr.d.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── tsconfig.json │ └── tsup.config.ts └── echarts-theme-rsuite │ ├── .gitignore │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ ├── index.ts │ ├── rsuite_dark.project.json │ ├── rsuite_dark.ts │ ├── rsuite_light.project.json │ └── rsuite_light.ts │ └── tsconfig.json ├── tsconfig.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "access": "public", 6 | "baseBranch": "master", 7 | "updateInternalDependencies": "patch", 8 | "ignore": [] 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_style = space 9 | indent_size = 2 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [package.json] 14 | indent_style = space 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /bin/** 2 | /build/** 3 | *.d.ts 4 | dist -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint'], 5 | extends: [ 6 | 'eslint:recommended', 7 | 'plugin:@typescript-eslint/recommended', 8 | 'plugin:react/recommended', 9 | 'plugin:react-hooks/recommended', 10 | 'prettier', 11 | ], 12 | rules: { 13 | '@typescript-eslint/no-empty-interface': [ 14 | 'error', 15 | { 16 | allowSingleExtends: true, 17 | }, 18 | ], 19 | }, 20 | settings: { 21 | react: { 22 | version: 'detect', 23 | }, 24 | }, 25 | overrides: [ 26 | { 27 | files: ['*.js', '*.cjs'], 28 | env: { 29 | node: true, 30 | }, 31 | rules: { 32 | '@typescript-eslint/no-var-requires': 'off', 33 | }, 34 | }, 35 | { 36 | files: ['docs/*.js'], 37 | env: { 38 | browser: true, 39 | }, 40 | }, 41 | ], 42 | }; 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Smartphone (please complete the following information):** 33 | 34 | - Device: [e.g. iPhone6] 35 | - OS: [e.g. iOS8.1] 36 | - Browser [e.g. stock browser, safari] 37 | - Version [e.g. 22] 38 | 39 | **Additional context** 40 | Add any other context about the problem here. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | strategy: 15 | matrix: 16 | react-version: [16, 17, 18] 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Use Node.js LTS 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: 'lts/*' 23 | - run: npm ci --force 24 | - run: npm run build 25 | - run: npm test -- --coverage 26 | env: 27 | REACT: ${{ matrix.react-version }} 28 | - name: Upload coverage to Codecov 29 | uses: codecov/codecov-action@v2 30 | with: 31 | flags: React-${{ matrix.react-version }} 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | lib/ 40 | .DS_Store 41 | 42 | .vscode/ 43 | yarn.lock 44 | 45 | .idea 46 | es/ 47 | *.tgz 48 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | coverage 3 | .umi -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 2, 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "master", 4 | { 5 | "name": "next", 6 | "prerelease": "beta" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Suite Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Charts for React Suite 2 | 3 | :bar_chart: A set of charts based on rsuite and ECharts 4 | 5 | [![npm version](https://badge.fury.io/js/%40rsuite%2Fcharts.svg)](https://badge.fury.io/js/%40rsuite%2Fcharts) 6 | [![Node.js CI](https://github.com/rsuite/charts/actions/workflows/node.js.yml/badge.svg)](https://github.com/rsuite/charts/actions/workflows/node.js.yml) 7 | [![codecov](https://codecov.io/gh/rsuite/charts/branch/master/graph/badge.svg?token=boxBzGyjGx)](https://codecov.io/gh/rsuite/charts) 8 | [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) 9 | 10 | ## Install 11 | 12 | ```bash 13 | npm i --save @rsuite/charts echarts 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```js 19 | import { LineChart } from '@rsuite/charts'; 20 | 21 | const data = [ 22 | ['00:00', random()], 23 | ['01:00', random()], 24 | ]; 25 | const App = () => ; 26 | 27 | ReactDOM.render(, mountNode); 28 | ``` 29 | 30 | ![](https://user-images.githubusercontent.com/1203827/53936390-93543000-40e4-11e9-9892-98cadb183fc6.png) 31 | 32 | ## Documentation 33 | 34 | [https://charts.rsuitejs.com/](https://charts.rsuitejs.com/) 35 | 36 | ## License 37 | 38 | MIT licensed 39 | -------------------------------------------------------------------------------- /__mocks__/svg.js: -------------------------------------------------------------------------------- 1 | export default 'SvgrURL'; 2 | export const ReactComponent = 'div'; 3 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transform: { 3 | '^.+\\.(t|j)sx?$': [ 4 | '@swc-node/jest', 5 | { 6 | react: { 7 | runtime: 'automatic', 8 | }, 9 | }, 10 | ], 11 | }, 12 | testEnvironment: 'jsdom', 13 | setupFilesAfterEnv: ['./jest.setup.ts'], 14 | transformIgnorePatterns: ['/node_modules/(?!echarts|zrender)'], 15 | moduleNameMapper: { 16 | '\\.svg': '/__mocks__/svg.js', 17 | }, 18 | }; 19 | 20 | if (process.env.REACT === '17') { 21 | module.exports.moduleNameMapper = { 22 | ...module.exports.moduleNameMapper, 23 | '^react((\\/.*)?)$': 'react-17$1', 24 | '^react-dom((\\/.*)?)$': 'react-dom-17$1', 25 | }; 26 | } 27 | 28 | if (process.env.REACT === '18') { 29 | module.exports.moduleNameMapper = { 30 | ...module.exports.moduleNameMapper, 31 | '^react((\\/.*)?)$': 'react-18$1', 32 | '^react-dom((\\/.*)?)$': 'react-dom-18$1', 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /jest.setup.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "workspaces": [ 3 | "packages/*" 4 | ], 5 | "scripts": { 6 | "build": "turbo run build", 7 | "format": "prettier --write .", 8 | "format:check": "prettier --list-different \"{src,test,docs}/**/*.js\"", 9 | "dev": "turbo run dev --filter=@rsuite/charts", 10 | "docs": "turbo run build-docs --filter=@rsuite/charts", 11 | "publish-docs": "node docs/gh-pages.js", 12 | "prepages": "npm run docs", 13 | "pages": "npm run publish-docs", 14 | "prepublishOnly": "npm run build", 15 | "lint": "eslint .", 16 | "test": "jest" 17 | }, 18 | "devDependencies": { 19 | "@changesets/cli": "^2.23.0", 20 | "@swc-node/jest": "^1.5.2", 21 | "@testing-library/jest-dom": "^5.11.9", 22 | "@testing-library/react": "^11.2.5", 23 | "@types/jest": "^26.0.20", 24 | "@types/lodash.merge": "^4.6.6", 25 | "@types/lodash.omit": "^4.5.6", 26 | "@typescript-eslint/eslint-plugin": "^5.28.0", 27 | "@typescript-eslint/parser": "^5.28.0", 28 | "cross-env": "^7.0.3", 29 | "dumi": "^1.1.42", 30 | "esbuild-plugin-svgr": "^1.0.1", 31 | "eslint": "^8.17.0", 32 | "eslint-config-prettier": "^8.5.0", 33 | "eslint-plugin-react": "^7.30.0", 34 | "eslint-plugin-react-hooks": "^4.6.0", 35 | "gh-pages": "^4.0.0", 36 | "jest": "^26.6.3", 37 | "prettier": "^2.7.0", 38 | "react": "^16.8.2", 39 | "react-dom": "^16.8.2", 40 | "react-17": "npm:react@^17.0.0", 41 | "react-dom-17": "npm:react-dom@^17.0.0", 42 | "react-18": "npm:react@^18.0.0", 43 | "react-dom-18": "npm:react-dom@^18.0.0", 44 | "tsup": "^6.1.2", 45 | "turbo": "^1.3.1", 46 | "typescript": "^4.7.3" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/charts/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | dumi-dist 3 | **/.umi*/ -------------------------------------------------------------------------------- /packages/charts/.umirc.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | outputPath: 'dumi-dist', 3 | }; 4 | -------------------------------------------------------------------------------- /packages/charts/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @rsuite/charts 2 | 3 | ## 5.2.3 4 | 5 | ### Patch Changes 6 | 7 | - 206db7f: Fix wrong package files. 8 | 9 | ## 5.2.2 10 | 11 | ### Patch Changes 12 | 13 | - bbd781c: Add React 18 to compatible peerDepedencies 14 | 15 | ## 5.2.1 16 | 17 | ### Patch Changes 18 | 19 | - d94baeb: Fix MapChart throwing when data is empty 20 | 21 | ## 5.2.0 22 | 23 | ### Minor Changes 24 | 25 | - 779aef1: Improve empty placeholder for ECharts and add renderEmptyPlaceholder prop for customization. 26 | 27 | ## 5.2.0-alpha.0 28 | 29 | ### Minor Changes 30 | 31 | - 779aef1: Improve empty placeholder for ECharts and add renderEmptyPlaceholder prop for customization. 32 | 33 | ## 5.1.0 34 | 35 | ### Patch Changes 36 | 37 | - d247c45: Separate echarts-theme-rsuite as a standalone package 38 | - Updated dependencies [d247c45] 39 | - echarts-theme-rsuite@1.0.0 40 | 41 | ## 5.1.0-beta.5 42 | 43 | ### Patch Changes 44 | 45 | - d247c45: Separate echarts-theme-rsuite as a standalone package 46 | - Updated dependencies [d247c45] 47 | - echarts-theme-rsuite@0.0.0-beta.0 48 | -------------------------------------------------------------------------------- /packages/charts/docs/api.md: -------------------------------------------------------------------------------- 1 | # API 2 | 3 | `@rsuite/charts` 中的 React 组件对应 ECharts 配置项中的各个部分。 4 | 除特殊说明的 props 外,它们会将接收的所有 props 直接转换为相应的 ECharts  配置项。 5 | 6 | 如: 7 | 8 | ```jsx | pure 9 | 10 | ``` 11 | 12 | 即对应: 13 | 14 | ```js | pure 15 | { 16 | xAxis: { 17 | type: "value", 18 | minInterval: 10000 19 | } 20 | } 21 | ``` 22 | 23 | ### `` 24 | 25 | `` 是 `@rsuite/charts` 中最基础的组件, 26 | 接收 option 参数, 27 | 生成一个 ECharts 图表。 28 | 29 | | prop | type | default | description | 30 | | ------- | --------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------- | 31 | | option | `object` | | ECharts 配置项,详见 [ECharts 配置项手册](http://echarts.baidu.com/option.html) | 32 | | loading | `boolean` | `false` | 显示 loading 状态 | 33 | | height | `number` | 300 | 图表高度 | 34 | | locale | `object<{emptyMessage, loading}>` | `{emptyMessage: 'No data found', loading: 'Loading...'}` | 数据为空/loading 时显示的信息 | 35 | 36 | ### Series 37 | 38 | `series` 是展示数据的主要组件 39 | 40 | ```jsx | pure 41 | import { Line, Bars, Scatter, Pie, Map, Tree, Treemap, Sankey } from '@rsuite/charts'; 42 | ``` 43 | 44 | 分别对应 [ECharts 配置项中各个 type 的 series](http://echarts.baidu.com/option.html#series)。 45 | 46 | 除了 `` `` `` 外,其他的 `series` 通常不会单独使用,而是继承相应的 `charts` 接收的 props。如 `` 会从 `` 继承 `donut` 等 props。 47 | 48 | #### `` 49 | 50 | | prop | type | default | description | 51 | | ----- | ----------------------- | ------- | --------------------------------------------------------------------------------------------------- | 52 | | stack | `boolean`|`string` | | 当设为 `true` 时,所有 `stack={true}` 的 `` 会在同一个堆叠中。其它用法同 ECharts 配置项手册。 | 53 | | area | `boolean` | `false` | 设为 `true` 时,相当于设置 `areaStyle={{opacity: 0.2}}`。 | 54 | 55 | #### `` 56 | 57 | | prop | type | default | description | 58 | | ----- | ----------------------------- | ------- | --------------------------------------------------------------------------------------------------- | 59 | | stack | `boolean`|`string` | | 当设为 `true` 时,所有 `stack={true}` 的 `` 会在同一个堆叠中。其它用法同 ECharts 配置项手册。 | 60 | | color | `string`|`array` | | 当设为数组时,该组图柱中的各条图柱将显示为数组中的各个颜色。其它用法同 ECharts 配置项手册。 | 61 | 62 | #### `` 63 | 64 | | prop | type | default | description | 65 | | ----- | --------- | ------- | ---------------------------------------------------------- | 66 | | donut | `boolean` | `false` | 是否为环形图。默认 `innerRadius` 比 `outerRadius` 小 15%。 | 67 | 68 | ### Components 69 | 70 | `components` 是图表的其他组成部分, 71 | 72 | ```jsx | pure 73 | import { XAxis, YAxis, Legend, Tooltip, DataZoom, VisualMap } from '@rsuite/charts'; 74 | ``` 75 | 76 | ### Charts 77 | 78 | `charts` 是 `@rsuite/charts` 预先封装的一些常用图表,通常包括一个默认 `series` 和一些默认 `components`。 79 | 80 | ```jsx | pure 81 | import { 82 | BarChart, 83 | FunnelChart, 84 | LineChart, 85 | MapChart, 86 | PieChart, 87 | RadarChart, 88 | SankeyChart, 89 | ScatterChart, 90 | TreeChart, 91 | TreemapChart, 92 | } from '@rsuite/charts'; 93 | ``` 94 | 95 | `charts` 都接收 `name` 和 `data` 两个 props,并传递给其内部的 `series`。大多时候,其他的 props 也会被传递下去。 96 | 97 | #### `` 和 `` 98 | 99 | 除了使用默认 `series` 之外,`` 和 `` 还可以手动添加更多的 `series`,并将 `data` 中的数据依次分配给它们。 100 | 101 | ```js | pure 102 | { 103 | data: [ 104 | [category, value1, value2, ...], 105 | ... 106 | ] 107 | } 108 | ``` 109 | 110 | ### 特殊 props 111 | 112 | `@rsuite/charts` 对一些常用的配置项进行了处理,使用更加简便。 113 | 114 | #### `textOption.formatter()` 115 | 116 | 如果对 `label` `axisLabel` `tooltip` 等 props 传入一个函数,`@rsuite/charts` 会自动将它用作该项配置的 `formatter` 字段。 117 | 118 | 如: 119 | 120 | ```jsx | pure 121 | `${value}%`} /> 122 | ``` 123 | 124 | 相当于: 125 | 126 | ```jsx | pure 127 | `${value}%`, 131 | }} 132 | /> 133 | ``` 134 | 135 | 类似地,如果传入一个字符串或数字,则被视作 `formatter()` 的返回值。 136 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/basic.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["1次", 4800000], 3 | ["2次", 1200000], 4 | ["3次", 800000], 5 | ["4次", 500000], 6 | ["5次", 400000], 7 | ["6次", 350000], 8 | ["7次", 300000], 9 | ["8次", 200000], 10 | ["9次", 150000], 11 | ["10次", 100000], 12 | ["10次+", 150000] 13 | ] 14 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/horizontal-bars.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["<15岁", 1, 2], 3 | ["16-25岁", 16, 18], 4 | ["26-35岁", 29, 30], 5 | ["36-45岁", 23, 20], 6 | ["46-55岁", 4, 3], 7 | [">55岁", 4, 3], 8 | ["未知", 8, 10] 9 | ] 10 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 柱状图 3 | --- 4 | 5 | # BarChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { BarChart } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ; 15 | ``` 16 | 17 | ## 多组图柱 18 | 19 | ```jsx 20 | import React from 'react'; 21 | import { BarChart, YAxis, Bars } from '@rsuite/charts'; 22 | import data from './multiple-bars.json'; 23 | 24 | export default () => ( 25 | 26 | `${value / 1000}K`} minInterval={500000} splitLine={false} /> 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | ``` 36 | 37 | ## 水平图柱 38 | 39 | ```jsx 40 | import React from 'react'; 41 | import { BarChart, XAxis, Bars } from '@rsuite/charts'; 42 | import data from './horizontal-bars.json'; 43 | 44 | export default () => ( 45 | 46 | `${value}K`} minInterval={15} /> 47 | 48 | 49 | 50 | ); 51 | ``` 52 | 53 | ## 堆叠图柱 54 | 55 | ```jsx 56 | import React from 'react'; 57 | import { BarChart, YAxis, Bars } from '@rsuite/charts'; 58 | import data from './stacked.json'; 59 | 60 | export default () => ( 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | ); 71 | ``` 72 | 73 | ## 在柱状图中添加折线 74 | 75 | ```jsx 76 | import React from 'react'; 77 | import { BarChart, YAxis, Bars, Line } from '@rsuite/charts'; 78 | import data from './with-line.json'; 79 | 80 | export default () => ( 81 | 82 | `${value / 1000}K`} /> 83 | 84 | 85 | 86 | ); 87 | ``` 88 | 89 | ## 在柱状图中添加散点 90 | 91 | ```jsx 92 | import React from 'react'; 93 | import { BarChart, Bars, Scatter } from '@rsuite/charts'; 94 | import data from './with-scatter.json'; 95 | 96 | export default () => ( 97 | 98 | 99 | 100 | 101 | ); 102 | ``` 103 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/multiple-bars.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["2018-03", 0, 980000, 0, 0, 0, 0], 3 | ["2018-04", 800000, 780000, 0, 180000, 0, 0], 4 | ["2018-05", 750000, 730000, 0, 180000, 0, 0], 5 | ["2018-06", 730000, 680000, 80000, 180000, 270000, 180000], 6 | ["2018-07", 730000, 680000, 80000, 180000, 270000, 180000], 7 | ["2018-08", 730000, 680000, 80000, 180000, 270000, 180000] 8 | ] 9 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/stacked.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["18-24岁", 650, 650, 750, 100, 100, 150], 3 | ["25-29岁", 200, 200, 1000, 100, 100, 150], 4 | ["30-34岁", 650, 650, 1400, 300, 250, 400], 5 | ["35-39岁", 750, 750, 1400, 300, 250, 400], 6 | ["40-44岁", 650, 650, 1300, 100, 100, 150], 7 | ["45-49岁", 650, 650, 1300], 8 | ["50-54岁", 650, 650, 1250], 9 | ["55岁+", 400, 450, 900] 10 | ] 11 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/with-line.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["2018-8-1", 1155168, 2140651], 3 | ["2018-8-2", 174303, 2643018], 4 | ["2018-8-3", 1204738, 2403906], 5 | ["2018-8-4", 528544, 1756223], 6 | ["2018-8-5", 1462146, 1319376], 7 | ["2018-8-6", 1369350, 1276033], 8 | ["2018-8-7", 1586491, 2647751], 9 | ["2018-8-8", 871780, 1046025], 10 | ["2018-8-9", 1643321, 1548328], 11 | ["2018-8-10", 1399218, 1527891], 12 | ["2018-8-11", 401678, 2652136], 13 | ["2018-8-12", 562678, 1791003], 14 | ["2018-8-13", 1828779, 2577522], 15 | ["2018-8-14", 436815, 1791301], 16 | ["2018-8-15", 1175730, 1501207], 17 | ["2018-8-16", 1803047, 2795674], 18 | ["2018-8-17", 929171, 1779035], 19 | ["2018-8-18", 1329717, 2196592], 20 | ["2018-8-19", 1849691, 2295164], 21 | ["2018-8-20", 628283, 1685463], 22 | ["2018-8-21", 389806, 2491230], 23 | ["2018-8-22", 1815758, 2066379], 24 | ["2018-8-23", 1095956, 1920822], 25 | ["2018-8-24", 1310876, 1637300], 26 | ["2018-8-25", 1653013, 1802276], 27 | ["2018-8-26", 123767, 1541151], 28 | ["2018-8-27", 17582, 2714247], 29 | ["2018-8-28", 152499, 1663036], 30 | ["2018-8-29", 1678072, 1805206], 31 | ["2018-8-30", 1070889, 2946885], 32 | ["2018-8-31", 1295320, 2580696] 33 | ] 34 | -------------------------------------------------------------------------------- /packages/charts/docs/bar-chart/with-scatter.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["新客", 26, 10], 3 | ["流失至竞品", 25, 11], 4 | ["老客", 49, 11], 5 | ["来自竞品", 5, 5], 6 | ["非品牌客户", 78, 12] 7 | ] 8 | -------------------------------------------------------------------------------- /packages/charts/docs/data/locales/en-US/china-cities.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable quotes */ 2 | export default { 3 | 三沙市: 'Sansha', 4 | 济源市: 'Jiyuan', 5 | 襄阳市: 'Xiangyang', 6 | 铁门关市: 'Tiemenguan', 7 | 北屯市: 'Beitun', 8 | 双河市: 'Shuanghe', 9 | 重庆市: 'Chongqing', 10 | 北京市: 'Beijing', 11 | 天津市: 'Tianjin', 12 | 上海市: 'Shanghai', 13 | 香港: 'Hong Kong', 14 | 澳门: 'Macao', 15 | 巴音郭楞蒙古自治州: 'Bayingol', 16 | 和田地区: 'Hotan', 17 | 哈密地区: 'Hami', 18 | 阿克苏地区: 'Aksu, Xinjiang', 19 | 阿勒泰地区: 'Altay', 20 | 喀什地区: 'Kashgar', 21 | 塔城地区: 'Qoqek', 22 | 昌吉回族自治州: 'Changji', 23 | 克孜勒苏柯尔克孜自治州: 'Kizilsu', 24 | 吐鲁番地区: 'Turpan', 25 | 伊犁哈萨克自治州: 'Ili', 26 | 博尔塔拉蒙古自治州: 'Bortala', 27 | 乌鲁木齐市: 'Urumqi', 28 | 克拉玛依市: 'Karamay', 29 | 阿里地区: 'Ngari,Tibet', 30 | 日喀则市: 'Shigatse', 31 | 林芝市: 'Nyingchi', 32 | 昌都市: 'Qamdo', 33 | 山南地区: 'Shannan,Tibet', 34 | 拉萨市: 'Lhasa', 35 | 呼伦贝尔市: 'Hulun Buir', 36 | 阿拉善盟: 'Alxa', 37 | 锡林郭勒盟: 'Xilin Gol', 38 | 鄂尔多斯市: 'Ordos', 39 | 赤峰市: 'Chifeng', 40 | 巴彦淖尔市: 'Bayan Nur', 41 | 通辽市: 'Tongliao', 42 | 乌兰察布市: 'Ulanqab', 43 | 兴安盟: 'Xinganmeng', 44 | 包头市: 'Baotou', 45 | 呼和浩特市: 'Hohhot', 46 | 乌海市: 'Wuhai', 47 | 海西蒙古族藏族自治州: 'Haixi', 48 | 玉树藏族自治州: 'Yushu', 49 | 果洛藏族自治州: 'Golog', 50 | 海南藏族自治州: 'Hainan (Qinghai)', 51 | 海北藏族自治州: 'Haibei', 52 | 黄南藏族自治州: 'Huangnan', 53 | 海东市: 'Haidong', 54 | 西宁市: 'Xining', 55 | 甘孜藏族自治州: 'Garze', 56 | 阿坝藏族羌族自治州: 'Aba', 57 | 凉山彝族自治州: 'Liangshan', 58 | 绵阳市: 'Mianyang', 59 | 达州市: 'Dazhou', 60 | 广元市: 'Guangyuan', 61 | 雅安市: 'Ya An', 62 | 宜宾市: 'Yibin', 63 | 乐山市: 'Leshan', 64 | 南充市: 'Nanchong', 65 | 巴中市: 'Bazhong', 66 | 泸州市: 'Luzhou', 67 | 成都市: 'Chengdu', 68 | 资阳市: 'Ziyang', 69 | 攀枝花市: 'Panzhihua', 70 | 眉山市: 'Meishan', 71 | 广安市: 'Guang An', 72 | 德阳市: 'Deyang', 73 | 内江市: 'Neijiang', 74 | 遂宁市: 'Suining', 75 | 自贡市: 'Zigong', 76 | 黑河市: 'Heihe', 77 | 大兴安岭地区: 'Da hinggan Ling', 78 | 哈尔滨市: 'Harbin', 79 | 齐齐哈尔市: 'Qiqihar', 80 | 牡丹江市: 'Mudanjiang', 81 | 绥化市: 'Suihua', 82 | 伊春市: 'Yichun', 83 | 佳木斯市: 'Jiamusi', 84 | 鸡西市: 'Jixi', 85 | 双鸭山市: 'Shuangyashan', 86 | 大庆市: 'Daqing', 87 | 鹤岗市: 'Hegang', 88 | 七台河市: 'Qitaihe', 89 | 酒泉市: 'Jiuquan', 90 | 张掖市: 'Zhangye', 91 | 甘南藏族自治州: 'Gannan', 92 | 武威市: 'Wuwei', 93 | 陇南市: 'Longnan', 94 | 庆阳市: 'Qingyang', 95 | 白银市: 'Baiyin', 96 | 定西市: 'Dingxi', 97 | 天水市: 'Tianshui', 98 | 兰州市: 'Lanzhou', 99 | 平凉市: 'Pingliang', 100 | 临夏回族自治州: 'Linxia', 101 | 金昌市: 'Jinchang', 102 | 嘉峪关市: 'Jiayuguan', 103 | 普洱市: "Pu'er", 104 | 红河哈尼族彝族自治州: 'Honghe', 105 | 文山壮族苗族自治州: 'Wenshan', 106 | 曲靖市: 'Qujing', 107 | 楚雄彝族自治州: 'Chuxiong', 108 | 大理白族自治州: 'Dali', 109 | 临沧市: 'Lincang', 110 | 迪庆藏族自治州: 'Deqen', 111 | 昭通市: 'Zhaotong', 112 | 昆明市: 'Kunming', 113 | 丽江市: 'Lijiang', 114 | 西双版纳傣族自治州: 'Xishuangbanna', 115 | 保山市: 'Baoshan', 116 | 玉溪市: 'Yuxi', 117 | 怒江傈僳族自治州: 'Nujiang', 118 | 德宏傣族景颇族自治州: 'Dehong', 119 | 百色市: 'Baise', 120 | 河池市: 'Hechi', 121 | 桂林市: 'Guilin', 122 | 南宁市: 'Nanning', 123 | 柳州市: 'Liuzhou', 124 | 崇左市: 'Chongzuo', 125 | 来宾市: 'Laibin', 126 | 玉林市: 'Yulin', 127 | 梧州市: 'Wuzhou', 128 | 贺州市: 'Hezhou', 129 | 钦州市: 'Qinzhou', 130 | 贵港市: 'Guigang', 131 | 防城港市: 'Fangchenggang', 132 | 北海市: 'Beihai', 133 | 怀化市: 'Huaihua', 134 | 永州市: 'Yongzhou', 135 | 邵阳市: 'Shaoyang', 136 | 郴州市: 'Chenzhou', 137 | 常德市: 'Changde', 138 | 湘西土家族苗族自治州: 'Xiangxi', 139 | 衡阳市: 'Hengyang', 140 | 岳阳市: 'Yueyang', 141 | 益阳市: 'Yiyang', 142 | 长沙市: 'Changsha', 143 | 株洲市: 'Zhuzhou', 144 | 张家界市: 'Zhangjiajie', 145 | 娄底市: 'Loudi', 146 | 湘潭市: 'Xiangtan', 147 | 榆林市: 'Yulin', 148 | 延安市: 'Yanan', 149 | 汉中市: 'Hanzhong', 150 | 安康市: 'Ankang', 151 | 商洛市: 'Shangluo', 152 | 宝鸡市: 'Baoji', 153 | 渭南市: 'Weinan', 154 | 咸阳市: 'Xianyang', 155 | 西安市: 'Xi An', 156 | 铜川市: 'Tongchuan', 157 | 清远市: 'Qingyuan', 158 | 韶关市: 'Shaoguan', 159 | 湛江市: 'Zhanjiang', 160 | 梅州市: 'Meizhou', 161 | 河源市: 'Heyuan', 162 | 肇庆市: 'Zhaoqing', 163 | 惠州市: 'Huizhou', 164 | 茂名市: 'Maoming', 165 | 江门市: 'Jiangmen', 166 | 阳江市: 'Yangjiang', 167 | 云浮市: 'Yunfu', 168 | 广州市: 'Guangzhou', 169 | 汕尾市: 'Shanwei', 170 | 揭阳市: 'Jieyang', 171 | 珠海市: 'Zhuhai', 172 | 佛山市: 'Foshan', 173 | 潮州市: 'Chaozhou', 174 | 汕头市: 'Shantou', 175 | 深圳市: 'Shenzhen', 176 | 东莞市: 'Dongguan', 177 | 中山市: 'Zhongshan', 178 | 延边朝鲜族自治州: 'Yanbian', 179 | 吉林市: 'Jilin', 180 | 白城市: 'Baicheng', 181 | 松原市: 'Songyuan', 182 | 长春市: 'Changchun', 183 | 白山市: 'Baishan', 184 | 通化市: 'Tonghua', 185 | 四平市: 'Siping', 186 | 辽源市: 'Liaoyuan', 187 | 承德市: 'Chengde', 188 | 张家口市: 'Zhangjiakou', 189 | 保定市: 'Baoding', 190 | 唐山市: 'Tangshan', 191 | 沧州市: 'Cangzhou', 192 | 石家庄市: 'Shijiazhuang', 193 | 邢台市: 'Xingtai', 194 | 邯郸市: 'Handan', 195 | 秦皇岛市: 'Qinhuangdao', 196 | 衡水市: 'Hengshui', 197 | 廊坊市: 'Langfang', 198 | 恩施土家族苗族自治州: 'Enshi', 199 | 十堰市: 'Shiyan', 200 | 宜昌市: 'Yichang', 201 | 襄樊市: 'Xiangfan', 202 | 黄冈市: 'Huanggang', 203 | 荆州市: 'Jingzhou', 204 | 荆门市: 'Jingmen', 205 | 咸宁市: 'Xianning', 206 | 随州市: 'Suizhou', 207 | 孝感市: 'Xiaogan', 208 | 武汉市: 'Wuhan', 209 | 黄石市: 'Huangshi', 210 | 鄂州市: 'Ezhou', 211 | 遵义市: 'Zunyi', 212 | 黔东南苗族侗族自治州: 'Qiandongnan', 213 | 毕节市: 'Bijie', 214 | 黔南布依族苗族自治州: 'Qiannan', 215 | 铜仁市: 'Tongren', 216 | 黔西南布依族苗族自治州: 'Qianxinan', 217 | 六盘水市: 'Liupanshui', 218 | 安顺市: 'Anshun', 219 | 贵阳市: 'Guiyang', 220 | 烟台市: 'Yantai', 221 | 临沂市: 'Linyi', 222 | 潍坊市: 'Weifang', 223 | 青岛市: 'Qingdao', 224 | 菏泽市: 'Heze', 225 | 济宁市: 'Jining', 226 | 德州市: 'Dezhou', 227 | 滨州市: 'Binzhou', 228 | 聊城市: 'Liaocheng', 229 | 东营市: 'Dongying', 230 | 济南市: 'Jinan', 231 | 泰安市: 'Taian', 232 | 威海市: 'Weihai', 233 | 日照市: 'Rizhao', 234 | 淄博市: 'Zibo', 235 | 枣庄市: 'Zaozhuang', 236 | 莱芜市: 'Laiwu', 237 | 赣州市: 'Ganzhou', 238 | 吉安市: 'Ji An', 239 | 上饶市: 'Shangrao', 240 | 九江市: 'Jiujiang', 241 | 抚州市: 'Fuzhou', 242 | 宜春市: 'Yichun', 243 | 南昌市: 'Nanchang', 244 | 景德镇市: 'Jingdezhen', 245 | 萍乡市: 'Pingxiang', 246 | 鹰潭市: 'Yingtan', 247 | 新余市: 'Xinyu', 248 | 南阳市: 'Nanyang', 249 | 信阳市: 'Xinyang', 250 | 洛阳市: 'Luoyang', 251 | 驻马店市: 'Zhumadian', 252 | 周口市: 'Zhoukou', 253 | 商丘市: 'Shangqiu', 254 | 三门峡市: 'Sanmenxia', 255 | 新乡市: 'Xinxiang', 256 | 平顶山市: 'Pingdingshan', 257 | 郑州市: 'Zhengzhou', 258 | 安阳市: 'Anyang', 259 | 开封市: 'Kaifeng', 260 | 焦作市: 'Jiaozuo', 261 | 许昌市: 'Xuchang', 262 | 濮阳市: 'Puyang', 263 | 漯河市: 'Luohe', 264 | 鹤壁市: 'Hebi', 265 | 大连市: 'Dalian', 266 | 朝阳市: 'Chaoyang', 267 | 丹东市: 'Dandong', 268 | 铁岭市: 'Tieling', 269 | 沈阳市: 'Shenyang', 270 | 抚顺市: 'Fushun', 271 | 葫芦岛市: 'Huludao', 272 | 阜新市: 'Fuxin', 273 | 锦州市: 'Jinzhou', 274 | 鞍山市: 'Anshan', 275 | 本溪市: 'Benxi', 276 | 营口市: 'Yingkou', 277 | 辽阳市: 'Liaoyang', 278 | 盘锦市: 'Panjin', 279 | 忻州市: 'Xinzhou', 280 | 吕梁市: 'Luliang', 281 | 临汾市: 'Linfen', 282 | 晋中市: 'Jinzhong', 283 | 运城市: 'Yuncheng', 284 | 大同市: 'Datong', 285 | 长治市: 'Changzhi', 286 | 朔州市: 'Shuozhou', 287 | 晋城市: 'Jincheng', 288 | 太原市: 'Taiyuan', 289 | 阳泉市: 'Yangquan', 290 | 六安市: 'Lu An', 291 | 安庆市: 'Anqing', 292 | 滁州市: 'Chuzhou', 293 | 宣城市: 'Xuancheng', 294 | 阜阳市: 'Fuyang', 295 | 宿州市: 'Suzou', 296 | 黄山市: 'Huangshan', 297 | 巢湖市: 'Chaohu', 298 | 亳州市: 'Bozhou', 299 | 池州市: 'Chizhou', 300 | 合肥市: 'Hefei', 301 | 蚌埠市: 'Bengbu', 302 | 芜湖市: 'Wuhu', 303 | 淮北市: 'Huaibei', 304 | 淮南市: 'Huainan', 305 | 马鞍山市: "Ma'anshan", 306 | 铜陵市: 'Tongling', 307 | 南平市: 'Nanping', 308 | 三明市: 'Sanming', 309 | 龙岩市: 'Longyan', 310 | 宁德市: 'Ningde', 311 | 福州市: 'Fuzhou', 312 | 漳州市: 'Zhangzhou', 313 | 泉州市: 'Quanzhou', 314 | 莆田市: 'Putian', 315 | 厦门市: 'Xiamen', 316 | 丽水市: 'Lishui', 317 | 杭州市: 'Hangzhou', 318 | 温州市: 'Wenzhou', 319 | 宁波市: 'Ningbo', 320 | 舟山市: 'Zhoushan', 321 | 台州市: 'Taizou', 322 | 金华市: 'Jinhua', 323 | 衢州市: 'Quzhou', 324 | 绍兴市: 'Shaoxing', 325 | 嘉兴市: 'Jiaxing', 326 | 湖州市: 'Huzhou', 327 | 盐城市: 'Yancheng', 328 | 徐州市: 'Xuzhou', 329 | 南通市: 'Nantong', 330 | 淮安市: 'Huaian', 331 | 苏州市: 'Suzhou', 332 | 宿迁市: 'Suqian', 333 | 连云港市: 'Lianyungang', 334 | 扬州市: 'Yangzhou', 335 | 南京市: 'Nanjing', 336 | 泰州市: 'Taizhou', 337 | 无锡市: 'Wuxi', 338 | 常州市: 'Changzhou', 339 | 镇江市: 'Zhenjiang', 340 | 吴忠市: 'Wuzhong', 341 | 中卫市: 'Zhongwei', 342 | 固原市: 'Guyuan', 343 | 银川市: 'Yinchuan', 344 | 石嘴山市: 'Shizuishan', 345 | 三亚市: 'Sanya', 346 | 海口市: 'Haikou', 347 | 神农架林区: 'Shennongjia', 348 | 天门市: 'Tianmen', 349 | 仙桃市: 'Xiantao', 350 | 潜江市: 'Qianjiang', 351 | 儋州市: 'Danzhou', 352 | 文昌市: 'Wenchang', 353 | 乐东黎族自治县: 'Ledong', 354 | 琼中黎族苗族自治县: 'Qiongzhong', 355 | 东方市: 'Dongfang', 356 | 阿拉尔市: 'Aral', 357 | 图木舒克市: 'Tumxuk', 358 | 五家渠市: 'Wujiaqu', 359 | 石河子市: 'Shihezi', 360 | 万宁市: 'Wanning', 361 | 澄迈县: 'Chengmai', 362 | 白沙黎族自治县: 'Baisha', 363 | 琼海市: 'Qionghai', 364 | 昌江黎族自治县: 'Changjiang', 365 | 临高县: 'Lingao', 366 | 陵水黎族自治县: 'Lingshui', 367 | 屯昌县: 'Tunchang', 368 | 定安县: "Ding'an", 369 | 保亭黎族苗族自治县: 'Baoting', 370 | 五指山市: 'Wuzhishan', 371 | 省直辖县级行政区划: 'Directly under the county-level administrative division', 372 | 自治区直辖县级行政区划: 'Autonomous regions directly under the county-level administrative', 373 | 那曲地区: 'Nagqu', 374 | }; 375 | -------------------------------------------------------------------------------- /packages/charts/docs/data/locales/en-US/china-provinces.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable quotes */ 2 | export default { 3 | 北京: 'Beijing', 4 | 天津: 'Tianjin', 5 | 重庆: 'Chongqing', 6 | 上海: 'Shanghai', 7 | 河北: 'Hebei', 8 | 河南: 'Henan', 9 | 云南: 'Yunnan', 10 | 辽宁: 'Liaoning', 11 | 黑龙江: 'Heilongjiang', 12 | 湖南: 'Hunan', 13 | 安徽: 'Anhui', 14 | 山东: 'Shandong', 15 | 江苏: 'Jiangsu', 16 | 浙江: 'Zhejiang', 17 | 江西: 'Jiangxi', 18 | 湖北: 'Hubei', 19 | 甘肃: 'Gansu', 20 | 山西: 'Shanxi', 21 | 陕西: 'Shaanxi', 22 | 吉林: 'Jilin', 23 | 福建: 'Fujian', 24 | 贵州: 'Guizhou', 25 | 广东: 'Guangdong', 26 | 青海: 'Qinghai', 27 | 四川: 'Sichuan', 28 | 海南: 'Hainan', 29 | 台湾: 'Taiwan', 30 | 内蒙古: 'Inner Mongolia', 31 | 广西: 'Guangxi', 32 | 宁夏: 'Ningxia', 33 | 新疆: 'Xinjiang', 34 | 西藏: 'Tibet', 35 | 香港: 'Hong Kong', 36 | 澳门: 'Macao', 37 | // ECharts 的 nameMap 南海诸岛有 bug 38 | // 南海诸岛: 'South China Sea Islands' 39 | }; 40 | -------------------------------------------------------------------------------- /packages/charts/docs/data/locales/zh-CN/world-countries.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable quotes */ 2 | export default { 3 | Afghanistan: '阿富汗', 4 | Angola: '安哥拉', 5 | Albania: '阿尔巴尼亚', 6 | 'United Arab Emirates': '阿联酋', 7 | Argentina: '阿根廷', 8 | Armenia: '亚美尼亚', 9 | 'French Southern and Antarctic Lands': '法属南部领地', 10 | Australia: '澳大利亚', 11 | Austria: '奥地利', 12 | Azerbaijan: '阿塞拜疆', 13 | Burundi: '布隆迪', 14 | Belgium: '比利时', 15 | Benin: '贝宁', 16 | 'Burkina Faso': '布基纳法索', 17 | Bangladesh: '孟加拉', 18 | Bulgaria: '保加利亚', 19 | Bahamas: '巴哈马', 20 | 'Bosnia and Herzegovina': '波黑', 21 | Belarus: '白俄罗斯', 22 | Belize: '伯利兹', 23 | Bermuda: '百慕大', 24 | Bolivia: '玻利维亚', 25 | Brazil: '巴西', 26 | Brunei: '文莱', 27 | Bhutan: '不丹', 28 | Botswana: '博茨瓦纳', 29 | 'Central African Rep.': '中非共和国', 30 | Canada: '加拿大', 31 | Switzerland: '瑞士', 32 | Chile: '智利', 33 | China: '中国', 34 | 'Ivory Coast': '象牙海岸', 35 | Cameroon: '喀麦隆', 36 | 'Dem. Rep. Congo': '刚果(金)', 37 | 'Republic of the Congo': '刚果(布)', 38 | Colombia: '哥伦比亚', 39 | 'Costa Rica': '哥斯达黎加', 40 | Cuba: '古巴', 41 | 'Northern Cyprus': '北塞浦路斯', 42 | Cyprus: '塞浦路斯', 43 | 'Czech Republic': '捷克', 44 | Germany: '德国', 45 | Djibouti: '吉布提', 46 | Denmark: '丹麦', 47 | 'Dominican Republic': '多米尼加', 48 | Algeria: '阿尔及利亚', 49 | Ecuador: '厄瓜多尔', 50 | Egypt: '埃及', 51 | Eritrea: '厄立特里亚', 52 | Spain: '西班牙', 53 | Estonia: '爱沙尼亚', 54 | Ethiopia: '埃塞俄比亚', 55 | Finland: '芬兰', 56 | Fiji: '斐济群岛', 57 | 'Falkland Islands': '福克兰群岛', 58 | France: '法国', 59 | Gabon: '加蓬', 60 | 'United Kingdom': '英国', 61 | Georgia: '格鲁吉亚', 62 | Ghana: '加纳', 63 | Guinea: '几内亚', 64 | Gambia: '冈比亚', 65 | 'Guinea Bissau': '几内亚比绍', 66 | 'Equatorial Guinea': '赤道几内亚', 67 | Greece: '希腊', 68 | Greenland: '格陵兰', 69 | Guatemala: '危地马拉', 70 | 'French Guiana': '法属圭亚那', 71 | Guyana: '圭亚那', 72 | Honduras: '洪都拉斯', 73 | Croatia: '克罗地亚', 74 | Haiti: '海地', 75 | Hungary: '匈牙利', 76 | Indonesia: '印尼', 77 | India: '印度', 78 | Ireland: '爱尔兰', 79 | Iran: '伊朗', 80 | Iraq: '伊拉克', 81 | Iceland: '冰岛', 82 | Israel: '以色列', 83 | Italy: '意大利', 84 | Jamaica: '牙买加', 85 | Jordan: '约旦', 86 | Japan: '日本', 87 | Kazakhstan: '哈萨克斯坦', 88 | Kenya: '肯尼亚', 89 | Kyrgyzstan: '吉尔吉斯斯坦', 90 | Cambodia: '柬埔寨', 91 | 'South Korea': '韩国', 92 | Kosovo: '科索沃', 93 | Kuwait: '科威特', 94 | Laos: '老挝', 95 | Lebanon: '黎巴嫩', 96 | Liberia: '利比里亚', 97 | Libya: '利比亚', 98 | 'Sri Lanka': '斯里兰卡', 99 | Lesotho: '莱索托', 100 | Lithuania: '立陶宛', 101 | Luxembourg: '卢森堡', 102 | Latvia: '拉脱维亚', 103 | Morocco: '摩洛哥', 104 | Moldova: '摩尔多瓦', 105 | Madagascar: '马达加斯加', 106 | Mexico: '墨西哥', 107 | Macedonia: '马其顿', 108 | Mali: '马里', 109 | Myanmar: '缅甸', 110 | Montenegro: '黑山', 111 | Mongolia: '蒙古', 112 | Mozambique: '莫桑比克', 113 | Mauritania: '毛里塔尼亚', 114 | Malawi: '马拉维', 115 | Malaysia: '马来西亚', 116 | Namibia: '纳米比亚', 117 | 'New Caledonia': '新喀里多尼亚', 118 | Niger: '尼日尔', 119 | Nigeria: '尼日利亚', 120 | Nicaragua: '尼加拉瓜', 121 | Netherlands: '荷兰', 122 | Norway: '挪威', 123 | Nepal: '尼泊尔', 124 | 'New Zealand': '新西兰', 125 | Oman: '阿曼', 126 | Pakistan: '巴基斯坦', 127 | Panama: '巴拿马', 128 | Peru: '秘鲁', 129 | Philippines: '菲律宾', 130 | 'Papua New Guinea': '巴布亚新几内亚', 131 | Poland: '波兰', 132 | 'Puerto Rico': '波多黎各', 133 | 'North Korea': '朝鲜', 134 | Portugal: '葡萄牙', 135 | Paraguay: '巴拉圭', 136 | Qatar: '卡塔尔', 137 | Romania: '罗马尼亚', 138 | Russia: '俄罗斯', 139 | Rwanda: '卢旺达', 140 | 'W. Sahara': '西撒哈拉', 141 | 'Saudi Arabia': '沙特阿拉伯', 142 | Sudan: '苏丹', 143 | 'S. Sudan': '南苏丹', 144 | Senegal: '塞内加尔', 145 | 'Solomon Islands': '所罗门群岛', 146 | 'Sierra Leone': '塞拉利昂', 147 | 'El Salvador': '萨尔瓦多', 148 | Somaliland: '索马里兰', 149 | Somalia: '索马里', 150 | 'Republic of Serbia': '塞尔维亚', 151 | Suriname: '苏里南', 152 | Slovakia: '斯洛伐克', 153 | Slovenia: '斯洛文尼亚', 154 | Sweden: '瑞典', 155 | Swaziland: '斯威士兰', 156 | Syria: '叙利亚', 157 | Chad: '乍得', 158 | Togo: '多哥', 159 | Thailand: '泰国', 160 | Tajikistan: '塔吉克斯坦', 161 | Turkmenistan: '土库曼斯坦', 162 | 'East Timor': '东帝汶', 163 | 'Trinidad and Tobago': '特立尼达和多巴哥', 164 | Tunisia: '突尼斯', 165 | Turkey: '土耳其', 166 | Tanzania: '坦桑尼亚', 167 | Uganda: '乌干达', 168 | Ukraine: '乌克兰', 169 | Uruguay: '乌拉圭', 170 | 'United States': '美国', 171 | Uzbekistan: '乌兹别克斯坦', 172 | Venezuela: '委内瑞拉', 173 | Vietnam: '越南', 174 | Vanuatu: '瓦努阿图', 175 | 'West Bank': '西岸', 176 | Yemen: '也门', 177 | 'South Africa': '南非', 178 | Zambia: '赞比亚', 179 | Zimbabwe: '津巴布韦', 180 | Anguilla: '安圭拉', 181 | Tokelau: '托克劳', 182 | 'South Georgia and The South Sandwich Islands': '南乔治亚岛和南桑威奇群岛', 183 | 'Caribbean Netherlands': '荷兰加勒比区', 184 | 'Cayman Islands': '开曼群岛', 185 | Malta: '马耳他', 186 | 'St. Lucia': '圣卢西亚', 187 | Martinique: '马提尼克', 188 | Niue: '纽埃', 189 | 'Turks and Caicos Islands': '特克斯和凯科斯群岛', 190 | Tuvalu: '图瓦卢', 191 | Grenada: '格林纳达', 192 | 'Bailiwick of Guernsey': '根西岛', 193 | Montserrat: '蒙塞拉特岛', 194 | Seychelles: '塞舌尔', 195 | Singapore: '新加坡', 196 | 'Territory of the Wallis and Futuna Islands': '瓦利斯和富图纳', 197 | 'British Indian Ocean Territory': '英属印度洋领地', 198 | "Cote d'Ivoire": '科特迪瓦', 199 | 'Cook Islands': '库克群岛', 200 | Mauritius: '毛里求斯', 201 | 'United States Minor Outlying Islands': '美国本土外小岛屿', 202 | Vatican: '梵蒂冈', 203 | 'Isle of Man': '马恩岛', 204 | 'Christmas Island': '圣诞岛', 205 | Palestine: '巴勒斯坦', 206 | 'Sao Tome and Principe': '圣多美和普林西比', 207 | Guam: '关岛', 208 | 'San Marino': '圣马力诺', 209 | 'Landskapet Aland': '奥兰群岛', 210 | 'American Samoa': '美属萨摩亚', 211 | 'Collectivity of Saint Martin': '法属圣马丁', 212 | 'Faroe Islands': '法罗群岛', 213 | Maldives: '马尔代夫', 214 | Reunion: '留尼汪', 215 | Monaco: '摩纳哥', 216 | Antarctica: '南极洲', 217 | 'Svalbard and Jan Mayen': '斯瓦尔巴群岛和扬马延岛', 218 | 'Bouvet Island': '布韦岛', 219 | 'St. Kitts and Nevis': '圣基茨和尼维斯', 220 | 'Marshall Islands': '马绍尔群岛', 221 | Global: '全球', 222 | Samoa: '萨摩亚', 223 | 'Cocos (Keeling) Islands': '科科斯群岛', 224 | Gibraltar: '直布罗陀', 225 | Mayotte: '马约特', 226 | Guadeloupe: '瓜德罗普', 227 | Barbados: '巴巴多斯', 228 | 'St. Pierre and Miquelon': '圣皮埃尔和密克隆', 229 | 'Saint Vincent and the Grenadines': '圣文森特和格林纳丁斯', 230 | 'French Polynesia': '法属波利尼西亚', 231 | Andorra: '安道尔', 232 | Dominica: '多米尼克', 233 | Bahrain: '巴林', 234 | 'Antigua and Barbuda': '安提瓜和巴布达', 235 | Palau: '帕劳', 236 | 'Bailiwick of Jersey': '泽西岛', 237 | Aruba: '阿鲁巴', 238 | Tonga: '汤加', 239 | 'U.S. Virgin Islands': '美属维尔京群岛', 240 | Comoros: '科摩罗', 241 | 'Commonwealth of the Northern Mariana Islands': '北马里亚纳群岛', 242 | 'Cape Verde': '佛得角', 243 | Kiribati: '基里巴斯', 244 | 'Virgin Islands (British)': '英属维尔京群岛', 245 | Liechtenstein: '列支敦士登', 246 | 'Federated States of Micronesi': '密克罗尼西亚联邦', 247 | 'St. Helena': '圣赫勒拿', 248 | Nauru: '瑙鲁', 249 | 'Norfolk Island': '诺福克岛', 250 | Curacao: '库拉索', 251 | 'Sint Maarten': '荷属圣马丁', 252 | 'St. Barthelemy': '圣巴泰勒米岛', 253 | }; 254 | -------------------------------------------------------------------------------- /packages/charts/docs/data/maps/README.md: -------------------------------------------------------------------------------- 1 | # DISCLAIMER 2 | 3 | The map data in this `docs/data/maps` folder are copied from `echarts@4` package. 4 | -------------------------------------------------------------------------------- /packages/charts/docs/data/maps/china-contour.json: -------------------------------------------------------------------------------- 1 | {"type":"FeatureCollection","features":[{"id":"100000","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@š¦ŜiÀºƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅ó­@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ AɞÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĒĞȠzÐŘΰH¨ȔBĠ "],["@@ƛĴÕƊÉɼģºðʀI̠ÔĚäœθؾNJŨxĚĮǂƺòƌ‚ĪŐĮXŦţƸZûЋƕƑ’ʳÛDžƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ"],["@@Óɖ± dƊ½ǒÂň×äı–§ĤƩ™¶hlçxĬŸĄŞkâ’ÌwøàIJaĞ‚fƠ¥Ž„Ŕdž˜®UɎÖ¢aƆúŪtŠųƠjd•ƺŠƺÅìnŽŢ¯äɝĦ]èpĄ¦´LƞĬŠ´ƤǬ˼Ēɸ¤rºǼìĴPðŀbþ¹ļD¢¹œ\\ĜÑ̔ùўÊ‰ȮŒǪűŽÀêZǚŐ¤qȂ\\`ºłĤ\\ºs|zºÿŐãѦvĪĺĺ†ĈłÈ͚FÞºĠUƢ¾ªì°`öøu®Ì¼ãÐUÞ˶¬æɒlʐߨvWʚ”ÖÕÁÜÅŵ­_«”E”ÍɪëÏ÷ÅyXo͂ĝĂÛÎf`Þ…¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘETėº¯ɀáMĺŝOéȇ¿ÖğǤǷŔ²å]­Ĥĝ‰œ¦EP}ûƥé¿İƷTėƫœŕƅ™ƱB»Đ±‚řü›]µȺrĦáŖuҞª«IJ‡πdƺÏɌ]͚œĐ™ǂZɔ¹ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥Ǖǚk˦ӷxūД̵nơԆ|DŽŽࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãɜRצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´ԜÃƲÀɠmǐnȺĸƠ´ǠNˠŜ‚¶ƌĆĘźʆȬμƒĞGȖƴƀj`ĢçĶȅŚē̃ĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDƞŧǘÛۨĝȘIJžªǬ”¾äʀƪ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊ˰ȎŜHĦðDĝŒ|ø˂˜ƮÐ¬ҌqjĔ²Äw°dždĞéĸdîàŎjɒĚŌ‡ŜWÈ|Ŗ‡¶îÎFC•ĊZĀēƄNĤ¶ŠłKĊOj“Ě”j´ĜYp˜{¦„ˆSĚÍ\\Tš×ªV–÷Šų¬K°ȧǵÂcḷ̌ĚǣȄɧ\\ĵœŇ‹ȣFέ̿ʏƶɷØ̫»ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔDzlжøZh¤Ɛ E ĈDJ˜ì¸̚¸ƎGú´Pž¬WÄì–HsIJ¾wLVnƽCw`h`¥V”„¦U¤¸}€¾Ô[~âxh¢ªHÆÂr–iĐɘǜhÀoRzNy˜ÀDs~€bcfÌ`L–¾n‹|¾T‚°c¨È¢a‚ÈÄ[|òDȎŸÖdH„Ʈ–Àì~Ǝ†â•¦^¢ķ¶e”ÐÚEꖄɡČÅyġLû™ŇV®ŠÄ‰Ðź~ϰƂŤǒȦÒŬÂezÂvǴZ„{ĘFǜĴAΜĐȄEÔ¤ØQĄ–Ą»ΈZǺ¨ìSŊÄƸwŠn¼–c]—ܬì¯DŽ]ȘŏńzƺŷɄeeOĨS’Œfm Ɋ’̎ēz©þ†ÐÙÊmgŸÇsJ¥ƔˆŊśÎÔsÁtÃßGo—À­ xňË_½ä@êíuáĠ[ġ¥g“ɊדûÏWXáǠDZÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃQíÜçÛġԏsĕ¬—Dz¡SíċġHµ ¡EŃļƒrĉŘóƢFƺ«øxÊk†”ƈdƬÌr|©ÛńRŀƒøďŊœŀ›ˆàŀU²ŕƀB‚Q£Ď}L¹Îk@©ĈuǰųǨ”Ú§ƈnTËÇéƟÊcfčŤ^gēĊĕƯǏx³ǔķÐċJā‚wİ_ĸ˜Ȁ^ôWr­°oú¬Ɏ‘~”ȰCĐ´Ƕ£’fNÎèâ_ÐŮeʆNJǘuȔ\\¤ÒĨA¢Ê͠æÔ ŬGƠ”ƦYê‹ŊàƆXvkmŸͥœ@čŅĻA“¶çÎqC½Ĉ»NŸăëK™ďÍQ“Ʌ›řęgßÔÇOÝáWáħ£˯ā¡ÑķĎÛ寰WKɱ_d_}}vyŸõu¬ïÏҽ@gÏ¿rýб…Cd‰µ—°MFYxw¿CG£ǧ«»ó¡Ɵš¿BÇƻğëšܭNJĭôµ}‰čÓpg±˜ƒǫŋRwŕnéÑƕfSŸŋ‹®ÍšD Ûǖ֍Ÿ]gr¡µŷzįm³~S«“„›þeo³l™•{iē¥yZ÷īŖõġMRÇģZ“mÃ|¡™ģTɟij“Â`À–çm‰‘FK¥ÚíÁbXš³ÌQґHof{‰]e€pt·GŋĜTNJŋB…h–¬ƩDoˆ±enq©G`™wGçǑ‚“K‰‹F‚“›uNĝw‡őXtW·Ýďæßa}xV•—XR‰ãQ`­©GŒM»­”ďϝd‡©ÑW_ÏǷr¡…é\\ƒɹ~ɍuØ©Bš¤ÝĤ½¢Å_Á¿•LŅñuT\\rÅIs®y}’ywdS™DZtCmûvašʋJr€Ư‚⦳P‡rbbÍzš€wBG’ĭ€T†Ák‘»ƒlY­ċ²z“Ç£—^§»d¯íŻŽ£ćGŵDžƍÓ]í“M^o•£Ã]ªUóo½~ŕ‘|ŋݘ¥ċh“¹·CÉ­Dřlg‡ȵë[‘’}ģS}xƃği©ĝ‡ɝǡF꼵áƣ©‚Hžĕoƫ€Ňqƒr³Ãg[„šÃS–ő_†±ÅFC¥Pq{‚ñg—¿įX…•ƝıĉNj•ûěʼn³F‘¦oĵ—hŸÕP{¯~TÍl¸ÓßYÏàs{ÃVU™™eĎwk±ʼnVÓ½ŽJūĉ»Jm°fϑdF~ˆ€ĀeĖ€O˜² Ĉ‰żĀiÂd^~ăÔHˆ¦\\§|ĄVez¤NP ǹӗR™ÆƇP[¦´Âghwm}ÐШźhI|žVVŽ—Ž|p[¦À¶èNä¶ÒCÀ¢^h—PfvƾĪ×òúNZÞÒKxpw|ÊEZŽI¨®œİFÜçmĩ‚WĪñt‘ÞʼnËÝ^³uL‚±|Əlĉ¥čn§ßÅc‘˜B× CNƒǟ‹_ñŧı¯Y]ăٟ™Ľѷť‹³ÃAR‹‡ZRlʑýSëÍDěïÿȧ¢ÙġƒěŗŷęŸUªhJˆƁ™ƅn³gF‹³HàŋÅÃƉÀKšť`ċŮÁõYėé÷`ٚ_Ïǵ—R§òoEÅąLœŐœƜVµąłíļĐ·ũ̈«ªdÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿäćú y±¨Mf~C¿`€à_ŒÿƌfQnð³ƬˆŲŎ¥ĠʦĘĒØ‰¼Â†±ŴPè¸ŔLƔÜƺ_T‘üÃĤBBċȉöA´fa„˜M¨{«Múīô‰Ö°ʊkŲÆM|²@¤u•ƒ¤Û´Œä«̰\\„}ēƒ‹ÅM•¼Ã­]NągoõľH‰yGă{{çrnÓE‰‹ƕZGª¹Fj¢ïW…uøC̍ƃhÛ­–Ň\\bÅxì²ƝýN‰īCȽĿǃšŖÕy\\‡¹kx‡Ã£Č×G¿Ï¤ÁçFQ¡„KtŵΥëÚź—Љ«ėn½ĉŀ—›Á¼zK›¶†G•­Y§Ëƒ@–´śÇµƕñžx———Z¯u™Œ…Ï•˜ï{éƵP—™_K«™pÍÁwƏčaE›U”£uݘāɌŁFŴu»¹İ×ȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±hǥ®jű¢KOķÅ}`åÂK­_Юƫ²ʯÊ^H{ǸÃĆēĤȍzȥݵċF͓ŸI©Õ͈ǫȌȥ¦ŋEӏ“†ıŪěřÀåżȟLƏ—ŽąđGǛģLjƧĎOłčȶʋÀBŖÕªˆŠÁŐTőŕåqûõi¨hÜ·ƒñt»¹ýv_[«²Kƒ{L¯‰SªƒGѵ¸•gÑpY´«•ęœƘʑcoċ\\œ­gěŧ«Āý¶ŧ·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZ~﵉fzʼnfåÂȝǷÕĕÊĉ{ğč±uƁí]Í»ęX\\­•Ip™¡éĥZE‹ãoP…þy—¸k³—†¡ƽŸ¿å³BRضˆœWlâþäą`“]aģc— ĹGµ¶H™åՌ‰¾xĨ‡ôȉðX«½đCIŇOK³Á‰Äţ¬OAwã»aLʼn‡ËĥW[“ÂGI—ÂNrį~IМ‘êĘÎG§Ė¥Ý™F{ WK}ùaH‘āÖ{OoužHEÅǍqĬuë±KEò£‰UplÀ÷tMāe£bYÂý¡a±Öcp©®^ö±q…ÇGjųªKy¬ŏ–®¤ÉEŸ–ĀåA¬ˆV{Xģ‰Đƒpě…¼³Ăp·¤ƒīyÚ¡ŅLĻŗž§qlŸÀh¬µ»åÇGnùčÙmÆß–ėu›ĕeûҍiÁŧSW¥˜QŠûŗ½ùěYÓ±]ÓđīkWó«íěCŸŇͱ™‘čvĭõĉ‚ę÷N¹³ĉoTĵËçŁYلǝŕ¹tȏģ·Ĕĭ|đėÊK™½R‘ē ó]™ĀęAx–ŸNk©|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™áÎÁąÏŸHcòßÎſ¿Çdğ·ùT×Çūʄ¡XgWÀLJƟψOj YÇ÷Sğ³kzőȝğ§õ¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰Ƈ׫BhlmtÃPµy‹ÓɉUīí}†€GBȅ‰ŹãĻFŷŽǩoo¿ē‹±ß}ŽwƋtƺ—CőØEîǻīƓʑã͘ƍ“DĈ±ÌŒÜӔĨ£LóɢVȞĆĖMĸĤfˆÜǗjđĆ»ýͥãğ¶ĞØO¤Ǜn³Žő}‹¦…·z€YŠwa™–šőűMę§ZĨ훘Û]é’ÛUćİȹ¯…dƒy¹TcÂĕ½A´µê÷wĻþÙ`K€¦˜…¢ÍeœĥR¡ˆã…‚Ĉu¼dl‰t‚†U¶¶ď\\zœ}ưŬ–{ÚfKš¶Ð_„ÂÒ¿C©Ö•TmuŸ¼ãl‰›ŇÕVåĤĵfÝYYįk‘ÒīØſNQĠ³r³øÓrŸÖͳgÍſGįÅ_—±he¡ÅM²Ɠ綾ßīZgmk„ǭƁć¦UĔťƒ×ëǟ…e˭ʔħǛāĘPªij¶‘Ņăw§n‰ď£S»şŒÍļɉŀ‰}ÛÞ»å£_ˆŸıęÏZ—÷`…[„ùx½}ÑRH‘YėĺďsÍn‘™é½Ya¤Ïm¬ĝg•ĂsA•ØÅwď‚õ¤q}—«Dx¿}UũlŸê™@•HÅ­F‰¨ÇoJ´Ónȯ×âpÒŌ“Ø Tˆêa²ËX€€c̋lLìģËŁkŻƑŷÉăP¹æƧÝ¡¦}•veèÆ´UvÅ~§‡½˜“Ġ²Ŵwæč\\Dƒ}O÷š£[ŽăŒá[™‚į‰ŷvŸœRsdĒƄwžŎĒo~t¾ÍŶÒtD¦Ú„iôö‰€z«Ųƭ¸Û±¯€ÿm·zR¦Ɵ`ªŊÃh¢rOԍ´£Ym¼èêf¯ŪĽn„†AĦw\\ưĆ ¦g–ʉË£¢ι‰ǫßK‘ÙIįóVesb‘aĕ ǠƺpªqŒ‚ďŒE˜®tŸôřk˜ȌwêżĔÂe‚nËÂQƞ´’¼ŲƝÎô¶R„ä’Q^Øu¬°š_Èôc´¹ò¨P΢hlϦ´Ħ“¬oêDŽŲÚr^¯°’^º{ªBHŒ²Ö¤ɦ§Țv€qĸ„ ­viļ€ndĜ­ĆfŒ“xÝgyށqóžSᝑ³X_ĞçêtrmÚ§z„¦c¦¥jnŞi˜¯´ÓH@ÂċĂჷÌ_þ·–¹_wzË£Z­¹|ŕWM‰“|O¥ÃWTÕ­ùÔQ†¥‡¥Rã»Ge†ŸeƃīQ•}J[ғK…¬Ə|o’ėjġĠÑN¡ð¯EBčnkòəėªƒ²œm˽ŏġǝʅįĭạ̃ūȹ]ΓͧŹəăЕ·ƭˆęgſ¶ҍć`ĘąŌJޚä¤rÅň¥ÖƝ^ęuůÞiĊÄÀ\\Æs¦ÓRäšřÌkÄŷ¶½÷ùCMÝۛĥ°G¬ĩ`£Øą‚ğ¯ß”§aëbéüÑOčœk£ÍI ïCċÀÕÕĻSŧʼnïŽŗãWÑăû‚··‘Q—òı}¯ã‰I•éÕÂZ¨īès¶ZÈsŽæĔŠƦ›Ú@îá¾ó@‰˜ÙwU±ÉT廣TđŸWxĉWù׌¯cĩv‡Œėŧ³BM|¹k‰ªħ—¥TzNYnݍßpęrñĠĉRÑÈěVVе‚õ‡«Œ¯ůĉ¥áºaeõ|uĐh`Ü³ç@šƋĿa©|z²Ý¼ŸĴ貋ŸƒIƒû›I ā€óK¥}rÝ_Á´éMaňæêSĈ½Ž½KÙóĿeƃÆBŽ·¬ƃV×ĴƳ˜lŒµ`bԑ¨ˆÐÓ@s¬ƿ‚ûws¡åQÑßÁ`ŋĴ{Ī“T•ÚÅTSÄį¤Ç[ǾµMW¢ĭiÕØ¿@ŠÂ…pÕ]j†éò¿OƇĆƇp€êĉâlØw–ěsˆǩ‚ĵ¸c…bU¹ř¨^“ƒ±ze…ė·¥Ó@~¯‹éīB™Š\\”āƚǗÀƷŘóQīÈáP•œǥ@ŗĸIæÅ„hnszÁCËìñšÏ·ąĚÝUm®ó­Z±đ[‰Âÿiñ¬‰Òj°ŁŤ_uµ^‘°ŒìÇÊĶĒ¡Æ‡MğźİĨƥôRŽāð©[wâ䥩Ô\\°ÝĄ̄Ƣ’ăk™néǀůŠ˜ĆK„ĒĬœ¶è‰âz¨u¦¥L~ƄýÎIƖߔµĔƱĐċņbÎՂĄæ_ƞZRÖíŽJ²öLĸҜcºƖÎ\\ñºÛqY–Ѩ`x¥’ù^•}ƒÌđYªƅ”Aйn~Ꝛf¤áÀz„gŠÇDIԝ´Aňńňĕuĩt[{ù°ŁÏ•|Soċxţ[õÔĥkŋÞŭZ˺óYËüċrw €ÞkrťË¿XGǣ@Dü·Ē÷Aê[Ää€I®BÕИÞ_¢āĠpŠÛÄȉĖġDKÕK‡ÄNô‡ŠfœƫVó¼dz—H‘‹QµâFšù­Âœ³¦{Y‹Â¢ĚÜO „€{Ö¦ÞͨJÜÄƨ€lŽU˧ªÍE˨¡ĐĬĬùÎRƠŸHÕŔ_ƪàÒKäȇĬə²ȕnáûl—÷eǛò•Ğ\\ªÑò˜Üìc\\üqˆÕ[ēdžċªbØ­Œø|€¶ȴZdÆÂšońéŒGšŠǚnìÈƲ‚ہȖưòTxÊǪMīИÖŲÃɎO̚ǰއRěò—¿ġ~åŊœú‰¬ô¸qŽ’Ę[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ŀ¤ĄYÒ©ÊfºmԈȈ¡DŽ~¤„s²‚”ʘچžȂVƼîèW²æIJXŔþɔÖĚêϜêĮŢɨJ€˜¯ÎrDDšĤ€`€Q¾§~wâJÂ˜ñÈOú¤p¨ŪŊMǎÀW|ų ¿¾ɄĦƖAiƒ÷fØĶK¢ȝ˔"]],"encodeOffsets":[[[112750,20508]],[[123335,22980]],[[82455,44869]]]},"properties":{"cp":[116.3683244,39.915085],"name":"中华人民共和国","childNum":3}}],"UTF8Encoding":true} -------------------------------------------------------------------------------- /packages/charts/docs/data/maps/province/aomen.json: -------------------------------------------------------------------------------- 1 | {"type":"FeatureCollection","features":[{"id":"820001","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@LADC^umZ@DONWE@DALBBF@H@DFBBTC"],["@@P@LC@AGM@OECMBABBTCD@DDH"]],"encodeOffsets":[[[116285,22746]],[[116303,22746]]]},"properties":{"cp":[113.552965,22.207882],"name":"花地玛堂区","childNum":2}},{"id":"820002","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@MK@CA@AAGDEB@NVFJG"],"encodeOffsets":[[116281,22734]]},"properties":{"cp":[113.549052,22.199175],"name":"花王堂区","childNum":1}},{"id":"820003","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@EGOB@DNLHE@C"],"encodeOffsets":[[116285,22729]]},"properties":{"cp":[113.550252,22.193791],"name":"望德堂区","childNum":1}},{"id":"820004","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@ŸYMVAN@BFCBBDAFHDBBFDHIJJEFDPCHHlYJQ"],"encodeOffsets":[[116313,22707]]},"properties":{"cp":[113.55374,22.188119],"name":"大堂区","childNum":1}},{"id":"820005","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@JICGAECACGEBAAEDBFNXB@"],"encodeOffsets":[[116266,22728]]},"properties":{"cp":[113.54167,22.187778],"name":"风顺堂区","childNum":1}},{"id":"820006","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@ ZNWRquZCBCC@AEA@@ADCDCAACEAGBQ@INEL"],"encodeOffsets":[[116265,22694]]},"properties":{"cp":[113.558783,22.154124],"name":"嘉模堂区","childNum":1}},{"id":"820007","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@MOIAIEI@@GE@AAUCBdCFIFR@HAFBBDDBDCBC@@FB@BDDDA\\M"],"encodeOffsets":[[116316,22676]]},"properties":{"cp":[113.56925,22.136546],"name":"路凼填海区","childNum":1}},{"id":"820008","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@DKMMa_GC_COD@dVDBBF@@HJ@JFJBNPZK"],"encodeOffsets":[[116329,22670]]},"properties":{"cp":[113.559954,22.124049],"name":"圣方济各堂区","childNum":1}}],"UTF8Encoding":true} -------------------------------------------------------------------------------- /packages/charts/docs/data/maps/province/shanghai.json: -------------------------------------------------------------------------------- 1 | {"type":"FeatureCollection","features":[{"id":"310101","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@AHV@BDCPEPLENFHCJHFBNCAGBGXWFIBGCGMUKKCCcGCDGBALCPIAAPGR"],"encodeOffsets":[[124373,31970]]},"properties":{"cp":[121.490317,31.222771],"name":"黄浦区","childNum":1}},{"id":"310104","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@CEAMMAA@C@AFA@@BC@ABC@@BD@@BH@@BB@EHDDCBECADGEEAEBFNET]CMRELQjOEGRFBAHDBAHH@@B@BDA`H@F@BC@AB@FD@DD@@@CH@DDAFDD^LEPF@DFTDPHHQBOJBDOBKHADCOGCEAE@EFOBMAEUW@GBEHILMBE@KGM"],"encodeOffsets":[[124381,31859]]},"properties":{"cp":[121.43752,31.179973],"name":"徐汇区","childNum":1}},{"id":"310105","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@AACE@FO]KCCBECCG@@D@@CCmBSAcKG@EBAEGC@DC@QE@CA@@BEBMTNFAFDBA`D@BDA@AA@FFBBLD@@@IBDBABDB@@DBADB@CHA@@DC@C@@@BBABFDH@AHD@ACDA@FD@BCA@@CJCNWJ@BCHAFEF@XCV@DFH@VFBBCFD@HEFFFBB@@IDAJFBABIFK"],"encodeOffsets":[[124354,31964]]},"properties":{"cp":[121.4222,31.218123],"name":"长宁区","childNum":1}},{"id":"310106","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@AB@PCJBNG@ABBDBB@DNBAJJ@@FB@@H@@@DF@ENB@BDD@BAT@BENDFDPB@AF@A]G@BOCKCEBA@G@KBEDCLMVQ@EACDECABCDKECGDMEKFFODOACU@BGOGUCELAJABIECBBNFHJBTLHB@BADDD@FB@@DC@BHOVUJCFIG"],"encodeOffsets":[[124340,32022]]},"properties":{"cp":[121.448224,31.229003],"name":"静安区","childNum":1}},{"id":"310107","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@DB@DHBBCDBB@A@DF@@DFDDHGBDDALZCB@@EBA@ACQ@@DGBEFBB@FD@J@BFMBCCCDID@AODAEIDBDEBABBB@DC@AF@@AFGACBADBB@@NFADD@@BB@B@BAB@@@BBDA@HBB@AJ@@AD@@BB@AFHBDCJFHBGQAAJA@ALCBBF@@AB@@BD@@@JABDABD@@BHBBBNACEJA@ADAAA@B@ADAAAJBIQB@FCBBD@AGJ@@EJA@EHADDAB@BFANNDEVIPUAGD@@CA@@ECCBC@AGASKIAEGACA@EAEEA@EFC@DEAAUEG@CEU@WDE@EFGBADI@MV"],"encodeOffsets":[[124267,31987]]},"properties":{"cp":[121.392499,31.241701],"name":"普陀区","childNum":1}},{"id":"310109","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@OHWVFBABIKK@MJCJGBKV[C@@I[AOEODCACCCLADDBCFBD@FURQT@J@F@HABDFDLAPH@BTVCLBBE"],"encodeOffsets":[[124402,32064]]},"properties":{"cp":[121.491832,31.26097],"name":"虹口区","childNum":1}},{"id":"310110","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@JD@U\\ALIHID@NLLAJABUEGX@PVA@ZDDADGFX`ZKDHFAFHpSNGDCDGDM@cBGL[BKAGEGMOcY[GWA"],"encodeOffsets":[[124433,31997]]},"properties":{"cp":[121.522797,31.270755],"name":"杨浦区","childNum":1}},{"id":"310112","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@EBAD@@A@E_GCB@A@AG@BGCABGEAHQPFRiFKNQ^DFSEMFAFBHFBCFDDACCFGA@@AG@@AC@@AD@BAD@@AB@BED@B@F@B@FBBNDFLCDBCBFB@DFG@CBBABDB@CDBAFCB@DABD@B@DB@BD@@B@BB@B@@FJ@DKLFB@DMDBBABBCFDB@@HB@BBABBDCBGNBDAB@@BPDBAF@@AB@@AB@@CDB@BF@DGB@@CD@FDADF@BADDDCBBDCAAC@BCFEAAB@FECABC@ADBBEB@@EGCABAB@@CAA@CAIABAAA@@ECDGD@BCBBD@BBHBFALABAFBD@@CGA@BC@BCEAA@A@@AEA@@AAA@G@DCG@CCBAAA@ADBDAEAC@ACE@BCC@BG@ACBBAEAAA@B@CECDEAEBAB@BDB@DBD@BBD@FDBGBBFCAABCBDBCEC@UBACA@AAA@ABB@CCCE@AA@ADCD@@BF@@FB@@BDB@CDB@ED@DFB@ABB@HDAADCBE@CCACC@CACIABA@@@BD@@AD@DICABCECFA@AMEO@@CC@ABA@@ABA@GCACBADCDA@@BAAAB@BICADE@@BEAABC@GHC@E@@FD@@BA@CFC@@BC@AASEKG@ACAIZBFGDYCIAKGKAU@OCGAKIMIMCOEeC‘WOBQHI@C@CBB\\HBPTBHJHABECM@ADBB@J@F@D@B@FBDAD@NBBBN@T@DBBADFCFDDGTDJFAFNB@DB@EFFBADD@@DFDDCDBADERCDAB@DELGAADMCEPHB@AB@@BHF@@GNQV@DEJCDC@ADD@@BCFABADA@@FCB@DCD@DABA@EJEF@BEJCLGJABCHAB@BABCFCB@BED@BA@@BABADGFAAA@@CAAKGCAKAUTC@CDDBADIHDFCF@@CDBDCHDBAHGDBDCDABCAABAFKACBDDABBF@@@BHBBDDBC@BDFFFBBDD@@AH@HB@EFC@ABC@FFCFBB@LCFBBAEGFEDABGJMJCL@XGNFH@PDBB@FHDBAAA@@D@D@@CB@DGA@BCCA@@CABACAJA@@C@AKEA@EBBB@ACC@B_CABEMENSFA@AB@@DRFD@@CHDBFFAH@dLTBjA"],"encodeOffsets":[[124327,31940]]},"properties":{"cp":[121.375972,31.111658],"name":"闵行区","childNum":1}},{"id":"310113","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@JE@@BOAECMCAFS@ABC@ACA@FME@@C@@@GA@@EI@BIMA@CCA@CBAH@AMDI@OBACEEB@ABACCGB@FIB@FI@BHC@AAEDA@JRIABBCB@B@ABBCB@BIBDFMBAAGA@AC@BAACIB@@C@@AA@@BE@AAKD@BIBBBHRC@ICCCCDGABEA@@AC@@BI@@BAA@GCBAAA@ABBBCDAAEJFDB@P\\J@@FB@@DGA@FD@@DAAADCF@@ABBBCDDB@DF@CLCAEFEB@DG@@HD@DB@BB@@FHD@BADA@CFCFABDB@BED@BCDEFFBABB@ADG@GNCBFHAFA@@DCAIB@DB@@FBBEF^JBAH@AFD@A@@DA@@BFDABD@@JB@@BA@AD@DB@@FCJ@FA@C@ABAAABENDB@BCDCFG@ADDBEDDDABA@ADB@ADF@BD@BEACD@BCBJF@BABA@BBCFE@ABCLABBBAFEB@A@BCDEBADD@CBBBBAADBBD@B@BBADFADDDA@ED@ACB@FF@DFBBCB@@AC@@GF@B@AFD@@DB@@AD@@BD@\\PfK^I|]BAEGBE\\Q`W|i\\UdSXUBD@DFAEG\\UQQQY@QJONIVIEGEBCGYLW_HEBCCC@YUBAFKAUD"],"encodeOffsets":[[124384,32068]]},"properties":{"cp":[121.489934,31.398896],"name":"宝山区","childNum":1}},{"id":"310114","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@A@A@@AC@BCME@@AABCDAHBBE@@BED@@CAABAFAACJCBFPC@BJCDCDDNAAEI@C@@EAAFEHA@CR@BDB@FA@@DAKYCBACGHCCCE@@CEB@A@CAADGA@CCAADGB@DB@ADC@@ECBBDC@BGG@CCIC@EAAOCG@OEUHK@IDINAHCBEFFHABEAKDA@EAED@EAD@BED@FGAG@@BC@@AC@@DA@@CCBEA@DGAKFOB@CG@@BAA@CGCBAEA@CA@@DEA@FCFB@ABAAABAC@AAACFGEBCABCCABCCABCAB@@CC@ADGDEEC@EDCA@BA@BDA@ACEFECABC@@BB@BDC@AJIJCAADC@CGEB@@AB@BDF@JDD@DHBABD@B@@BCHE@@BC@@DCA@DC@@DDBADA@EDFBIPCFIIBCMAE@AJ@B@FAB@DAJDB@DDB@FD@@BCBBBB@@DABAB@DCBBBAHBB@FMCKB@HF@EHIACBE@BFCBBLAH@DD@@CD@D@BFNBCDGBAFTHBEBB@DB@@AJD@ANFABBBD@ABD@@ANDBDCD@BABA@ABLDCFDBF@ABC@ABDB@BFDADJDDCCDBDCDAAABBB@BC@ABA@ABC@@HA@C@@DJ@@DFB@BD@HB@AD@ABBDFA@HA@@CA@BDABOBMFAFB@ADBDAB\\LDAHBBADBHAPFJFAFBFFD@BJHRD@FHFNHDACCLADBH@DDFABHCB@BHJF@AJ@@FAFDB@AEFE@CBIHB@AC@@AA@DEHD@BD@ADB@BDB@AKD@@DBA@@@AD@DBBDBBDBD@@FDDBA@CDAHDBBHDADB@FA@BD@DCD@BFFCJD@DA@FBBDFADC@A@BFABEAABADKBAF@DEAAB@BA@AIEDA@ADCFB@AACE@BCA@BCB@BACCFCCABCH@DEDC@ACAFMBABBBAD@B@@EDI@EA@@CBCB@@AA@@IC@BAEC@AB@@CB@C@BEG@AB]IFEAA@EA@@CJADB@CB@BEEGDAHMH@BCA@BAEAFEDC@AFC@ACABALQGC@ECCE@@GH@@CFAFEDBDKE@@CCADCAABA@@DEBCBB@CC@@EHB@CA@@EI@GMEMICFIBBBABAAA"],"encodeOffsets":[[124249,32046]]},"properties":{"cp":[121.250333,31.383524],"name":"嘉定区","childNum":1}},{"id":"310115","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@bM²WLCļÑNI^_È€sJQ¶±`e`Z¡LƒD‡CsEWOWs@GBI\\wsYg|QNUBģFq„AZHZB@@JHBAJFRA@BB@HABB@@J@HBDBLAJC@@BD@ABA@B@AD@FB@@BA@@BA@G@@FC@AB@DA@ABCAC@@DEA@DD@BDEF@FQJE@CAGJA@ABCAEDBDGHADWR_TYJI@G@SD@AA@@AA@IDGB@A@BQBmAA@CBOAGFELC@AAaDACS@C@@AIAABKA@BEBFDADDBCJC@@BC@@A@@ABJBBD@DDDDB@DAFCDBBGCA@BAA@CEC@@FCA@DCA@AA@@EE@@AC@CD@BBBF@DD@DAA@BBB@BDBAB@VFDADACADBBEDAAAHECC@AAC@CAA@ACA@ABBFCFFD@D@ABBFBABDA@BAHD@ADF@BDD@FBCBCA@BBBABDDH@CDH@B@BB@@FB@BB@B@FBADD@@AHB@DC@EAABKBEBGAAAC@AAADC@CHFD@@BBABJBDBB@DB@@BABAHD@FA@AFCA@BADDBEFA@BBEFADD@BBCDAACDCCABE@BCECC@@DA@CHE@@ACA@DA@@BA@@BE@ABOC@AA@CBMAAHCDAAAB@AGA@@CADEAAABCACNA@KECLC@E@@EA@A@@A@AC@@AAAA@A@C@BA@CDABEAAADCABAAA@DEH@CEADACAKDHN@LAFKNGJAF@D@DBFNLHLANEP@FBFJJJDdHDDLLNVDHAHEJWXAF@FJFHDtDXHhZNPFHBHALK\\AH@dCNCHCDMHoTUJMJIP@RRZRR"],["@@PDNAvOFGBKCeEQGEI@IBMNY\\GJELATBJ"],["@@HRHJNBX@XCRGfEFGBM@eYuGIgCIAK@KDMPIREVCXARBP"]],"encodeOffsets":[[[124438,32149]],[[124808,31991]],[[124870,31965]]]},"properties":{"cp":[121.567706,31.245944],"name":"浦东新区","childNum":3}},{"id":"310116","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@DBBAGCBD"],["@@HADA@AGCKHBBF@"],["@@FACAAD"],["@@DB@EB@@CB@@GEQ@IEKAM@ATE@EHADF@GDCFFPD^BBED@@BD@@DPBB@@CDB@BLC@ADB@BF@@CF@@DB@BDCDA@@DCACBC@AB@HDBRTHGBCHBDB@AF@B@NACQ@@@AC@@CC@CIEE@CFCFHDBHABDN@BED@BDNA@HAF@FCBADDLD@DAAC@AB@@ANC@ANC@TDBL@DGJC^BDBDBJ@^F\\VHGPB@CD@BAF@DKDBBCA@BAC@FK@E@BD@@BNABCF@@AFB@AD@BADB@GA@@AF@BCFBDKB@@BDBB@BEDBBDF@@CFB@HD@@F@@@HA@BBA@BDC@BJADBBLB@AA@@ED@DIHA@BB@BDDBBCBA@@@BF@@CB@ABFBBCFB@BD@FCF@DBBAD@BAD@BABBBAHDJ@ABDDABDBHCBDJIBOFE@IDKJAFCBAJELAAEBCBKAA@GD@AIBEAIDOK@@EDEAABA@A@BB@@@B@B@AAD@@ADA@EJ@@CB@H@BLDBFA@@B@@GEB@EB@@CB@DETAAADA@GH@BHLAPA@ABBD@JU@ABBFCB@‚£«ugW›OCOCgB‡DaAE`@HCBBFCBAJA@AFDFAFFD@FDFCFBBA@BBAFBDA@CDAAA@STCBWLAAABBBCBAACB@AABBBIFAPCHCFBBCB@HA@CAABGPIBO@ICCEDMGAILADACCBCA@CECEAKCADCBADAAKAEC@HEBCAEDQBACEAAB@BGCYDEJCB@BBFN@B@@JDbHRJL@D@FA@@CCB@DABBDEFACSDA@AAA@DDBLFHAB@BABCAIDADABCEKCABC@CDABBBC@@B@BA@BBcO[@MGDCC@DK_KFMGBCFGADEA@AGCA@@DAD@AFB@BCB@DGOCCLKR]JADEAMMABBCA@CB@BABCAACB@CEAB@CAAGBDFGFHFGBBDFHF@BDB@ABBFDADFF@DHD@DFFADDGDDDADDABDA@DDCDFFBDEBFFDCDBCBDDEBBDB@@@CDCDI@GB@BBFAB]DAHCDDH@DDBHB@DHABDB@@FG@CABJBl@FEFCFBB@LB@J@@GPDA@DD@AD@D@@CCA@BCA@CB@A@@AF@BGFAADDB@ARF"]],"encodeOffsets":[[[124321,31442]],[[124337,31429]],[[124341,31419]],[[123933,31687]]]},"properties":{"cp":[121.330736,30.724697],"name":"金山区","childNum":4}},{"id":"310117","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@DLB@BFTHAFB@DABHFELFBBAH@DIHB@GB@@CB@BEDAB@LAPB@DFBADD@@BBBN@@DRB@BADALHABlH@@\\ABAFQPOLDBDBDCJBBJFA@FCJC@@DCAABDDBDKHB@CDBDEBCEINHDABFB@DDDD@F@@ABCAA@EB@@CH@B@BCBABD@DLBBCB@R@ADD@BAJ@BBBB@BA@@NG@AFELC@AB@@CBA@KJAAA@CAC@CLD@ABBBGJDBBDCFBBDCFDADBBDCABB@@BA@HHDBABFFDCBBDCB@BABB@AFEBBBED@FEDDBED@BALB@CD@DEHBBGDBBCB@BFB@@LC@@FJA@AJB@@B@@FB@@HH@@BJ@CJDDADDBB@B@BCJD@DB@AB@FC@@FC@@D@FDA@X\\ILF@CAA@ABBJ@DEXFPBI_CM@CF@NFF@BBB@BAADBLFBJABHKB@@L@BHXCAGBAF@@BB@@BCFBDDBD@BB^ENNEFEAEHCC@DBB@BB@AH@BFCD@B@ABDB@@FAF@ABXFnNHKB@BA@CDC@CDA@EB@BCBADE@AC@BCD@DCFI@CRUHM@@GE@AA@@BGAFONDBCHBFK@CBAHODICACDEC@CC@BCEAFEA@@CMABEIESCCHECEDBCAA@WAMAA@MBCAC@E@A@C@E@IAABCN@FDBAIGAGOSGAA[DAD@J@XIJ@PDDI@ODK@UD@BCAAGADSG@CAA@AABAAAA@@BECBC@IFCBC@CIG@A@AGDCABACCBAA@@@G@GCCB@AABC@ABC@ABCAE@EDC@@AEAADEABAA@@DE@@A@@ABADCAACA@@AGBCJC@@FB@@BMCBCAID@ACB@AAB@@G@@@EC@@GEA@DE@ACCAAFA@CA@AA@CLEAADE@@BB@@HCAABC@@BEA@BE@ADMB@AC@@A@FELD@ABB@ADCACLE@ABC@@DOAGH[U]EI@CACA]AIDCHK@CA@SMD@BMD@BA@@BBDCBC@CKBCDA@EBE@GMBACC@AFM@ACGBCAEGED@DFFDJD@@DD@@B@@DRMBA@E@@BCAGAADGHQSCA@GBAD@DADB@CB@DCACA@@CE@@DE@@ACA@BKD@ACA@DA@OA@CC@@AC@AF]AOCEECD@HCEGB@FSF@BBNFL@JFR@HA@@DA@@FCA"],"encodeOffsets":[[123933,31687]]},"properties":{"cp":[121.223543,31.03047],"name":"松江区","childNum":1}},{"id":"310118","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@@GCIBA@@FADHD@BCDBJIBID@ACA@@AD@BAFDFEBDB@ACB@@ADBFCD@FFHCBCD@@DA@DBBADDBADDBAADHFDEBB@BBDBABBBAA@DE@EFB@CB@@DFBABHD@DBB@AH@@DPALEHB@CFBDA@DB@@CD@AAEAEEACD@CAACGA@A@@AEBACCDALBBEBADBBADCACHCBGCADGACDC@@DECEJGBCCADCD@VSLBDBLHBB@DB@BBFCDEBA@AB@@AFC@ADADEBA@ABADGBAHIDKJOmMWEBAE@EB@@CABAA@C@ED@ABGA@@AAA@CDDFGFBFEMM]FAAC@CAACDE@AA@@AE@ABBHWDAGK@@@LAAGIBEAAKBCABA@AAE@MEE@@DDNJ`OAWECFI@AA@BBB@DKE[J@WCB@E@CD@@ED@@EBAA@@CICADA@A@CABCCCDII@@AG@@GA@@EA@@@IA@BIB@ED@@KA@AEA@ADCAAHGACFC@@DKAABC@AFCCEFC@AFAAEF@BAAABA@CDAACDEEBACAGGB@@AA@BACDAABCECCDAADGAACAHIAABAC@@EDEB@HBBBLIB@DA@@BAD@FKBEH@@MB@@AAAAAI@ABC@BCQ@A@ADKA@CACABADA@G@@DA@@FBBAD@BE@C@CC@CEABAGCJMDFFAACDCA@LGACCCBADB@CD@DI@EEBAIIACDCACAPKROBEBA@[G@AkGBBKBC@AQA@CM@AA@AC@BCEA@COAKBA@CBAFA@@DA@@HGACJG@ABEAFKGEBA@CEAGBEUKA@CQE@BCABCEBAHE@@BB@A@@DDB@ADB@DC@C@@BCCB@OC@HM@AHC@AHF@CHBF@BC@@DB@ADBB@BNB@BB@@FDB@DC@A@CRA@CFBBAFGAADDB@HA@@DB@@D@@ADBBEJDBM@ADg@ABFFABGBCNGBC@CACBAADAAEFACK[AAAJK@AC@GBEDG@ACOFOEAD@JQ@@FBdCDEL@FCD@H@JHXBPHABDEJ@BEDCACHCFAHA@@EG@QB@BBDE@@DE@AAE@@CG@ABADA@ABCAABCDBLD@DHNJDD@HDHHHJFdDPCTD\\JnE€MPDvBJHADHBBD@BD@@EHBFCBEDB@AD@HREB@FHD@DHBBGD@H@ABDBL@@AB@@AD@@CFA@BAFFD@BBB@CB@@FHDADB@@DEAADJB@DCHEAABBB@BFBAFEFADJDABIAADFB@DAB@B@BDBABCB@BE@@DD@Kz@DD@@HD@@DC@ADA@A@AFFB@HBA@BAB@FC@@AIBDBDABD@NA@BBBBABBRA@@@dFFDDHEBBHDNFFABDBDADCB@@AB@BCFO@ABCHCD@BBC@@@FDPRF@FA@DB@@AHAACFCHA@DFAACD@BBDAAABAD@BBD@@CDALBFB"],"encodeOffsets":[[124062,32028]]},"properties":{"cp":[121.113021,31.151209],"name":"青浦区","childNum":1}},{"id":"310120","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@LBBAJB@BD@T@BDbCBBD@FKHEPBDAB@nBRA@A@BHAJCB@@BB@@BTCH@J@ZI`SXQBCHGACFCDBBAB@HIDBF@NGDA@EFEACC@@CFB@CD@DBBAB@@CBAD@@EH@B@@AB@@AA@@EBCA@B@BAC@@AD@BIAKAC@G@IA@BA@GAAB@EQBIGA@IA@GYBYrƒĥDƒEŸU¡_‰[g¤A@EDAA@BIVC@AA@BOBKBAGG@@HCBBBSBCFA@@DA@@FFA@HA@@@EBCAAKG@A@@DI@@FCB@BC@BBA@A@@@A@@A@BABBBCF@FL@CPBJAFBJC@@HBBALADBFKBIFABEDIBCL@JEFAPKJHFBFADED@JADFD@AB@BBABBBB@DBH@CTHBBBADC@@VCL@PCJ‚TfD^JNJLJHBPDV@LBLHJBZDHCAEJYDB@BLHTFBBD@@AD@DEB@@AC@@EF@D@HGD@BAFB@AF@BCJD@ABABB@AB@DCBCDADB@HAB@BB@BAD@@DP@NF"],"encodeOffsets":[[124489,31743]]},"properties":{"cp":[121.458472,30.912345],"name":"奉贤区","childNum":1}},{"type":"Feature","properties":{"name":"崇明区"},"geometry":{"id":"310151","type":"MultiPolygon","coordinates":[["@@Ɯp@dG¶ƒY€IЏtuÆu¬RWˆWckĜyPVĆgðÕTUm…U¥c}S“H¥|÷Œ^oGĝ¬åеxƒb™žcAXor‘š]dš€"],["@@”MšURm@kYiD[YRwRmdS^ChQv"],["@@¬Q˜SzoMUægLShQ”e^sFwS_aL“’ïž{d\\ungZeNGZ"]],"encodeOffsets":[[[124119,32586]],[[124716,32134]],[[124427,32249]]]}}],"UTF8Encoding":true} -------------------------------------------------------------------------------- /packages/charts/docs/data/maps/province/xianggang.json: -------------------------------------------------------------------------------- 1 | {"type":"FeatureCollection","features":[{"id":"810001","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@D@bKBoCWKACBGCI@CJSVGFIBKCM@ABAF@LFHPFJJPFVB"],["@@ABD@@AA@"],["@@AAEAAB@DDBFC"]],"encodeOffsets":[[[116895,22829]],[[116861,22818]],[[116860,22817]]]},"properties":{"cp":[114.154334,22.281931],"name":"中西区","childNum":3}},{"id":"810002","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@BMHBBGD@BAHBD@HKDEF@FHDEDECCGCIAAQWCUBSBDXApREHD"],"encodeOffsets":[[116927,22822]]},"properties":{"cp":[114.18299,22.276345],"name":"湾仔区","childNum":1}},{"id":"810003","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@rWAGBEJKRO@ACCBEAIAEGEACKPA@MDICIDOBKDGAIBIABRNDHFEHADEGE@CFGLC@GAABC@AHECABAN|TTI"],"encodeOffsets":[[116967,22827]]},"properties":{"cp":[114.225965,22.279779],"name":"东区","childNum":1}},{"id":"810004","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@JBJAHBLCPAJCJDPCLOJM@IBAFBBA@CE@AAE@AAFIBQBADAFECCBEA@GFCAYBABIRC@QEGEACBEHMACECQACFE`A@GCK@AFFHADMJBBF@BB@FBHCFI@KLEBCAGWAAQDGCGJQHOPOHS`KLN@LDJAHETUDIJ@HDxCZD"],["@@ACCBFB"],["@@D@@ACCCB@CC@CFBDJA"],["@@BA@AG@@B@BF@"],["@@DABAGCADADBBDA"],["@@BAEBD@"]],"encodeOffsets":[[[116946,22787]],[[116886,22776]],[[116934,22767]],[[117006,22758]],[[116932,22748]],[[116970,22738]]]},"properties":{"cp":[114.160023,22.245811],"name":"南区","childNum":6}},{"id":"810005","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@AIBINQNIHU]IsRC@AvFBHFDCLDV@"],"encodeOffsets":[[116920,22860]]},"properties":{"cp":[114.173347,22.311632],"name":"油尖旺区","childNum":1}},{"id":"810006","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@H[@EEGU@KCCDGEEABQi@AHCF@B^P@BABOFCFBFF@FDNADADHJDjB"],"encodeOffsets":[[116919,22881]]},"properties":{"cp":[114.163349,22.333775],"name":"深水埗区","childNum":1}},{"id":"810007","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@DEBEFC@CJKD@DCHDLDBMEG@CFCLICETSDQSJeMGVKHGJIR@HFJBFG^FDF@"],"encodeOffsets":[[116925,22883]]},"properties":{"cp":[114.193047,22.312373],"name":"九龙城区","childNum":1}},{"id":"810008","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@AC@IH_BAYCEDIAGDICGCCDC@IL@DEDAFCFNDVD@BADBBHCFDJA^D"],"encodeOffsets":[[116970,22892]]},"properties":{"cp":[114.203985,22.336112],"name":"黄大仙区","childNum":1}},{"id":"810009","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@F@HWF@DABD@IHBB@GOAENMBE@AEAGOBCFE@CqXCRSTDFKJED@DFHANFCJBFCZD"],"encodeOffsets":[[116974,22868]]},"properties":{"cp":[114.214083,22.320679],"name":"观塘区","childNum":1}},{"id":"810010","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@AEDQ@WQACIKIGCQCABAHC@]I@ADC@ECICCKEGA@NuASIHyO@IEQW@CÙF~bNJFL@D@FLBBNPJJFIDAHEDBDHBDDBBTCB@AHDB^@@JHHF@DDLFJFDBHCD@PPD@L@RLLBDHVBNAHBBABGhB"],"encodeOffsets":[[116914,22950]]},"properties":{"cp":[114.121234,22.368458],"name":"荃湾区","childNum":1}},{"id":"810011","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@AC@G]@CABGA@SDAACCGAACFCBGJCIEOIAMKAEHGFgFgPS@E@MEGEEGCAO@E@SLUNCH@DDH@H@JEHAJCHQFAB\\`ZHTCFKBAHFFJFJBBZ@FC^CND@AEINGXA@OL@@U˜@@HN@BEE@@KTA@G"],["@@BAFADAAC@AACDACGEBBHAFGFBDD@"],["@@B@B@@CA@AD"],["@@BAB@CCA@ABDD"],["@@D@CGABAFD@"],["@@@ACICABJFD"],["@@DA@ACCC@ADBFBBBC"],["@@@A@@ABB@"]],"encodeOffsets":[[[116810,22924]],[[116618,22917]],[[116612,22891]],[[116626,22888]],[[116629,22880]],[[116725,22874]],[[116708,22866]],[[116720,22861]]]},"properties":{"cp":[113.976308,22.393896],"name":"屯门区","childNum":8}},{"id":"810012","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@BMDIEK@CDCAMHG@C@MCG@YBAZHZDLIJA[gAGBEHMTO@EAIKAQKK@C@OOC@GDCAIEKECCE@EE@HSB@LF@AFM@@G—@@VK@@PWBMHFJ@BMC]DEDY@AAEIEIGEABELSDVHNRJPHJLHXHFBP^ZVBRB@\\CJIDEH@DDAJHDFF@DGL@FFB^CRED@JFDPJHPBHED@HFFF"],"encodeOffsets":[[116828,23059]]},"properties":{"cp":[114.032528,22.44132],"name":"元朗区","childNum":1}},{"id":"810013","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@A@@HIEK@EA@BDH@BBBD@BBBAB@MN@DH@@BEFBDFBDA@C@@VABBDAJ@B@D@D@@CC@ECGB@ACACCA@IFEBAC@CFABEHGF@BACGGB"],["@@DC@CEDAFB@BA"],["@@AABB"],["@@@AC@DB"],["@@AABB"],["@@BAAAEABDDB"],["@@@A@CEDBBD@"],["@@@AABB@"],["@@DA@CIE@JFB"],["@@@@@@@@"],["@@DCD@BNDBDIAE@I@EE@ABABOHAJDDFABC"],["@@@A@B"],["@@B@B@ECAFB@BA"],["@@AA@BB@"],["@@@@A@B@"],["@@A@B@@@"],["@@@A@B"],["@@BCAB@B"],["@@@A@B"],["@@@FBCDBDABBBBBABCB@ABDBBDB@DH@JABBDNEBE@CD@FCKKG@AEC@EBA@ACIEA@EDBB@DB@ED"],["@@A@B@"],["@@D@BCG@ADBBBA"],["@@@@@@"],["@@BAAB"],["@@A@B@"],["@@@@AABB"],["@@QCKMECAKH@FDD@FFDABAFBBHJBPZBDJ@BCD@BBHA@DF@HAAAEEDA@EF@DGF@BC@CGE@GFBLABBADBBDAH@D@@AEIBAFF@ADBDAGGAEA@EIBCLBBA@CDBBCHBBABCTKLFZHRJH@DASMQGGIOEGAGBaNM@eEK@EDKLGBCFEBAAAGGGEEEIIGAEIDU@GBK@IDUAIAEEEGCIEBEAAHM@AABC@EKCWOMEIBKJYCYGAB@ZDH@N@DGHBNCFFNEN@JBFMJBDNDFHFBHEDALDFAFD@KFAFDBFH@FHDBF@DFHAHDLABAFBBDFF@BAAA@@D@DD@@HH@LLDCJFFCJ@BABEFABBJAB@DADDH@BBB@FBDCPBFEJBFC@AFADC@IDA"]],"encodeOffsets":[[[117049,23071]],[[117017,23092]],[[117013,23092]],[[117010,23091]],[[117004,23090]],[[117009,23086]],[[117081,23081]],[[117014,23081]],[[117057,23081]],[[117015,23077]],[[117062,23071]],[[117020,23075]],[[117024,23072]],[[117021,23072]],[[117029,23071]],[[117037,23071]],[[116974,23071]],[[116957,23067]],[[117036,23065]],[[117043,23049]],[[117033,23064]],[[117035,23059]],[[117043,23052]],[[117049,23053]],[[117040,23048]],[[117054,23039]],[[116975,23082]]]},"properties":{"cp":[114.147404,22.496143],"name":"北区","childNum":27}},{"id":"810014","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@HGNA@ACGC@G@OFADCL@FDDJDBA@M"],["@@@EACUMIMGGGCE@@CACIEMCMISGG@CESIGKGEQGG@CBABALQTCDABC@GCK@EBCACAAKBAHABAB@HA@AE@@ENADBDLFBFABACGEEICG@ICQB@B@J@@GBAAEEAODERKMIGMAAUAAAUA@ACAAA[ASAAHABGAMBUAAA@D@FSPIRBJ\\hNFXPLD@FADBBN@BGFBFAHPDFHD\\BJCL@HAV@JCBFJHFJFFHHBHDBHGHALKFCL@fFN@bMLATHHJRHTN"],["@@CIEAEJBBBDBBBBHAFBEG"],["@@@CFABAAGCC@ECCEACB@HAJAB@FEDJJDBHABA@CAC"],["@@BAEBBBBA"],["@@^DLCFBBBBJFJNLH@DHN@NXJFFHPHDABABKDAFDDABGAEBCDBFFALDDBFDBDADIBIFOCCICAAAI@CDG@KJ@HEBBDJCBALDBFBBBDB@HBHHALEDE@IEG@EGA@EDIBYEGAIEEICADMFOLA@KEE@OHKHYDAC@KCECAS@CCAEBGGOK@CACIYCEAGEBLCH@JGJ@FBXCHDL@P"],["@@AEA@ABB@@FB@BA"],["@@@CABBB"],["@@BAAAABBB"],["@@BACDBA"],["@@@A@B"],["@@@DHBAEC@A@"],["@@AA@BB@"],["@@BB@CAA@D"]],"encodeOffsets":[[[117183,23086]],[[117087,23049]],[[117113,23039]],[[117114,23018]],[[117122,23021]],[[116998,22974]],[[117082,23017]],[[117084,23018]],[[117081,23013]],[[117180,23003]],[[117039,23001]],[[116966,22997]],[[117006,22983]],[[116968,22976]]]},"properties":{"cp":[114.171713,22.44573],"name":"大埔区","childNum":14}},{"id":"810015","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@B@@@C@BB@A"],["@@FIJBFCF@JDF@DDBEDBDEHACGDK@EFEFK@EGAI@CDILEBEAIG@C@EECCKBCJEFGFAJGAGDKEGDG@GCCC@CBCFC@AIGAACFEEACC@CEAGB@EC@@AID@KBC@CACCGE@ABALGLBFA@GGEAE@GJAFBFIFCJHN@JOFGFG@@DBHABCFKAAEDCACI@GBGAAFI@GJEBE@ECAEBICCCU@KJI@IGKIBAAHcDEFENAFADE@CDGDET@BCBEJGDKAIKEEEGAACBCF@DA@MHI@CACCAE@AGE@OLEHGBAA@CECCGEAEBITGDANHRGLCDG@QSEG@DEDADHPFB@BEJIJBFHPA@GA@JACCBEBGVE@ABG`@JBDB@ADBFPBPJLLBJRDAJHFFBZDFLN@HPAHBFDDT@DBDF@LBDZCLGPGF@LFB@PKNEBCJDFFBJFHAZCJ@FHB"],["@@A@@@B@"],["@@@@@@"],["@@AABB"],["@@BAC@@DBA"],["@@BAA@ABB@"],["@@@AABB@"],["@@@AABB@"],["@@B@BACEC@@DDD"],["@@A@B@"],["@@@AADBA"],["@@DC@CA@ADA@ADD@"],["@@DBFADBLC@MDEBIA@@GJAHGCCBEAA@CCA@CAEKBEBGACBEDEJAFHHAB@LABBDA@@AA@CBBB@DD@@DCDCB@JBBHA"],["@@@AAAAD@@D@"],["@@@A@B@@"],["@@HE@C@ICAA@AHAHCEEFBF@BD@FA"],["@@BACA@CC@@DFD"],["@@@AA@BB"],["@@BCFE@ACCDQCACB@FCBCLGHFFBHFDB@DE@AEBBE"],["@@@ACAAFFA"],["@@BA@@CBB@"],["@@B@C@BB@A"],["@@@AABB@"],["@@@AA@@DBB@C"],["@@ACABDB"],["@@BAAB"],["@@@@@@"],["@@BACA@BBB"],["@@A@BB@A"],["@@FADIFEAICAACC@ABI@CFBDCD@BCHFFLB"],["@@CEBEBACA@AA@KD@JBHH@@BF@BE"],["@@@@A@B@"],["@@@CE@BFB@BA"],["@@AB@FDC@AAA"],["@@DHFEDAFGACBCMBEJ@D"],["@@BADABAB@BCKBCFDB"],["@@B@B@C@"],["@@A@@BB@@A"],["@@D@C@@@"],["@@BAAB"],["@@@AA@BB"],["@@BAAB@@"],["@@@AADBA"],["@@@@@@"],["@@@A@B"],["@@AA@DBA"],["@@@A@B"],["@@@A@B"],["@@@AABB@"],["@@BAEBBBBA"],["@@@@@@"],["@@A@B@"],["@@BC@AAAEDBDD@"],["@@B@@AAB"],["@@BACKAAC@@JDDBBB@"],["@@AA@B@@B@"],["@@BCA@@D"],["@@@@@@"],["@@@A@B"],["@@@EAABAE@AAA@@JF@@FBBBA@C"],["@@@CCB@BD@"],["@@AA@GAAEAAE@@E@AJFLDDFADFF@@EEC"],["@@AFDBJBAADCDEACFEGA@EEB@FEDAH"],["@@JDB@ACDC@AA@ACB@@ADA@EC@@EAEC@E@AECAABBFIBED@F@DFHFDDAFF"]],"encodeOffsets":[[[117146,22985]],[[117119,22980]],[[117154,22972]],[[117153,22970]],[[117139,22942]],[[117137,22939]],[[117137,22938]],[[117033,22925]],[[117063,22925]],[[117066,22923]],[[117031,22921]],[[117064,22919]],[[117029,22917]],[[117054,22915]],[[117038,22915]],[[117048,22915]],[[117075,22911]],[[117036,22912]],[[117039,22911]],[[117043,22905]],[[117051,22909]],[[117044,22906]],[[117050,22906]],[[117074,22902]],[[117143,22898]],[[117036,22899]],[[117076,22898]],[[117116,22882]],[[117120,22880]],[[117102,22876]],[[117073,22876]],[[117119,22871]],[[117126,22873]],[[117085,22870]],[[117121,22865]],[[117041,22863]],[[117123,22866]],[[117118,22860]],[[117118,22859]],[[117118,22859]],[[117069,22860]],[[117077,22857]],[[117116,22856]],[[117068,22845]],[[117059,22840]],[[117059,22838]],[[117061,22837]],[[117066,22837]],[[117066,22837]],[[117061,22835]],[[117070,22834]],[[117061,22834]],[[117068,22833]],[[117064,22810]],[[117100,22804]],[[117100,22803]],[[117118,22799]],[[117120,22799]],[[117028,22798]],[[117095,22795]],[[117103,22791]],[[117097,22787]],[[117105,22856]],[[117111,22850]],[[117039,22789]]]},"properties":{"cp":[114.264813,22.314203],"name":"西贡区","childNum":65}},{"id":"810016","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@PGJAVDFD@HDBJBPA@OCKDGAYHM@IDGAKBIQCAIKKOIMACEBC_CIBECGDAABC@AUCKCG@ICeAICAAGHAL@FFJCP@FDHADLBFDLJDJRB@XCRBFHBBBDB@BVBBBXBHPNJ"],"encodeOffsets":[[116956,22970]]},"properties":{"cp":[114.195126,22.379715],"name":"沙田区","childNum":1}},{"id":"810017","type":"Feature","geometry":{"type":"Polygon","coordinates":["@@AECBMBECGA@CDEPEBA]QDGBGj@@cUADF@F@DCFIFSJQTQBaASPEBGzTJvB@MHBLFDDDJ@FCD@@ZJHBBIJBBCCI@GDKEI@EBKHG"],"encodeOffsets":[[116892,22877]]},"properties":{"cp":[114.13918,22.363908],"name":"葵青区","childNum":1}},{"id":"810018","type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[["@@AIIGQCQ@GE@G@ICCGAAABCBA@GBGCA@ADOAGO@KBMLC@ACAEFARSDEACSGCEACLIL@DEPCBACEAECCE@AACEIECCKCMGI@KJGJEJ@FDLIBSGUAOOSEAABE@ECG_CSBUPAHGBICEOUMGCKBC@GCGGMCABDRGDAF@HBFEHAP@JJJH@BNRFDDBHEBICAH@DPHF@DAFFFNLBRFBHNNBD@HEJJVED@DBD’ZD@DEPFBAFCBAI[@CFGF@~dÚE"],["@@DC@AKE@ABADDF@BCFCAAIEG@CBAB@DABAFGDBBXF"],["@@BAAAC@ADDBBA"],["@@BCAAIBA@BDBDJB@CAA"],["@@BCCGGCGBABBHFDL@"],["@@J@FC@AAKFGCIC@EDADAD@B@BCBAAEHI@AF@BB@@DT@"],["@@CEMI@ABEHHFBHBHAFDFBF@BCLBDC@AGIK@OMDKJM@CAAC@YP@AHKAGAACBGHEGC@GBMDCD@HBDFDDDBXCFBNAHEBA@@IEAGCK@CNBDLHHD@BEBDFGD@DVJBBBBBCF@BECGACLGBEAADEDADFF@DE@E"],["@@@CEA@DDDBA"],["@@FEFBD@DEC@@CCAACGF@AE@CCBAC@CCCCCBBBG@AHH@DHH@DFADABE@CD@BD@DF@BABBDDBH@DBDB@E@AEAFABAKCAA@EDA"],["@@D@ACAACD@B@BDA"],["@@BAC@BB"],["@@B@BBBA@EACGAEFA@GDBHJJFA@CB@BCAA@C"],["@@D@BCBEAECCGC@BIB@CAA@FA@@PTD"],["@@DE@KG@CBAHBDDABFB@"],["@@BB@CAB"],["@@BHBB@CAEA@"],["@@BADBDABAD@BAAABAAAABABAA@CA@ADAAAB@DABCACCC@BRHCBC"],["@@@A@ACA@DDB"],["@@DAAC@@CD@BB@"],["@@ABBA"],["@@BAC@BB"],["@@AAA@BDBA"],["@@A@B@"],["@@BBBAAAABCAA@FB"],["@@@BD@DDCDBDDBDAB@FCAAE@@EBABEE@CAI@AACAGF@DFDF@DA"],["@@@A@A@D"],["@@BACA@BBB"],["@@B@@AEABBBB"],["@@DFPFBFF@BCFCFICCDEBIQA@DA@EC@ECCEAE@FJIBABD@@DCAABBJDF"]],"encodeOffsets":[[[116799,22849]],[[116787,22826]],[[116803,22822]],[[116823,22817]],[[116799,22797]],[[116780,22791]],[[116882,22747]],[[116881,22757]],[[116774,22741]],[[116575,22748]],[[116686,22746]],[[116733,22725]],[[117001,22721]],[[117036,22720]],[[117038,22719]],[[117053,22714]],[[116651,22714]],[[117053,22714]],[[116664,22710]],[[116665,22706]],[[116984,22706]],[[116645,22704]],[[116647,22703]],[[116640,22702]],[[116646,22692]],[[116656,22693]],[[116663,22685]],[[116998,22691]],[[117001,22702]]]},"properties":{"cp":[113.946059,22.286371],"name":"离岛区","childNum":29}}],"UTF8Encoding":true} -------------------------------------------------------------------------------- /packages/charts/docs/echarts/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 基础图表组件 3 | --- 4 | 5 | # ECharts 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import ECharts from '@rsuite/charts'; 12 | import option from './option.json'; 13 | 14 | export default () => ( 15 |
16 | 17 |
18 | ); 19 | ``` 20 | 21 | ## 加载中状态 22 | 23 | ```jsx 24 | import React, { useState } from 'react'; 25 | import { LineChart } from '@rsuite/charts'; 26 | import data from './loading.json'; 27 | 28 | export default () => { 29 | const [loading, setLoading] = useState(true); 30 | const handleToggleLoading = (loading) => setLoading(loading); 31 | 32 | return ( 33 |
34 | 35 |
36 | 41 |
42 |
43 | ); 44 | }; 45 | ``` 46 | 47 | ## 空数据状态 48 | 49 | ```jsx 50 | import React, { useState } from 'react'; 51 | import { LineChart } from '@rsuite/charts'; 52 | 53 | export default () => { 54 | return ( 55 | 62 | ); 63 | }; 64 | ``` 65 | 66 | ### 自定义空数据占位符 67 | 68 | ```jsx 69 | import React, { useState } from 'react'; 70 | import { LineChart } from '@rsuite/charts'; 71 | 72 | export default () => { 73 | return ( 74 |
没有符合筛选条件的数据
} 78 | /> 79 | ); 80 | }; 81 | ``` 82 | -------------------------------------------------------------------------------- /packages/charts/docs/echarts/loading.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["00:00", 68874], 3 | ["01:00", 61436], 4 | ["02:00", 13057], 5 | ["03:00", 3911], 6 | ["04:00", 34126], 7 | ["05:00", 35901], 8 | ["06:00", 84671], 9 | ["07:00", 49445], 10 | ["08:00", 55172], 11 | ["09:00", 77145], 12 | ["10:00", 56307], 13 | ["11:00", 4378], 14 | ["12:00", 84317], 15 | ["13:00", 36118], 16 | ["14:00", 25326], 17 | ["15:00", 72575], 18 | ["16:00", 31141], 19 | ["17:00", 78784], 20 | ["18:00", 37441], 21 | ["19:00", 55667], 22 | ["20:00", 83654], 23 | ["21:00", 61721], 24 | ["22:00", 76744], 25 | ["23:00", 86145] 26 | ] 27 | -------------------------------------------------------------------------------- /packages/charts/docs/echarts/option.json: -------------------------------------------------------------------------------- 1 | { 2 | "color": [ 3 | "#60c0dd", 4 | "#fe8463", 5 | "#9bca63", 6 | "#fad860", 7 | "#29D3D3", 8 | "#d7504b", 9 | "#c6e579", 10 | "#26c0c0", 11 | "#f0805a", 12 | "#f4e001" 13 | ], 14 | "tooltip": { 15 | "trigger": "axis", 16 | "axisPointer": { 17 | "type": "shadow" 18 | } 19 | }, 20 | "legend": { 21 | "top": "20", 22 | "data": [ 23 | "直接访问", 24 | "邮件营销", 25 | "联盟广告", 26 | "视频广告", 27 | "搜索引擎", 28 | "百度", 29 | "谷歌", 30 | "必应", 31 | "其他" 32 | ] 33 | }, 34 | "grid": { 35 | "left": "3%", 36 | "right": "4%", 37 | "bottom": "3%", 38 | "containLabel": true 39 | }, 40 | "xAxis": { 41 | "type": "category", 42 | "axisLine": { 43 | "lineStyle": { 44 | "color": "#CCC" 45 | } 46 | }, 47 | "axisLabel": { 48 | "rotate": -45 49 | }, 50 | "data": ["周一", "周二", "周三", "周四", "周五", "周六", "周日"] 51 | }, 52 | "yAxis": { 53 | "type": "value", 54 | "nameTextStyle": { 55 | "color": "#000" 56 | }, 57 | "axisLine": { 58 | "lineStyle": { 59 | "color": "#CCC" 60 | } 61 | }, 62 | "splitLine": { 63 | "lineStyle": { 64 | "color": "rgba(240, 240, 240, 0.8)" 65 | } 66 | }, 67 | "splitArea": { 68 | "show": true, 69 | "areaStyle": { 70 | "color": ["rgba(250,250,250,0.1)", "rgba(200,200,200,0.1)"] 71 | } 72 | } 73 | }, 74 | "series": [ 75 | { 76 | "name": "直接访问", 77 | "type": "bar", 78 | "data": [320, 332, 301, 334, 390, 330, 320] 79 | }, 80 | { 81 | "name": "邮件营销", 82 | "type": "bar", 83 | "stack": "广告", 84 | "data": [120, 132, 101, 134, 90, 230, 210] 85 | }, 86 | { 87 | "name": "联盟广告", 88 | "type": "bar", 89 | "stack": "广告", 90 | "data": [220, 182, 191, 234, 290, 330, 310] 91 | }, 92 | { 93 | "name": "视频广告", 94 | "type": "bar", 95 | "stack": "广告", 96 | "data": [150, 232, 201, 154, 190, 330, 410] 97 | }, 98 | { 99 | "name": "搜索引擎", 100 | "type": "bar", 101 | "data": [862, 1018, 964, 1026, 1679, 1600, 1570], 102 | "markLine": { 103 | "lineStyle": { 104 | "normal": { 105 | "type": "dashed" 106 | } 107 | }, 108 | "data": [[{ "type": "min" }, { "type": "max" }]] 109 | } 110 | }, 111 | { 112 | "name": "百度", 113 | "type": "bar", 114 | "barWidth": 5, 115 | "stack": "搜索引擎", 116 | "data": [620, 732, 701, 734, 1090, 1130, 1120] 117 | }, 118 | { 119 | "name": "谷歌", 120 | "type": "bar", 121 | "stack": "搜索引擎", 122 | "data": [120, 132, 101, 134, 290, 230, 220] 123 | }, 124 | { 125 | "name": "必应", 126 | "type": "bar", 127 | "stack": "搜索引擎", 128 | "data": [60, 72, 71, 74, 190, 130, 110] 129 | }, 130 | { 131 | "name": "其他", 132 | "type": "bar", 133 | "stack": "搜索引擎", 134 | "data": [62, 82, 91, 84, 109, 110, 120] 135 | } 136 | ] 137 | } 138 | -------------------------------------------------------------------------------- /packages/charts/docs/funnel-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 漏斗图 3 | --- 4 | 5 | # FunnelChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { FunnelChart, Funnel } from '@rsuite/charts'; 12 | 13 | const data1 = [ 14 | ['品牌认知度', 70], 15 | ['品牌购买欲望', 44], 16 | ['品牌忠诚', 21], 17 | ['品牌使用', 35], 18 | ['品牌常用', 32], 19 | ]; 20 | 21 | const data2 = [ 22 | ['目标人群到达率', 34.4], 23 | ['广告认知度', 18.2], 24 | ['品牌联系度', 8.4], 25 | ]; 26 | 27 | const color2 = ['#34c3ff', '#009de6', '#0771b3']; 28 | 29 | export default () => ( 30 | 31 | 32 | 33 | 34 | ); 35 | ``` 36 | -------------------------------------------------------------------------------- /packages/charts/docs/index.md: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 3 | `@rsuite/charts` 是基于 ECharts 的 RSUITE 图表设计实现。 4 | 5 | npm i @rsuite/charts echarts 6 | -------------------------------------------------------------------------------- /packages/charts/docs/line-chart/basic.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["00:00", 81892], 3 | ["01:00", 84365], 4 | ["02:00", 54029], 5 | ["03:00", 3355], 6 | ["04:00", 4354], 7 | ["05:00", 66019], 8 | ["06:00", 9730], 9 | ["07:00", 23042], 10 | ["08:00", 22501], 11 | ["09:00", 80550], 12 | ["10:00", 2521], 13 | ["11:00", 70519], 14 | ["12:00", 4494], 15 | ["13:00", 25376], 16 | ["14:00", 83612], 17 | ["15:00", 68671], 18 | ["16:00", 19130], 19 | ["17:00", 21519], 20 | ["18:00", 73269], 21 | ["19:00", 14993], 22 | ["20:00", 60756], 23 | ["21:00", 74292], 24 | ["22:00", 77725], 25 | ["23:00", 74567] 26 | ] 27 | -------------------------------------------------------------------------------- /packages/charts/docs/line-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 折线图 3 | --- 4 | 5 | # LineChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { LineChart } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ; 15 | ``` 16 | 17 | ## 多条图线 18 | 19 | ```jsx 20 | import React from 'react'; 21 | import { LineChart, Line, YAxis } from '@rsuite/charts'; 22 | import data from './multiple-lines.json'; 23 | 24 | export default () => ( 25 | 26 | `${value / 1000}K`} /> 27 | 28 | 29 | 30 | ); 31 | ``` 32 | 33 | ## 多个 Y 轴 34 | 35 | ```jsx 36 | import React from 'react'; 37 | import { LineChart, Line, YAxis } from '@rsuite/charts'; 38 | import data from './multiple-yaxis.json'; 39 | 40 | export default () => ( 41 | 42 | 43 | value.toFixed(2)} /> 44 | 45 | 46 | 47 | ); 48 | ``` 49 | 50 | ## 图线阴影 51 | 52 | ```jsx 53 | import React from 'react'; 54 | import { LineChart, Line, YAxis } from '@rsuite/charts'; 55 | import data from './multiple-lines.json'; 56 | 57 | export default () => ( 58 | 59 | 60 | 61 | 62 | ); 63 | ``` 64 | -------------------------------------------------------------------------------- /packages/charts/docs/line-chart/multiple-lines.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["00:00", 24758, 18180], 3 | ["01:00", 57666, 73289], 4 | ["02:00", 1743, 1037], 5 | ["03:00", 60425, 86558], 6 | ["04:00", 2862, 63701], 7 | ["05:00", 3631, 55744], 8 | ["06:00", 83788, 53377], 9 | ["07:00", 34138, 8063], 10 | ["08:00", 65635, 87076], 11 | ["09:00", 40086, 32176], 12 | ["10:00", 89728, 36250], 13 | ["11:00", 55000, 64098], 14 | ["12:00", 67378, 56347], 15 | ["13:00", 53958, 89845], 16 | ["14:00", 30590, 1742], 17 | ["15:00", 59808, 87358], 18 | ["16:00", 6570, 58156], 19 | ["17:00", 20861, 48829], 20 | ["18:00", 64949, 75989], 21 | ["19:00", 85392, 63148], 22 | ["20:00", 57778, 60936], 23 | ["21:00", 27390, 2766], 24 | ["22:00", 35348, 45691], 25 | ["23:00", 50878, 8247] 26 | ] 27 | -------------------------------------------------------------------------------- /packages/charts/docs/line-chart/multiple-yaxis.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["00:00", 2619, 0], 3 | ["01:00", 87604, 3], 4 | ["02:00", 63805, 2], 5 | ["03:00", 42095, 3], 6 | ["04:00", 71358, 5], 7 | ["05:00", 72006, 3], 8 | ["06:00", 30150, 4], 9 | ["07:00", 10763, 3], 10 | ["08:00", 66611, 6], 11 | ["09:00", 56978, 5], 12 | ["10:00", 24397, 3], 13 | ["11:00", 7569, 3], 14 | ["12:00", 63603, 2], 15 | ["13:00", 309, 0], 16 | ["14:00", 732, 1], 17 | ["15:00", 43679, 4], 18 | ["16:00", 48109, 4], 19 | ["17:00", 88727, 4], 20 | ["18:00", 46981, 5], 21 | ["19:00", 17816, 4], 22 | ["20:00", 23644, 5], 23 | ["21:00", 28492, 2], 24 | ["22:00", 85677, 2], 25 | ["23:00", 23521, 3] 26 | ] 27 | -------------------------------------------------------------------------------- /packages/charts/docs/map-chart/basic.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["北京", 133], 3 | ["天津", 249], 4 | ["上海", 529], 5 | ["重庆", 923], 6 | ["河北", 756], 7 | ["河南", 372], 8 | ["云南", 907], 9 | ["辽宁", 998], 10 | ["黑龙江", 826], 11 | ["湖南", 261], 12 | ["安徽", 129], 13 | ["山东", 408], 14 | ["新疆", 487], 15 | ["江苏", 39], 16 | ["浙江", 437], 17 | ["江西", 399], 18 | ["湖北", 780], 19 | ["广西", 536], 20 | ["甘肃", 180], 21 | ["山西", 550], 22 | ["内蒙古", 342], 23 | ["陕西", 95], 24 | ["吉林", 409], 25 | ["福建", 280], 26 | ["贵州", 54], 27 | ["广东", 20], 28 | ["青海", 527], 29 | ["西藏", 32], 30 | ["四川", 910], 31 | ["宁夏", 704], 32 | ["海南", 337], 33 | ["台湾", 720], 34 | ["香港", 412], 35 | ["澳门", 888], 36 | ["南海诸岛", 975] 37 | ] 38 | -------------------------------------------------------------------------------- /packages/charts/docs/map-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 地图 3 | --- 4 | 5 | # MapChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import * as echarts from 'echarts/core'; 12 | import { MapChart } from '@rsuite/charts'; 13 | import chinaMapJson from '../data/maps/china.json'; 14 | import data from './basic.json'; 15 | 16 | echarts.registerMap('china', chinaMapJson); 17 | 18 | export default () => ; 19 | ``` 20 | 21 | ## 多语言 22 | 23 | ```jsx 24 | import React from 'react'; 25 | import * as echarts from 'echarts/core'; 26 | import { MapChart, VisualMap } from '@rsuite/charts'; 27 | import chinaMapJson from '../data/maps/china.json'; 28 | import chinaProvinces from '../data/locales/en-US/china-provinces'; 29 | import data from './basic.json'; 30 | 31 | echarts.registerMap('china', chinaMapJson); 32 | 33 | export default () => ( 34 | 35 | 36 | 37 | ); 38 | ``` 39 | -------------------------------------------------------------------------------- /packages/charts/docs/pie-chart/basic.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["搜索引擎", 40], 3 | ["外部链接", 6], 4 | ["站内来源", 6], 5 | ["其他", 1], 6 | ["直接访问", 47] 7 | ] 8 | -------------------------------------------------------------------------------- /packages/charts/docs/pie-chart/donut.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["有汽车", 40], 3 | ["无汽车", 60] 4 | ] 5 | -------------------------------------------------------------------------------- /packages/charts/docs/pie-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 饼图 3 | --- 4 | 5 | # PieChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { PieChart } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ; 15 | ``` 16 | 17 | ## 环形饼图 18 | 19 | ```jsx 20 | import React from 'react'; 21 | import { PieChart } from '@rsuite/charts'; 22 | import data from './donut.json'; 23 | 24 | const colors = ['#34c3ff', '#1464ac']; 25 | 26 | export default () => ; 27 | ``` 28 | -------------------------------------------------------------------------------- /packages/charts/docs/radar-chart/basic.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["广告的内容清晰易懂", 100, 62, 53], 3 | ["广告的内容是可信的", 100, 75, 80], 4 | ["广告中的品牌符合我的生活方式和需要", 100, 44, 37], 5 | ["这个广告与众不同,很独特", 100, 39, 56], 6 | ["这个广告让我想与身边的人分享", 100, 44, 61] 7 | ] 8 | -------------------------------------------------------------------------------- /packages/charts/docs/radar-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 雷达图 3 | --- 4 | 5 | # RadarChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { RadarChart, RadarLine } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ( 15 | 16 | 17 | 18 | 19 | ); 20 | ``` 21 | -------------------------------------------------------------------------------- /packages/charts/docs/sankey-chart/basic.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { "name": "Agricultural 'waste'" }, 4 | { "name": "Bio-conversion" }, 5 | { "name": "Liquid" }, 6 | { "name": "Losses" }, 7 | { "name": "Solid" }, 8 | { "name": "Gas" }, 9 | { "name": "Biofuel imports" }, 10 | { "name": "Biomass imports" }, 11 | { "name": "Coal imports" }, 12 | { "name": "Coal" }, 13 | { "name": "Coal reserves" }, 14 | { "name": "District heating" }, 15 | { "name": "Industry" }, 16 | { "name": "Heating and cooling - commercial" }, 17 | { "name": "Heating and cooling - homes" }, 18 | { "name": "Electricity grid" }, 19 | { "name": "Over generation / exports" }, 20 | { "name": "H2 conversion" }, 21 | { "name": "Road transport" }, 22 | { "name": "Agriculture" }, 23 | { "name": "Rail transport" }, 24 | { "name": "Lighting & appliances - commercial" }, 25 | { "name": "Lighting & appliances - homes" }, 26 | { "name": "Gas imports" }, 27 | { "name": "Ngas" }, 28 | { "name": "Gas reserves" }, 29 | { "name": "Thermal generation" }, 30 | { "name": "Geothermal" }, 31 | { "name": "H2" }, 32 | { "name": "Hydro" }, 33 | { "name": "International shipping" }, 34 | { "name": "Domestic aviation" }, 35 | { "name": "International aviation" }, 36 | { "name": "National navigation" }, 37 | { "name": "Marine algae" }, 38 | { "name": "Nuclear" }, 39 | { "name": "Oil imports" }, 40 | { "name": "Oil" }, 41 | { "name": "Oil reserves" }, 42 | { "name": "Other waste" }, 43 | { "name": "Pumped heat" }, 44 | { "name": "Solar PV" }, 45 | { "name": "Solar Thermal" }, 46 | { "name": "Solar" }, 47 | { "name": "Tidal" }, 48 | { "name": "UK land based bioenergy" }, 49 | { "name": "Wave" }, 50 | { "name": "Wind" } 51 | ], 52 | "links": [ 53 | { "source": "Agricultural 'waste'", "target": "Bio-conversion", "value": 124.729 }, 54 | { "source": "Bio-conversion", "target": "Liquid", "value": 0.597 }, 55 | { "source": "Bio-conversion", "target": "Losses", "value": 26.862 }, 56 | { "source": "Bio-conversion", "target": "Solid", "value": 280.322 }, 57 | { "source": "Bio-conversion", "target": "Gas", "value": 81.144 }, 58 | { "source": "Biofuel imports", "target": "Liquid", "value": 35 }, 59 | { "source": "Biomass imports", "target": "Solid", "value": 35 }, 60 | { "source": "Coal imports", "target": "Coal", "value": 11.606 }, 61 | { "source": "Coal reserves", "target": "Coal", "value": 63.965 }, 62 | { "source": "Coal", "target": "Solid", "value": 75.571 }, 63 | { "source": "District heating", "target": "Industry", "value": 10.639 }, 64 | { "source": "District heating", "target": "Heating and cooling - commercial", "value": 22.505 }, 65 | { "source": "District heating", "target": "Heating and cooling - homes", "value": 46.184 }, 66 | { "source": "Electricity grid", "target": "Over generation / exports", "value": 104.453 }, 67 | { "source": "Electricity grid", "target": "Heating and cooling - homes", "value": 113.726 }, 68 | { "source": "Electricity grid", "target": "H2 conversion", "value": 27.14 }, 69 | { "source": "Electricity grid", "target": "Industry", "value": 342.165 }, 70 | { "source": "Electricity grid", "target": "Road transport", "value": 37.797 }, 71 | { "source": "Electricity grid", "target": "Agriculture", "value": 4.412 }, 72 | { "source": "Electricity grid", "target": "Heating and cooling - commercial", "value": 40.858 }, 73 | { "source": "Electricity grid", "target": "Losses", "value": 56.691 }, 74 | { "source": "Electricity grid", "target": "Rail transport", "value": 7.863 }, 75 | { 76 | "source": "Electricity grid", 77 | "target": "Lighting & appliances - commercial", 78 | "value": 90.008 79 | }, 80 | { "source": "Electricity grid", "target": "Lighting & appliances - homes", "value": 93.494 }, 81 | { "source": "Gas imports", "target": "Ngas", "value": 40.719 }, 82 | { "source": "Gas reserves", "target": "Ngas", "value": 82.233 }, 83 | { "source": "Gas", "target": "Heating and cooling - commercial", "value": 0.129 }, 84 | { "source": "Gas", "target": "Losses", "value": 1.401 }, 85 | { "source": "Gas", "target": "Thermal generation", "value": 151.891 }, 86 | { "source": "Gas", "target": "Agriculture", "value": 2.096 }, 87 | { "source": "Gas", "target": "Industry", "value": 48.58 }, 88 | { "source": "Geothermal", "target": "Electricity grid", "value": 7.013 }, 89 | { "source": "H2 conversion", "target": "H2", "value": 20.897 }, 90 | { "source": "H2 conversion", "target": "Losses", "value": 6.242 }, 91 | { "source": "H2", "target": "Road transport", "value": 20.897 }, 92 | { "source": "Hydro", "target": "Electricity grid", "value": 6.995 }, 93 | { "source": "Liquid", "target": "Industry", "value": 121.066 }, 94 | { "source": "Liquid", "target": "International shipping", "value": 128.69 }, 95 | { "source": "Liquid", "target": "Road transport", "value": 135.835 }, 96 | { "source": "Liquid", "target": "Domestic aviation", "value": 14.458 }, 97 | { "source": "Liquid", "target": "International aviation", "value": 206.267 }, 98 | { "source": "Liquid", "target": "Agriculture", "value": 3.64 }, 99 | { "source": "Liquid", "target": "National navigation", "value": 33.218 }, 100 | { "source": "Liquid", "target": "Rail transport", "value": 4.413 }, 101 | { "source": "Marine algae", "target": "Bio-conversion", "value": 4.375 }, 102 | { "source": "Ngas", "target": "Gas", "value": 122.952 }, 103 | { "source": "Nuclear", "target": "Thermal generation", "value": 839.978 }, 104 | { "source": "Oil imports", "target": "Oil", "value": 504.287 }, 105 | { "source": "Oil reserves", "target": "Oil", "value": 107.703 }, 106 | { "source": "Oil", "target": "Liquid", "value": 611.99 }, 107 | { "source": "Other waste", "target": "Solid", "value": 56.587 }, 108 | { "source": "Other waste", "target": "Bio-conversion", "value": 77.81 }, 109 | { "source": "Pumped heat", "target": "Heating and cooling - homes", "value": 193.026 }, 110 | { "source": "Pumped heat", "target": "Heating and cooling - commercial", "value": 70.672 }, 111 | { "source": "Solar PV", "target": "Electricity grid", "value": 59.901 }, 112 | { "source": "Solar Thermal", "target": "Heating and cooling - homes", "value": 19.263 }, 113 | { "source": "Solar", "target": "Solar Thermal", "value": 19.263 }, 114 | { "source": "Solar", "target": "Solar PV", "value": 59.901 }, 115 | { "source": "Solid", "target": "Agriculture", "value": 0.882 }, 116 | { "source": "Solid", "target": "Thermal generation", "value": 400.12 }, 117 | { "source": "Solid", "target": "Industry", "value": 46.477 }, 118 | { "source": "Thermal generation", "target": "Electricity grid", "value": 525.531 }, 119 | { "source": "Thermal generation", "target": "Losses", "value": 787.129 }, 120 | { "source": "Thermal generation", "target": "District heating", "value": 79.329 }, 121 | { "source": "Tidal", "target": "Electricity grid", "value": 9.452 }, 122 | { "source": "UK land based bioenergy", "target": "Bio-conversion", "value": 182.01 }, 123 | { "source": "Wave", "target": "Electricity grid", "value": 19.013 }, 124 | { "source": "Wind", "target": "Electricity grid", "value": 289.366 } 125 | ] 126 | } 127 | -------------------------------------------------------------------------------- /packages/charts/docs/sankey-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 桑基图 3 | --- 4 | 5 | # SankeyChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { SankeyChart } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ; 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/charts/docs/scatter-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 散点图 3 | --- 4 | 5 | # ScatterChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { ScatterChart, XAxis, YAxis, Scatter } from '@rsuite/charts'; 12 | 13 | const data1 = [ 14 | [26, 7, 18], 15 | [53, 9, 35], 16 | [61, 18, 22], 17 | [62, 17, 22], 18 | [67, 5, 50], 19 | ]; 20 | 21 | const data2 = [ 22 | [30, 11, 22], 23 | [37, 6, 18], 24 | [39, 5, 22], 25 | [42, 9, 35], 26 | [43, 17, 50], 27 | ]; 28 | 29 | const data3 = [ 30 | [30, 10, 22], 31 | [31, 11, 18], 32 | [48, 8, 22], 33 | [59, 6, 35], 34 | [63, 16, 50], 35 | ]; 36 | 37 | const data4 = [ 38 | [30, 5, 22], 39 | [49, 8, 35], 40 | [52, 15, 22], 41 | [59, 12, 18], 42 | [61, 5, 50], 43 | ]; 44 | 45 | export default () => ( 46 | 47 | 48 | `${value}%`} 52 | minInterval={5} 53 | /> 54 | data[2]} /> 55 | data[2]} /> 56 | data[2]} /> 57 | data[2]} /> 58 | 59 | ); 60 | ``` 61 | -------------------------------------------------------------------------------- /packages/charts/docs/tree-chart/basic.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "flare", 4 | "children": [ 5 | { 6 | "name": "穷游族", 7 | "children": [ 8 | { 9 | "name": "LonelyPlant" 10 | }, 11 | { 12 | "name": "daodao" 13 | }, 14 | { 15 | "name": "打折机票" 16 | }, 17 | { 18 | "name": "酒店促销" 19 | }, 20 | { 21 | "name": "优惠" 22 | } 23 | ] 24 | }, 25 | { 26 | "name": "婴儿幼儿产品" 27 | }, 28 | { 29 | "name": "教育" 30 | }, 31 | { 32 | "name": "新手妈妈" 33 | }, 34 | { 35 | "name": "都市白领" 36 | }, 37 | { 38 | "name": "健身" 39 | }, 40 | { 41 | "name": "AC追番" 42 | }, 43 | { 44 | "name": "HBO GO" 45 | }, 46 | { 47 | "name": "频道订阅" 48 | }, 49 | { 50 | "name": "明星粉丝团" 51 | } 52 | ] 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /packages/charts/docs/tree-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 树状图 3 | --- 4 | 5 | # TreeChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { TreeChart } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ; 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/charts/docs/treemap-chart/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 矩形树图 3 | --- 4 | 5 | # TreemapChart 6 | 7 | ## 基础用例 8 | 9 | ```jsx 10 | import React from 'react'; 11 | import { TreemapChart } from '@rsuite/charts'; 12 | import data from './basic.json'; 13 | 14 | export default () => ; 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/charts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@rsuite/charts", 3 | "version": "5.2.3", 4 | "description": "ECharts for React", 5 | "files": [ 6 | "dist" 7 | ], 8 | "main": "./dist/index.js", 9 | "module": "./dist/esm/index.js", 10 | "exports": { 11 | "require": "./dist/index.js", 12 | "import": "./dist/esm/index.js" 13 | }, 14 | "types": "./dist/index.d.ts", 15 | "dependencies": { 16 | "echarts-for-react": "^3.0.2", 17 | "echarts-theme-rsuite": "^1.0.0", 18 | "lodash.merge": "^4.6.2", 19 | "lodash.omit": "^4.5.0", 20 | "react-keyed-flatten-children": "^1.2.0" 21 | }, 22 | "devDependencies": { 23 | "@types/react": "^16.9.6", 24 | "echarts": "^5.0.0" 25 | }, 26 | "peerDependencies": { 27 | "echarts": "^5.0.0", 28 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0" 29 | }, 30 | "author": "Doma ", 31 | "license": "MIT", 32 | "repository": { 33 | "type": "git", 34 | "url": "https:git@github.com:rsuite/charts.git", 35 | "directory": "packages/charts" 36 | }, 37 | "scripts": { 38 | "dev": "cross-env dumi dev", 39 | "build": "tsup src/index.ts", 40 | "build-docs": "cross-env dumi build" 41 | }, 42 | "homepage": "https://github.com/rsuite/charts" 43 | } 44 | -------------------------------------------------------------------------------- /packages/charts/src/ECharts.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import ECharts from './ECharts'; 4 | 5 | describe('Empty state', () => { 6 | test('renders empty message when data is empty', () => { 7 | render( 8 |
9 | 10 |
11 | ); 12 | 13 | expect(screen.getByTestId('chart')).toHaveTextContent(/no data found/i); 14 | }); 15 | 16 | test('dont render empty message when chart is loading', () => { 17 | render( 18 |
19 | 20 |
21 | ); 22 | 23 | expect(screen.getByTestId('chart')).not.toHaveTextContent(/no data found/i); 24 | }); 25 | 26 | test('Renders custom message specified by `locale.emptyMessage`', () => { 27 | render( 28 |
29 | 30 |
31 | ); 32 | 33 | expect(screen.getByTestId('chart')).toHaveTextContent('没有数据'); 34 | }); 35 | 36 | test('Renders custom placeholder specified by `renderEmptyPlaceholder`', () => { 37 | render( 38 |
39 |
没有数据
} /> 40 |
41 | ); 42 | 43 | expect(screen.getByTestId('chart')).toHaveTextContent('没有数据'); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /packages/charts/src/ECharts.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useContext, useImperativeHandle, useMemo, useRef } from 'react'; 2 | import _merge from 'lodash.merge'; 3 | import ReactEchartsCore from 'echarts-for-react/lib/core'; 4 | import type { EChartsReactProps } from 'echarts-for-react'; 5 | import * as echarts from 'echarts/core'; 6 | import type { ECharts as EChartsInstance, EChartsOption, SeriesOption } from 'echarts'; 7 | import { CanvasRenderer } from 'echarts/renderers'; 8 | import { createEChartsOptionFromChildren, isDataEmpty } from './utils'; 9 | import * as themes from 'echarts-theme-rsuite'; 10 | import { ReactComponent as IconChartNoData } from './assets/chart-nodata.svg'; 11 | import { EChartsContext } from './constants'; 12 | 13 | echarts.use([CanvasRenderer]); 14 | 15 | echarts.registerTheme('rsuite_light', themes.light); 16 | echarts.registerTheme('rsuite_dark', themes.dark); 17 | 18 | const styles: { 19 | [key: string]: React.CSSProperties; 20 | } = { 21 | blockCenter: { 22 | width: '100%', 23 | height: '100%', 24 | display: 'flex', 25 | flexDirection: 'column', 26 | alignItems: 'center', 27 | justifyContent: 'center', 28 | color: '#8e8e93', 29 | fontSize: 14, 30 | fontWeight: 'normal', 31 | lineHeight: '20px', 32 | }, 33 | loaderWrap: { 34 | position: 'absolute', 35 | top: 0, 36 | left: 0, 37 | backgroundColor: 'rgba(255, 255, 255, 0.9)', 38 | }, 39 | }; 40 | 41 | const defaultOption = { 42 | grid: { 43 | containLabel: true, 44 | }, 45 | }; 46 | 47 | export interface EChartsProps extends Omit { 48 | height?: number; 49 | loading?: boolean; 50 | option?: EChartsOption; 51 | locale?: { 52 | emptyMessage?: React.ReactNode; 53 | loading?: React.ReactNode; 54 | }; 55 | 56 | /** 57 | * Customize the placeholder when chart data is empty 58 | */ 59 | renderEmptyPlaceholder?: () => React.ReactNode; 60 | children?: React.ReactNode; 61 | } 62 | 63 | export interface ChartComponentProps extends EChartsProps { 64 | name?: SeriesOption['name']; 65 | data?: DataType; 66 | } 67 | 68 | // ECharts with empty message and loading 69 | function ECharts( 70 | { 71 | height = 300, 72 | locale = { 73 | emptyMessage: 'No data found', 74 | loading: 'Loading...', 75 | }, 76 | option = {}, 77 | children, 78 | renderEmptyPlaceholder, 79 | ...props 80 | }: EChartsProps, 81 | ref: React.Ref 82 | ) { 83 | const echartsRef = useRef(); 84 | 85 | useImperativeHandle(ref, () => echartsRef.current as EChartsInstance); 86 | 87 | const context = useContext(EChartsContext); 88 | 89 | const renderEmptyMessage = useCallback(() => { 90 | if (typeof renderEmptyPlaceholder !== 'undefined') { 91 | return renderEmptyPlaceholder(); 92 | } 93 | 94 | return ( 95 |
96 | 97 | {locale.emptyMessage} 98 |
99 | ); 100 | }, [renderEmptyPlaceholder, locale]); 101 | 102 | const renderLoader = useCallback(() => { 103 | return ( 104 |
108 | {locale.loading} 109 |
110 | ); 111 | }, [locale]); 112 | 113 | const onChartReady = useCallback((echarts: EChartsInstance) => { 114 | echartsRef.current = echarts; 115 | }, []); 116 | 117 | const { className, style, loading, ...echartsForReactProps } = props; 118 | 119 | const echartsOption = useMemo(() => { 120 | /** 121 | * option 覆盖优先级 122 | * 1. defaultOption 为底 123 | * 2. props.option 124 | * 3. state.option (components 的 props) 125 | */ 126 | return children 127 | ? _merge({}, defaultOption, option, createEChartsOptionFromChildren(children, context)) 128 | : option; 129 | }, [children, context, option]); 130 | 131 | const dataEmpty = isDataEmpty(echartsOption); 132 | 133 | return ( 134 |
138 | {!loading && dataEmpty && renderEmptyMessage()} 139 | 148 | {children} 149 | {loading && renderLoader()} 150 |
151 | ); 152 | } 153 | 154 | if (process.env.NODE_ENV !== 'production') { 155 | ECharts.displayName = 'ECharts'; 156 | } 157 | 158 | export default React.forwardRef(ECharts); 159 | -------------------------------------------------------------------------------- /packages/charts/src/assets/chart-nodata.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/charts/src/charts/BarChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children, cloneElement } from 'react'; 2 | import ECharts, { ChartComponentProps } from '../ECharts'; 3 | import XAxis from '../components/XAxis'; 4 | import YAxis from '../components/YAxis'; 5 | import Legend from '../components/Legend'; 6 | import Tooltip from '../components/Tooltip'; 7 | import Bars from '../series/Bars'; 8 | import { is, isSeries } from '../utils'; 9 | import { EChartsContext } from '../constants'; 10 | 11 | const categoryAxisProps: any = { 12 | type: 'category', 13 | splitLine: false, 14 | }; 15 | 16 | const valueAxisProps: any = { 17 | type: 'value', 18 | }; 19 | 20 | interface BarChartProps extends ChartComponentProps<[category: string, ...values: number[]][]> { 21 | horizontal?: boolean; 22 | tooltip?: boolean; 23 | xAxis?: boolean; 24 | yAxis?: boolean; 25 | legend?: boolean; 26 | } 27 | 28 | /** 29 | * 30 | * 31 | * 32 | * 33 | * 34 | * 35 | * 36 | */ 37 | function BarChart( 38 | { 39 | name, 40 | data: inputData = [], 41 | tooltip = true, 42 | xAxis = true, 43 | yAxis = true, 44 | horizontal = false, 45 | legend = true, 46 | children, 47 | ...props 48 | }: BarChartProps, 49 | ref: any 50 | ) { 51 | function renderDefaultCategoryAxis() { 52 | const data = horizontal ? [...inputData!].reverse() : inputData; 53 | const categories = data!.map(([category]) => category); 54 | 55 | return horizontal ? ( 56 | 57 | ) : ( 58 | 59 | ); 60 | } 61 | 62 | function renderDefaultValueAxis() { 63 | return horizontal ? ( 64 | 65 | ) : ( 66 | 67 | ); 68 | } 69 | 70 | function renderDefaultSeries() { 71 | // 水平图表从上往下阅读则需将 data 翻转过来 72 | const data = horizontal ? [...inputData!].reverse() : inputData!; 73 | const values = data.map((d) => d[1]); 74 | 75 | return ; 76 | } 77 | 78 | const components = Children.toArray(children) as React.ReactElement[]; 79 | const series = components.filter(isSeries); 80 | 81 | const data = horizontal ? [...inputData!].reverse() : inputData; 82 | 83 | const categoryAxis = horizontal 84 | ? components.find((comp: any) => is(comp, 'yAxis')) 85 | : components.find((comp: any) => is(comp, 'xAxis')); 86 | 87 | const valueAxis = horizontal 88 | ? components.find((comp: any) => is(comp, 'xAxis')) 89 | : components.find((comp: any) => is(comp, 'yAxis')); 90 | 91 | return ( 92 | 93 | 94 | {!categoryAxis && renderDefaultCategoryAxis()} 95 | {!valueAxis && renderDefaultValueAxis()} 96 | {!components.find((comp: any) => is(comp, 'bars')) && renderDefaultSeries()} 97 | {legend && !components.find((comp: any) => is(comp, 'legend')) && } 98 | {tooltip && } 99 | {components.map((child: any) => { 100 | if (child.type === (horizontal ? YAxis : XAxis)) { 101 | return cloneElement(child, { 102 | ...categoryAxisProps, 103 | data: child.props.data || data!.map(([category]) => category), 104 | }); 105 | } 106 | if (child.type === (horizontal ? XAxis : YAxis)) { 107 | return cloneElement(child, valueAxisProps); 108 | } 109 | if (data!.length && isSeries(child) && !child.props.data) { 110 | const serieIndex = series.indexOf(child); 111 | return cloneElement(child, { data: data!.map((d) => d[serieIndex + 1]) }); 112 | } 113 | return child; 114 | })} 115 | 116 | 117 | ); 118 | } 119 | 120 | export default React.forwardRef(BarChart); 121 | -------------------------------------------------------------------------------- /packages/charts/src/charts/FunnelChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children, Fragment, cloneElement } from 'react'; 2 | import _merge from 'lodash.merge'; 3 | import ECharts, { ChartComponentProps } from '../ECharts'; 4 | import Tooltip from '../components/Tooltip'; 5 | import Funnel, { FunnelProps } from '../series/Funnel'; 6 | import Legend from '../components/Legend'; 7 | import { EChartsContext } from '../constants'; 8 | import { is } from '../utils'; 9 | 10 | const funnelDefaultWidth = 40; 11 | 12 | export interface FunnelChartProps extends ChartComponentProps { 13 | asc?: boolean; 14 | tooltip?: boolean; 15 | } 16 | 17 | function FunnelChart( 18 | { asc = false, tooltip = true, name, data = [], children, option, ...props }: FunnelChartProps, 19 | ref: any 20 | ) { 21 | const components = Children.toArray(children) as React.ReactElement[]; 22 | const funnels = components.filter((comp) => is(comp, 'funnel')); 23 | const legends = components.filter((comp) => is(comp, 'legend')); 24 | const withoutLegend = legends.length === 0; 25 | 26 | function renderDefaultFunnel() { 27 | const funnelPosition = { 28 | width: `${funnelDefaultWidth}%`, 29 | left: `${(100 - funnelDefaultWidth) / 2}%`, 30 | }; 31 | 32 | return ( 33 | 34 | 35 | {withoutLegend && name)} />} 36 | 37 | ); 38 | } 39 | 40 | function renderFunnels(funnels: any[]) { 41 | // 2 个以内给排排版 42 | if (funnels.length === 1) { 43 | const funnelPosition = { 44 | width: `${funnelDefaultWidth}%`, 45 | left: `${(100 - funnelDefaultWidth) / 2}%`, 46 | }; 47 | return funnels.map((funnel, index) => ( 48 | 49 | {cloneElement(funnel, { ...funnelPosition, ...funnel.props })} 50 | {withoutLegend && name)} />} 51 | 52 | )); 53 | } 54 | 55 | const occupiedColorsCount = (index: number) => 56 | funnels.slice(0, index).reduce((sum, funnel) => sum + funnel.props.data.length, 0); 57 | 58 | if (funnels.length === 2) { 59 | return funnels.map((funnel: any, index: number) => { 60 | const funnelPosition = { 61 | width: `${funnelDefaultWidth}%`, 62 | left: `${5 + 50 * index}%`, 63 | }; 64 | return ( 65 | 66 | {cloneElement(funnel, { 67 | ...funnelPosition, 68 | color: 69 | funnel.props.color && 70 | new Array(occupiedColorsCount(index)).concat(funnel.props.color), 71 | ...funnel.props, 72 | })} 73 | {withoutLegend && ( 74 | name)} 76 | {...(funnelPosition as any)} 77 | /> 78 | )} 79 | 80 | ); 81 | }); 82 | } 83 | 84 | return funnels.map((funnel: any, index: number) => ( 85 | 86 | {cloneElement(funnel, { 87 | color: 88 | funnel.props.color && new Array(occupiedColorsCount(index)).concat(funnel.props.color), 89 | })} 90 | {withoutLegend && name)} />} 91 | 92 | )); 93 | } 94 | 95 | let titleOption = {}; 96 | if (!funnels.length) { 97 | titleOption = { 98 | title: { 99 | text: name, 100 | left: '50%', 101 | top: '10%', 102 | textAlign: 'center', 103 | textVerticalAlign: 'bottom', 104 | textStyle: { color: '#272c36', fontSize: 14, fontWeight: 'normal' }, 105 | }, 106 | }; 107 | } 108 | if (funnels.length <= 2) { 109 | titleOption = { 110 | title: funnels.map((funnel: any, index) => ({ 111 | text: funnel.props.name, 112 | left: `${funnels.length === 1 ? 50 : 5 + funnelDefaultWidth / 2 + index * 50}%`, 113 | top: '10%', 114 | textAlign: 'center', 115 | textVerticalAlign: 'bottom', 116 | textStyle: { color: '#272c36', fontSize: 14, fontWeight: 'normal' }, 117 | })), 118 | }; 119 | } 120 | 121 | return ( 122 | 123 | 124 | {!funnels.length && renderDefaultFunnel()} 125 | {funnels.length > 0 && renderFunnels(funnels)} 126 | {tooltip && } 127 | {components.filter((comp) => !is(comp, 'funnel'))} 128 | 129 | 130 | ); 131 | } 132 | 133 | export default React.forwardRef(FunnelChart); 134 | -------------------------------------------------------------------------------- /packages/charts/src/charts/LineChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children, cloneElement } from 'react'; 2 | import ECharts, { ChartComponentProps } from '../ECharts'; 3 | import Line from '../series/Line'; 4 | import XAxis from '../components/XAxis'; 5 | import YAxis from '../components/YAxis'; 6 | import Legend from '../components/Legend'; 7 | import { is, isSeries } from '../utils'; 8 | import Tooltip from '../components/Tooltip'; 9 | import { EChartsContext } from '../constants'; 10 | 11 | export interface LineChartProps 12 | extends ChartComponentProps<[category: string, ...values: number[]][]> { 13 | tooltip?: boolean; 14 | } 15 | 16 | /** 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | */ 25 | function LineChart( 26 | { name, data = [], tooltip = true, children, ...props }: LineChartProps, 27 | ref: any 28 | ) { 29 | function renderDefaultXAxis() { 30 | return category) } as any)} />; 31 | } 32 | 33 | function renderDefaultLine() { 34 | return d[1])} />; 35 | } 36 | 37 | const components = Children.toArray(children) as React.ReactElement[]; 38 | const series = components.filter(isSeries); 39 | 40 | return ( 41 | 42 | 43 | {!components.find((comp) => is(comp, 'xAxis')) && renderDefaultXAxis()} 44 | {!components.find((comp) => is(comp, 'yAxis')) && } 45 | {!components.find((comp) => is(comp, 'line')) && renderDefaultLine()} 46 | {tooltip && } 47 | {!components.find((comp) => is(comp, 'legend')) && } 48 | {components.map((child: any) => { 49 | if (data.length && isSeries(child) && !child.props.data) { 50 | const serieIndex = series.indexOf(child); 51 | return cloneElement(child, { data: data.map((d) => d[serieIndex + 1]) }); 52 | } 53 | return child; 54 | })} 55 | 56 | 57 | ); 58 | } 59 | 60 | export default React.forwardRef(LineChart); 61 | -------------------------------------------------------------------------------- /packages/charts/src/charts/MapChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children } from 'react'; 2 | import _merge from 'lodash.merge'; 3 | import ECharts, { ChartComponentProps } from '../ECharts'; 4 | import Tooltip from '../components/Tooltip'; 5 | import Map, { MapProps } from '../series/Map'; 6 | import VisualMap from '../components/VisualMap'; 7 | import { EChartsContext } from '../constants'; 8 | import { is } from '../utils'; 9 | 10 | const mapVisualMapColors = [ 11 | 'rgb(8, 132, 204)', 12 | 'rgba(8, 132, 204, .8)', 13 | 'rgba(8, 132, 204, .6)', 14 | 'rgba(8, 132, 204, .4)', 15 | 'rgba(8, 132, 204, .3)', 16 | ]; 17 | 18 | interface MapChartProps 19 | extends ChartComponentProps, 20 | Omit { 21 | visualMap?: boolean; 22 | } 23 | 24 | function MapChart( 25 | { name, data = [], visualMap: shouldShowVisualMap = true, children, ...props }: MapChartProps, 26 | ref: any 27 | ) { 28 | function renderDefaultMap() { 29 | return ; 30 | } 31 | 32 | const components = Children.toArray(children) as React.ReactElement[]; 33 | 34 | const compVisualMap = components.find((comp) => is(comp, 'visualMap')); 35 | 36 | const visualMapProps: any = { 37 | show: shouldShowVisualMap !== false, 38 | type: 'piecewise', 39 | inRange: { 40 | color: [...mapVisualMapColors].reverse(), 41 | }, 42 | controller: { 43 | symbol: 'rect', 44 | }, 45 | }; 46 | 47 | const map = components.find((comp) => is(comp, 'map')); 48 | 49 | return ( 50 | 51 | 52 | 53 | {!compVisualMap && } 54 | {!map && renderDefaultMap()} 55 | {components.map((child: any) => { 56 | if (child.type === VisualMap) { 57 | return React.cloneElement(child, _merge(visualMapProps, child.props)); 58 | } 59 | return child; 60 | })} 61 | 62 | 63 | ); 64 | } 65 | 66 | export default React.forwardRef(MapChart); 67 | -------------------------------------------------------------------------------- /packages/charts/src/charts/PieChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children } from 'react'; 2 | import ECharts, { ChartComponentProps } from '../ECharts'; 3 | import Pie, { PieProps } from '../series/Pie'; 4 | import Tooltip from '../components/Tooltip'; 5 | import Legend from '../components/Legend'; 6 | import { EChartsContext } from '../constants'; 7 | import { is } from '../utils'; 8 | 9 | export interface PieChartProps 10 | extends ChartComponentProps, 11 | Omit { 12 | legend?: boolean; 13 | } 14 | 15 | function PieChart({ data = [], legend = true, children, ...props }: PieChartProps, ref: any) { 16 | const components = Children.toArray(children) as React.ReactElement[]; 17 | 18 | function getPieData() { 19 | return (data as any).map(([name, value]: any) => ({ name, value })); 20 | } 21 | 22 | return ( 23 | 24 | 25 | {legend === true && !components.some((comp) => is(comp, 'legend')) && } 26 | {!components.some((comp) => is(comp, 'tooltip')) && } 27 | {!components.some((comp) => is(comp, 'pie')) && } 28 | {children} 29 | 30 | 31 | ); 32 | } 33 | 34 | export default React.forwardRef(PieChart); 35 | -------------------------------------------------------------------------------- /packages/charts/src/charts/RadarChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children, cloneElement } from 'react'; 2 | import type { ECharts as EChartsInstance } from 'echarts'; 3 | import ECharts, { ChartComponentProps } from '../ECharts'; 4 | import Tooltip from '../components/Tooltip'; 5 | import Legend from '../components/Legend'; 6 | import Radar from '../components/Radar'; 7 | import RadarLine from '../series/RadarLine'; 8 | import { is, isSeries } from '../utils'; 9 | import { EChartsContext } from '../constants'; 10 | 11 | export interface RadarChartProps 12 | extends ChartComponentProps<[name: string, max: number, ...values: number[]][]> { 13 | tooltip?: boolean; 14 | legend?: boolean; 15 | } 16 | 17 | function RadarChart( 18 | { name, data = [], tooltip = true, legend = true, children, ...props }: RadarChartProps, 19 | ref: React.Ref 20 | ) { 21 | function renderDefaultRadar() { 22 | const indicator = data.map(([name, max]) => ({ name, max })); 23 | 24 | return ; 25 | } 26 | 27 | function renderDefaultRadarLine() { 28 | return value)} />; 29 | } 30 | 31 | const components = Children.toArray(children) as React.ReactElement[]; 32 | const series = components.filter(isSeries); 33 | 34 | return ( 35 | 36 | 37 | {!components.find((comp) => is(comp, 'radar')) && renderDefaultRadar()} 38 | {!components.find((comp) => is(comp, 'radarLine')) && renderDefaultRadarLine()} 39 | {tooltip && } 40 | {legend && } 41 | {components.map((child) => { 42 | if (data.length && isSeries(child) && !child.props.data) { 43 | const serieIndex = series.indexOf(child); 44 | return cloneElement(child, { data: data.map((d) => d[serieIndex + 2]) }); 45 | } 46 | return child; 47 | })} 48 | 49 | 50 | ); 51 | } 52 | 53 | if (process.env.NODE_ENV !== 'production') { 54 | RadarChart.displayName = 'RadarChart'; 55 | } 56 | 57 | export default React.forwardRef(RadarChart); 58 | -------------------------------------------------------------------------------- /packages/charts/src/charts/SankeyChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children } from 'react'; 2 | import type { ECharts as EChartsInstance } from 'echarts'; 3 | import ECharts, { ChartComponentProps } from '../ECharts'; 4 | import Tooltip from '../components/Tooltip'; 5 | import Sankey, { SankeyProps } from '../series/Sankey'; 6 | import { EChartsContext } from '../constants'; 7 | import { is } from '../utils'; 8 | 9 | export interface SankeyChartProps extends ChartComponentProps {} 10 | 11 | function SankeyChart( 12 | { name, data = [], children, ...props }: SankeyChartProps, 13 | ref: React.Ref 14 | ) { 15 | function renderDefaultSankey() { 16 | return ; 17 | } 18 | 19 | const components = Children.toArray(children) as React.ReactElement[]; 20 | 21 | const sankey = components.find((comp) => is(comp, 'sankey')); 22 | 23 | return ( 24 | 25 | 26 | 27 | {!sankey && renderDefaultSankey()} 28 | {children} 29 | 30 | 31 | ); 32 | } 33 | 34 | export default React.forwardRef(SankeyChart); 35 | -------------------------------------------------------------------------------- /packages/charts/src/charts/ScatterChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children, cloneElement } from 'react'; 2 | import _merge from 'lodash.merge'; 3 | import type { ECharts as EChartsInstance } from 'echarts'; 4 | import ECharts, { ChartComponentProps } from '../ECharts'; 5 | import Tooltip from '../components/Tooltip'; 6 | import Legend from '../components/Legend'; 7 | import XAxis from '../components/XAxis'; 8 | import type { XAxisProps } from '../components/XAxis'; 9 | import YAxis from '../components/YAxis'; 10 | import type { YAxisProps } from '../components/YAxis'; 11 | import Scatter, { ScatterProps } from '../series/Scatter'; 12 | import { EChartsContext } from '../constants'; 13 | import { is } from '../utils'; 14 | 15 | const xAxisProps: XAxisProps = { 16 | axisLine: { 17 | symbol: ['none', 'arrow'], 18 | symbolSize: [9, 9], 19 | }, 20 | nameLocation: 'middle', 21 | nameGap: 25, 22 | nameTextStyle: { 23 | fontSize: 14, 24 | color: '#272c36', 25 | }, 26 | }; 27 | 28 | const yAxisProps: YAxisProps = { 29 | axisLine: { 30 | show: true, 31 | symbol: ['none', 'arrow'], 32 | symbolSize: [9, 9], 33 | }, 34 | splitLine: false, 35 | nameLocation: 'middle', 36 | nameGap: 35, 37 | nameTextStyle: { 38 | fontSize: 14, 39 | lineHeight: 20, 40 | color: '#272c36', 41 | }, 42 | }; 43 | 44 | export interface ScatterChartProps extends ChartComponentProps { 45 | tooltip?: boolean; 46 | legend?: boolean; 47 | } 48 | 49 | function ScatterChart( 50 | { name, data = [], tooltip = true, legend = true, children, ...props }: ScatterChartProps, 51 | ref: React.Ref 52 | ) { 53 | function renderDefaultScatter() { 54 | return ; 55 | } 56 | 57 | const components = Children.toArray(children) as React.ReactElement[]; 58 | 59 | return ( 60 | 61 | 62 | {!components.find((comp) => is(comp, 'xAxis')) && } 63 | {!components.find((comp) => is(comp, 'yAxis')) && } 64 | {!components.find((comp) => is(comp, 'scatter')) && renderDefaultScatter()} 65 | {tooltip && } 66 | {legend && } 67 | {components.map((child) => { 68 | if (is(child, 'xAxis')) { 69 | return cloneElement(child, _merge(xAxisProps, child.props)); 70 | } 71 | if (is(child, 'yAxis')) { 72 | return cloneElement(child, _merge(yAxisProps, child.props)); 73 | } 74 | return child; 75 | })} 76 | 77 | 78 | ); 79 | } 80 | 81 | export default React.forwardRef(ScatterChart); 82 | -------------------------------------------------------------------------------- /packages/charts/src/charts/TreeChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children } from 'react'; 2 | import type { TreeSeriesOption } from 'echarts'; 3 | import ECharts, { ChartComponentProps } from '../ECharts'; 4 | import Tooltip from '../components/Tooltip'; 5 | import Tree from '../series/Tree'; 6 | import { EChartsContext } from '../constants'; 7 | import { is } from '../utils'; 8 | 9 | type TreeProps = TreeSeriesOption; 10 | export interface TreeChartProps extends ChartComponentProps {} 11 | 12 | function TreeChart({ data = [], children, ...props }: TreeChartProps, ref: any) { 13 | function renderDefaultTree() { 14 | return ; 15 | } 16 | 17 | const components = Children.toArray(children) as React.ReactElement[]; 18 | 19 | const tree = components.find((comp) => is(comp, 'tree')); 20 | 21 | return ( 22 | 23 | 24 | 25 | {!tree && renderDefaultTree()} 26 | {children} 27 | 28 | 29 | ); 30 | } 31 | 32 | export default React.forwardRef(TreeChart); 33 | -------------------------------------------------------------------------------- /packages/charts/src/charts/TreemapChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { Children } from 'react'; 2 | import type { ECharts as EChartsInstance, TooltipComponentOption } from 'echarts'; 3 | import ECharts, { ChartComponentProps } from '../ECharts'; 4 | import Tooltip from '../components/Tooltip'; 5 | import VisualMap from '../components/VisualMap'; 6 | import Treemap, { TreemapProps } from '../series/Treemap'; 7 | import { EChartsContext } from '../constants'; 8 | import { is } from '../utils'; 9 | 10 | export interface TreemapChartProps extends ChartComponentProps {} 11 | 12 | const treemapTooltipFormatter = ({ seriesName, name, value }) => 13 | `${name}
${seriesName}: ${value}`; 14 | 15 | function TreemapChart( 16 | { name, data = [], children, ...props }: TreemapChartProps, 17 | ref: React.Ref 18 | ) { 19 | function renderDefaultTreemap() { 20 | return ; 21 | } 22 | 23 | const components = Children.toArray(children) as React.ReactElement[]; 24 | 25 | const treemap = components.find((comp) => is(comp, 'treemap')); 26 | 27 | return ( 28 | 29 | 30 | 31 | 32 | {!treemap && renderDefaultTreemap()} 33 | {children} 34 | 35 | 36 | ); 37 | } 38 | 39 | export default React.forwardRef(TreemapChart); 40 | -------------------------------------------------------------------------------- /packages/charts/src/components/DataZoom.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import DataZoom from './DataZoom'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into dataZoom option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('dataZoom'); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/components/DataZoom.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { DataZoomComponent, DataZoomComponentOption } from 'echarts/components'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([DataZoomComponent]); 8 | 9 | export type DataZoomProps = DataZoomComponentOption; 10 | 11 | const DataZoom: OptionComponent = (_: DataZoomProps) => null; 12 | 13 | DataZoom[symbols.typeKey] = symbols.dataZoom; 14 | 15 | DataZoom.tapEChartsOption = (option, props) => { 16 | function getOption() { 17 | return _merge( 18 | { 19 | type: 'slider', 20 | }, 21 | props 22 | ); 23 | } 24 | 25 | const dataZoomOption = getOption(); 26 | 27 | if (!option.dataZoom) { 28 | option.dataZoom = dataZoomOption; 29 | } else if (!Array.isArray(option.dataZoom)) { 30 | option.dataZoom = [option.dataZoom, dataZoomOption]; 31 | } else { 32 | option.dataZoom.push(dataZoomOption); 33 | } 34 | }; 35 | 36 | if (process.env.NODE_ENV !== 'production') { 37 | DataZoom.displayName = 'DataZoom'; 38 | } 39 | 40 | export default DataZoom; 41 | -------------------------------------------------------------------------------- /packages/charts/src/components/Dataset.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Dataset from './Dataset'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into dataset option', () => { 7 | const source = [ 8 | ['product', '2015', '2016', '2017'], 9 | ['Matcha Latte', 43.3, 85.8, 93.7], 10 | ['Milk Tea', 83.1, 73.4, 55.1], 11 | ['Cheese Cocoa', 86.4, 65.2, 82.5], 12 | ['Walnut Brownie', 72.4, 53.9, 39.1], 13 | ]; 14 | expect( 15 | createEChartsOptionFromChildren( 16 | ( 17 | <> 18 | 19 | 20 | ).props.children, 21 | {} 22 | ) 23 | ).toHaveProperty('dataset', { 24 | source, 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/charts/src/components/Dataset.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { DatasetComponent, DatasetComponentOption } from 'echarts/components'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([DatasetComponent]); 8 | 9 | export type DatasetProps = DatasetComponentOption; 10 | 11 | const Dataset: OptionComponent = (_: DatasetProps) => null; 12 | 13 | Dataset[symbols.typeKey] = symbols.dataset; 14 | 15 | Dataset.tapEChartsOption = (option, props) => { 16 | option.dataset = _merge({}, props); 17 | }; 18 | 19 | if (process.env.NODE_ENV !== 'production') { 20 | Dataset.displayName = 'Dataset'; 21 | } 22 | 23 | export default Dataset; 24 | -------------------------------------------------------------------------------- /packages/charts/src/components/Legend.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Legend from './Legend'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into legend option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('legend'); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/components/Legend.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { LegendComponent, LegendComponentOption } from 'echarts/components'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | import { EChartsOption } from 'echarts'; 7 | 8 | echarts.use([LegendComponent]); 9 | 10 | export type LegendProps = LegendComponentOption; 11 | 12 | const Legend: OptionComponent = (_: LegendProps) => null; 13 | 14 | Legend[symbols.typeKey] = symbols.legend; 15 | 16 | Legend.tapEChartsOption = (option, props, context) => { 17 | function getOption(): LegendComponentOption { 18 | const { chartType } = context; 19 | const legendOption: LegendComponentOption = { 20 | show: true, 21 | bottom: 10, 22 | }; 23 | 24 | if (chartType === 'pie') { 25 | legendOption.icon = 'circle'; 26 | } 27 | return _merge(legendOption, props); 28 | } 29 | 30 | const legendOption = getOption(); 31 | 32 | if (!option.legend) { 33 | option.legend = legendOption as EChartsOption['legend']; 34 | } else if (!Array.isArray(option.legend)) { 35 | option.legend = [option.legend, legendOption] as EChartsOption['legend']; 36 | } else { 37 | (option.legend as LegendComponentOption[]).push(legendOption); 38 | } 39 | }; 40 | 41 | if (process.env.NODE_ENV !== 'production') { 42 | Legend.displayName = 'Legend'; 43 | } 44 | 45 | export default Legend; 46 | -------------------------------------------------------------------------------- /packages/charts/src/components/Radar.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Radar from './Radar'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into radar option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('radar'); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/components/Radar.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { RadarComponent, RadarComponentOption } from 'echarts/components'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([RadarComponent]); 8 | 9 | export type RadarProps = RadarComponentOption & { 10 | circle?: boolean; 11 | }; 12 | 13 | const Radar: OptionComponent = () => null; 14 | 15 | Radar[symbols.typeKey] = symbols.radar; 16 | 17 | Radar.tapEChartsOption = (option, props) => { 18 | function getOption() { 19 | const { circle = false, ...rest } = props; 20 | 21 | return _merge( 22 | { 23 | axisName: { 24 | color: '#575757', 25 | }, 26 | axisNameGap: 10, 27 | shape: circle ? 'circle' : 'polygon', 28 | 29 | splitArea: { 30 | areaStyle: { 31 | color: ['#FFFFFF', '#F7F7FA'], 32 | }, 33 | }, 34 | }, 35 | rest 36 | ); 37 | } 38 | 39 | const radarOption = getOption(); 40 | 41 | if (!option.radar) { 42 | option.radar = radarOption; 43 | } else if (!Array.isArray(option.radar)) { 44 | option.radar = [option.radar, radarOption]; 45 | } else { 46 | option.radar.push(radarOption); 47 | } 48 | }; 49 | 50 | if (process.env.NODE_ENV !== 'production') { 51 | Radar.displayName = 'Radar'; 52 | } 53 | 54 | export default Radar; 55 | -------------------------------------------------------------------------------- /packages/charts/src/components/Tooltip.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Tooltip from './Tooltip'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into tooltip option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('tooltip'); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/components/Tooltip.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { TooltipComponent, TooltipComponentOption } from 'echarts/components'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | import { EChartsOption } from 'echarts'; 7 | 8 | echarts.use([TooltipComponent]); 9 | 10 | export type TooltipProps = TooltipComponentOption; 11 | 12 | const Tooltip: OptionComponent = (_: TooltipProps) => null; 13 | 14 | Tooltip[symbols.typeKey] = symbols.tooltip; 15 | 16 | Tooltip.tapEChartsOption = (option, props, context) => { 17 | function getOption(): TooltipComponentOption { 18 | const { chartType, series } = context; 19 | 20 | const hasAxis = 21 | chartType === 'bar' || 22 | chartType === 'line' || 23 | !!series.find( 24 | (comp: any) => 25 | comp.type[symbols.typeKey] === symbols.xAxis || 26 | comp.type[symbols.typeKey] === symbols.yAxis 27 | ); 28 | 29 | return _merge( 30 | { 31 | show: true, 32 | trigger: hasAxis ? 'axis' : 'item', 33 | axisPointer: { 34 | type: 'none', 35 | }, 36 | }, 37 | props 38 | ); 39 | } 40 | 41 | option.tooltip = getOption() as EChartsOption['tooltip']; 42 | }; 43 | 44 | if (process.env.NODE_ENV !== 'production') { 45 | Tooltip.displayName = 'Tooltip'; 46 | } 47 | 48 | export default Tooltip; 49 | -------------------------------------------------------------------------------- /packages/charts/src/components/VisualMap.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import VisualMap from './VisualMap'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into visualMap option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('visualMap'); 17 | }); 18 | 19 | test('Should not tap visualMap.max when chartData is empty', () => { 20 | expect( 21 | createEChartsOptionFromChildren( 22 | ( 23 | <> 24 | 25 | 26 | ).props.children, 27 | { chartData: [] } 28 | ).visualMap 29 | ).not.toHaveProperty('max'); 30 | }); 31 | -------------------------------------------------------------------------------- /packages/charts/src/components/VisualMap.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { VisualMapComponent, VisualMapComponentOption } from 'echarts/components'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([VisualMapComponent]); 8 | 9 | export type VisualMapProps = VisualMapComponentOption; 10 | 11 | const VisualMap: OptionComponent = (_: VisualMapProps) => null; 12 | 13 | VisualMap[symbols.typeKey] = symbols.visualMap; 14 | 15 | VisualMap.tapEChartsOption = (option, props, context) => { 16 | function getComponentOption() { 17 | const { type = 'continuous', ...rest } = props; 18 | const { chartData } = context; 19 | 20 | let inRange: any = { 21 | colorHue: [198, 199], 22 | colorSaturation: [1, 1], 23 | colorLightness: [0.88, 0.451], 24 | }; 25 | 26 | if (type === 'piecewise') { 27 | inRange = { 28 | symbol: 'rect', 29 | }; 30 | } 31 | 32 | const visualMapOption = _merge( 33 | { 34 | type, 35 | left: 0, 36 | bottom: 0, 37 | text: ['最大值', '最小值'], 38 | textGap: 5, 39 | orient: 'horizontal', 40 | inverse: true, 41 | min: 0, 42 | 43 | itemGap: 1, 44 | symbolSize: [18, 14], 45 | textStyle: { 46 | color: '#8e8e93', 47 | }, 48 | inRange, 49 | }, 50 | rest 51 | ); 52 | 53 | if (chartData && (chartData as number[]).length > 0 && !visualMapOption.max) { 54 | visualMapOption.max = (chartData as number[]).reduce( 55 | (max, d) => Math.max(max, d[1]), 56 | -Infinity 57 | ); 58 | } 59 | 60 | return visualMapOption; 61 | } 62 | 63 | option.visualMap = getComponentOption(); 64 | }; 65 | if (process.env.NODE_ENV !== 'production') { 66 | VisualMap.displayName = 'VisualMap'; 67 | } 68 | 69 | export default VisualMap; 70 | -------------------------------------------------------------------------------- /packages/charts/src/components/XAxis.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import XAxis from './XAxis'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into xAxis option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('xAxis'); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/components/XAxis.ts: -------------------------------------------------------------------------------- 1 | import type { EChartsOption, XAXisComponentOption } from 'echarts'; 2 | import _merge from 'lodash.merge'; 3 | import { symbols } from '../constants'; 4 | import { AxisLabelFormatter, OptionComponent } from '../types'; 5 | import { transformTextOption } from '../utils'; 6 | 7 | export type XAxisProps = Omit & { 8 | axisLine?: XAXisComponentOption['axisLine'] | boolean; 9 | axisLabel?: XAXisComponentOption['axisLabel'] | boolean | AxisLabelFormatter; 10 | splitLine?: XAXisComponentOption['splitLine'] | boolean; 11 | }; 12 | 13 | const XAxis: OptionComponent = () => null; 14 | 15 | XAxis[symbols.typeKey] = symbols.xAxis; 16 | 17 | XAxis.tapEChartsOption = (option, props, context) => { 18 | function getOption(): XAXisComponentOption { 19 | const { axisLabel, axisLine, splitLine, ...rest } = props; 20 | const { series } = context; 21 | 22 | return _merge( 23 | rest.type === 'category' 24 | ? { 25 | boundaryGap: !!series.find((comp) => comp.type[symbols.typeKey] === symbols.bars), 26 | } 27 | : {}, 28 | { 29 | nameTextStyle: { 30 | fontSize: 12, 31 | color: '#575757', 32 | }, 33 | }, 34 | axisLabel 35 | ? { 36 | axisLabel: transformTextOption(axisLabel), 37 | } 38 | : {}, 39 | typeof axisLine === 'boolean' 40 | ? { 41 | axisLine: { 42 | show: axisLine, 43 | }, 44 | } 45 | : axisLine, 46 | typeof splitLine === 'boolean' 47 | ? { 48 | splitLine: { 49 | show: splitLine, 50 | }, 51 | } 52 | : splitLine, 53 | rest 54 | ); 55 | } 56 | 57 | const xAxisOption = getOption(); 58 | 59 | if (!option.xAxis) { 60 | option.xAxis = xAxisOption as EChartsOption['xAxis']; 61 | } else if (!Array.isArray(option.xAxis)) { 62 | option.xAxis = [option.xAxis, xAxisOption] as EChartsOption['xAxis']; 63 | } else { 64 | (option.xAxis as XAXisComponentOption[]).push(xAxisOption); 65 | } 66 | }; 67 | 68 | if (process.env.NODE_ENV !== 'production') { 69 | XAxis.displayName = 'XAxis'; 70 | } 71 | 72 | export default XAxis; 73 | -------------------------------------------------------------------------------- /packages/charts/src/components/YAxis.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import YAxis from './YAxis'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into yAxis option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('yAxis'); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/components/YAxis.ts: -------------------------------------------------------------------------------- 1 | import type { EChartsOption, YAXisComponentOption } from 'echarts'; 2 | import _merge from 'lodash.merge'; 3 | import { symbols } from '../constants'; 4 | import { AxisLabelFormatter, OptionComponent } from '../types'; 5 | import { transformTextOption } from '../utils'; 6 | 7 | export type YAxisProps = Omit & { 8 | axisLine?: YAXisComponentOption['axisLine'] | boolean; 9 | axisLabel?: YAXisComponentOption['axisLabel'] | boolean | AxisLabelFormatter; 10 | splitLine?: YAXisComponentOption['splitLine'] | boolean; 11 | 12 | /** 13 | * When nameLocation="middle", 14 | * whether to transpose the axis name text into vertical direction. 15 | * 16 | * @default false 17 | */ 18 | transposeNameText?: boolean; 19 | }; 20 | 21 | const YAxis: OptionComponent = (_: YAxisProps) => null; 22 | 23 | YAxis.defaultProps = { 24 | show: true, 25 | type: 'value', 26 | }; 27 | YAxis[symbols.typeKey] = symbols.yAxis; 28 | 29 | YAxis.tapEChartsOption = (option, props) => { 30 | function getOption(): YAXisComponentOption { 31 | const { name, axisLabel, axisLine, splitLine, transposeNameText = false, ...rest } = props; 32 | 33 | return _merge( 34 | { 35 | name, 36 | nameTextStyle: { 37 | fontSize: 12, 38 | color: '#575757', 39 | }, 40 | }, 41 | name && rest.nameLocation === 'middle' && transposeNameText 42 | ? { 43 | nameRotate: 0, 44 | name: name.split('').join('\n'), 45 | } 46 | : {}, 47 | typeof axisLine === 'boolean' 48 | ? { 49 | axisLine: { 50 | show: axisLine, 51 | }, 52 | } 53 | : axisLine, 54 | typeof splitLine !== 'undefined' 55 | ? { 56 | splitLine: _merge( 57 | { 58 | show: !!splitLine, 59 | }, 60 | typeof splitLine !== 'boolean' && splitLine 61 | ), 62 | } 63 | : {}, 64 | axisLabel 65 | ? { 66 | axisLabel: transformTextOption(axisLabel), 67 | } 68 | : {}, 69 | rest 70 | ); 71 | } 72 | 73 | const yAxisOption = getOption(); 74 | 75 | if (!option.yAxis) { 76 | option.yAxis = yAxisOption as EChartsOption['yAxis']; 77 | } else if (!Array.isArray(option.yAxis)) { 78 | option.yAxis = [option.yAxis, yAxisOption] as EChartsOption['yAxis']; 79 | } else { 80 | (option.yAxis as YAXisComponentOption[]).push(yAxisOption); 81 | } 82 | }; 83 | 84 | if (process.env.NODE_ENV !== 'production') { 85 | YAxis.displayName = 'YAxis'; 86 | } 87 | 88 | export default YAxis; 89 | -------------------------------------------------------------------------------- /packages/charts/src/constants.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | interface EChartsContext { 4 | [key: string]: unknown; 5 | } 6 | 7 | export const EChartsContext = React.createContext({}); 8 | 9 | export const symbols = { 10 | typeKey: Symbol.for('$$typeKey'), 11 | // components 12 | dataset: Symbol.for('$$dataset'), 13 | dataZoom: Symbol.for('$$dataZoom'), 14 | legend: Symbol.for('$$legend'), 15 | radar: Symbol.for('$$radar'), 16 | tooltip: Symbol.for('$$tooltip'), 17 | visualMap: Symbol.for('$$visualMap'), 18 | xAxis: Symbol.for('$$xAxis'), 19 | yAxis: Symbol.for('$$yAxis'), 20 | 21 | // series 22 | bars: Symbol.for('$$bars'), 23 | funnel: Symbol.for('$$funnel'), 24 | line: Symbol.for('$$line'), 25 | map: Symbol.for('$$map'), 26 | pie: Symbol.for('$$pie'), 27 | radarLine: Symbol.for('$$radarLine'), 28 | sankey: Symbol.for('$$sankey'), 29 | scatter: Symbol.for('$$scatter'), 30 | tree: Symbol.for('$$tree'), 31 | treemap: Symbol.for('$$treemap'), 32 | }; 33 | 34 | (symbols as any).components = [ 35 | symbols.dataZoom, 36 | symbols.legend, 37 | symbols.radar, 38 | symbols.tooltip, 39 | symbols.visualMap, 40 | symbols.xAxis, 41 | symbols.yAxis, 42 | ]; 43 | 44 | (symbols as any).series = [ 45 | symbols.bars, 46 | symbols.funnel, 47 | symbols.line, 48 | symbols.map, 49 | symbols.pie, 50 | symbols.radarLine, 51 | symbols.sankey, 52 | symbols.scatter, 53 | symbols.tree, 54 | symbols.treemap, 55 | ]; 56 | -------------------------------------------------------------------------------- /packages/charts/src/index.ts: -------------------------------------------------------------------------------- 1 | import ECharts from './ECharts'; 2 | 3 | // Components 4 | import Dataset from './components/Dataset'; 5 | import DataZoom from './components/DataZoom'; 6 | import Legend from './components/Legend'; 7 | import Radar from './components/Radar'; 8 | import Tooltip from './components/Tooltip'; 9 | import VisualMap from './components/VisualMap'; 10 | import XAxis from './components/XAxis'; 11 | import YAxis from './components/YAxis'; 12 | 13 | // Series 14 | import Bars from './series/Bars'; 15 | import Funnel from './series/Funnel'; 16 | import Line from './series/Line'; 17 | import Map from './series/Map'; 18 | import Pie from './series/Pie'; 19 | import RadarLine from './series/RadarLine'; 20 | import Sankey from './series/Sankey'; 21 | import Scatter from './series/Scatter'; 22 | import Tree from './series/Tree'; 23 | import Treemap from './series/Treemap'; 24 | 25 | // Chart presets 26 | import BarChart from './charts/BarChart'; 27 | import FunnelChart from './charts/FunnelChart'; 28 | import LineChart from './charts/LineChart'; 29 | import MapChart from './charts/MapChart'; 30 | import PieChart from './charts/PieChart'; 31 | import RadarChart from './charts/RadarChart'; 32 | import SankeyChart from './charts/SankeyChart'; 33 | import ScatterChart from './charts/ScatterChart'; 34 | import TreeChart from './charts/TreeChart'; 35 | import TreemapChart from './charts/TreemapChart'; 36 | 37 | export default ECharts; 38 | 39 | export { Dataset, DataZoom, Legend, Radar, Tooltip, VisualMap, XAxis, YAxis }; 40 | 41 | export { Bars, Funnel, Line, Map, Pie, RadarLine, Sankey, Scatter, Tree, Treemap }; 42 | 43 | export { 44 | BarChart, 45 | FunnelChart, 46 | LineChart, 47 | MapChart, 48 | PieChart, 49 | RadarChart, 50 | SankeyChart, 51 | ScatterChart, 52 | TreeChart, 53 | TreemapChart, 54 | }; 55 | -------------------------------------------------------------------------------- /packages/charts/src/series/Bars.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Bars from './Bars'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-bar option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'bar' })])); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/series/Bars.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { BarChart, BarSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import type { OptionComponent } from '../types'; 6 | import { randstr, transformTextOption } from '../utils'; 7 | 8 | echarts.use([BarChart]); 9 | 10 | type BarsProps = Omit & { 11 | color?: string | string[]; 12 | stack?: string | true; 13 | }; 14 | 15 | const Bars: OptionComponent = () => null; 16 | 17 | const defaultBarsStackKey = randstr(); 18 | 19 | Bars[symbols.typeKey] = symbols.bars; 20 | Bars.tapEChartsOption = (option, props, context) => { 21 | function getSeriesOption(): BarSeriesOption { 22 | const { stack, color, label, ...rest } = props; 23 | const { chartType, horizontal, series } = context; 24 | 25 | const barsSeriesCount = series.filter( 26 | (comp: any) => comp.type[symbols.typeKey] === symbols.bars 27 | ).length; 28 | const stackedBars = stack 29 | ? series.filter( 30 | (comp: any) => comp.type[symbols.typeKey] === symbols.bars && comp.props.stack === stack 31 | ) 32 | : []; 33 | const stacked = stackedBars.length > 1; 34 | const stackTop = 35 | stackedBars.findIndex( 36 | (comp: any) => comp.type[symbols.typeKey] === symbols.bars && comp.props.name === rest.name 37 | ) === 38 | stackedBars.length - 1; 39 | 40 | let borderRadius; 41 | if (stacked && !stackTop) { 42 | borderRadius = 0; 43 | } else { 44 | borderRadius = chartType === 'bar' && horizontal ? [0, 5, 5, 0] : [5, 5, 0, 0]; 45 | } 46 | 47 | return _merge( 48 | { 49 | type: 'bar', 50 | barWidth: (!stack && barsSeriesCount) > 1 ? 6 : 20, 51 | stack: typeof stack === 'boolean' ? defaultBarsStackKey : stack, 52 | itemStyle: { 53 | color: Array.isArray(color) ? ({ dataIndex }: any) => color[dataIndex] : color, 54 | borderRadius, 55 | }, 56 | // 默认 label 57 | // 位置:top,水平则 right 58 | label: transformTextOption(label, { 59 | position: horizontal ? 'right' : 'top', 60 | }), 61 | } as const, 62 | rest 63 | ); 64 | } 65 | 66 | if (!option.series) { 67 | option.series = []; 68 | } 69 | 70 | (option.series as BarSeriesOption[]).push(getSeriesOption()); 71 | }; 72 | 73 | if (process.env.NODE_ENV !== 'production') { 74 | Bars.displayName = 'Bars'; 75 | } 76 | 77 | export default Bars; 78 | -------------------------------------------------------------------------------- /packages/charts/src/series/Funnel.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Funnel from './Funnel'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-funnel option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'funnel' })])); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/series/Funnel.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { FunnelChart, FunnelSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | import { transformTextOption } from '../utils'; 7 | 8 | echarts.use([FunnelChart]); 9 | 10 | export interface FunnelProps extends Omit { 11 | asc?: boolean; 12 | } 13 | 14 | const Funnel: OptionComponent = (_: FunnelProps) => null; 15 | 16 | Funnel.defaultProps = { 17 | asc: false, 18 | }; 19 | 20 | Funnel[symbols.typeKey] = symbols.funnel; 21 | 22 | Funnel.tapEChartsOption = (option, props) => { 23 | function getSeriesOption(): FunnelSeriesOption { 24 | const { data, asc, sort = asc ? 'ascending' : 'descending', label, ...rest } = props; 25 | 26 | return _merge( 27 | { 28 | type: 'funnel' as const, 29 | data: data 30 | ?.map(([name, value]: any) => ({ 31 | name, 32 | value, 33 | })) 34 | .sort((d1: any, d2: any) => d2.value - d1.value), 35 | sort, 36 | label: transformTextOption(label, { 37 | show: true, 38 | position: 'inside', 39 | formatter: ({ value }: any) => value, 40 | fontSize: 14, 41 | }), 42 | }, 43 | rest 44 | ); 45 | } 46 | 47 | if (!option.series) { 48 | option.series = []; 49 | } 50 | 51 | (option.series as FunnelSeriesOption[]).push(getSeriesOption()); 52 | }; 53 | 54 | if (process.env.NODE_ENV !== 'production') { 55 | Funnel.displayName = 'Funnel'; 56 | } 57 | 58 | export default Funnel; 59 | -------------------------------------------------------------------------------- /packages/charts/src/series/Line.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Line from './Line'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-line option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'line' })])); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/series/Line.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { LineChart, LineSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import type { OptionComponent } from '../types'; 6 | import { randstr } from '../utils'; 7 | 8 | echarts.use([LineChart]); 9 | 10 | export type LineProps = Omit & { 11 | stack?: string | boolean; 12 | area?: boolean; 13 | }; 14 | 15 | const Line: OptionComponent = (_: LineProps) => null; 16 | 17 | Line[symbols.typeKey] = symbols.line; 18 | 19 | const defaultLineStackKey = randstr(); 20 | 21 | Line.tapEChartsOption = (option, props) => { 22 | function getSeriesOption(): LineSeriesOption { 23 | const { stack, area, ...rest } = props; 24 | 25 | return _merge( 26 | { 27 | type: 'line', 28 | symbol: 'none', 29 | stack: typeof stack === 'boolean' ? defaultLineStackKey : stack, 30 | areaStyle: area && { opacity: stack ? 0.6 : 0.2 }, 31 | } as const, 32 | rest 33 | ); 34 | } 35 | 36 | if (!option.series) { 37 | option.series = []; 38 | } 39 | 40 | (option.series as LineSeriesOption[]).push(getSeriesOption()); 41 | }; 42 | 43 | if (process.env.NODE_ENV !== 'production') { 44 | Line.displayName = 'Line'; 45 | } 46 | 47 | export default Line; 48 | -------------------------------------------------------------------------------- /packages/charts/src/series/Map.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Map from './Map'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-map option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty( 17 | 'series', 18 | expect.arrayContaining([expect.objectContaining({ type: 'map', map: 'china' })]) 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/charts/src/series/Map.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { MapChart, MapSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([MapChart]); 8 | 9 | export type MapProps = Omit; 10 | 11 | const Map: OptionComponent = (_: MapProps) => null; 12 | 13 | Map[symbols.typeKey] = symbols.map; 14 | Map.tapEChartsOption = (option, props) => { 15 | function getSeriesOption(): MapSeriesOption { 16 | const { map, name, data, nameMap, ...rest } = props; 17 | 18 | return _merge( 19 | { 20 | type: 'map' as const, 21 | map, 22 | name, 23 | data: data?.map(([name, value]: any) => ({ 24 | name: (nameMap && nameMap[name]) || name, 25 | value, 26 | })), 27 | itemStyle: { 28 | areaColor: '#E5E5EA', 29 | borderColor: '#ffffff', 30 | borderWidth: 1, 31 | }, 32 | label: { 33 | fontSize: 10, 34 | }, 35 | emphasis: { 36 | label: { 37 | color: 'rgb(131, 56, 236)', 38 | }, 39 | itemStyle: { 40 | areaColor: 'rgba(131, 56, 236, .3)', 41 | borderColor: 'rgb(131, 56, 236)', 42 | }, 43 | }, 44 | nameMap, 45 | }, 46 | rest 47 | ); 48 | } 49 | 50 | if (!option.series) { 51 | option.series = []; 52 | } 53 | 54 | (option.series as MapSeriesOption[]).push(getSeriesOption()); 55 | }; 56 | 57 | if (process.env.NODE_ENV !== 'production') { 58 | Map.displayName = 'Map'; 59 | } 60 | 61 | export default Map; 62 | -------------------------------------------------------------------------------- /packages/charts/src/series/Pie.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Pie, { composeRadiusOption } from './Pie'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-line option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'pie' })])); 17 | }); 18 | 19 | describe('composeRadiusOption', () => { 20 | test("Return radiusProp when it's an array", () => { 21 | const radiusProp = ['50%', '100%']; 22 | 23 | expect(composeRadiusOption(radiusProp)).toEqual(radiusProp); 24 | }); 25 | 26 | test('Returns 80% when radiusProp not specified', () => { 27 | expect(composeRadiusOption(undefined)).toEqual('80%'); 28 | }); 29 | 30 | test('Returns radius percentage', () => { 31 | expect(composeRadiusOption(60)).toEqual('60%'); 32 | expect(composeRadiusOption('60%')).toEqual('60%'); 33 | }); 34 | 35 | test('Returns innerRadius and outerRadius with difference by 15', () => { 36 | expect(composeRadiusOption(75, true)).toEqual(['60%', '75%']); 37 | expect(composeRadiusOption('75%', true)).toEqual(['60%', '75%']); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/charts/src/series/Pie.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { PieChart, PieSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | import { transformTextOption } from '../utils'; 7 | 8 | echarts.use([PieChart]); 9 | 10 | export interface PieProps extends Omit { 11 | donut?: boolean; 12 | } 13 | 14 | const Pie: OptionComponent = (_: PieProps) => null; 15 | 16 | Pie.defaultProps = { 17 | data: [], 18 | donut: false, 19 | }; 20 | 21 | Pie[symbols.typeKey] = symbols.pie; 22 | 23 | Pie.tapEChartsOption = (option, props) => { 24 | function getSeriesOption(): PieSeriesOption { 25 | const { radius, donut, label, ...rest } = props; 26 | 27 | const pieOption: PieSeriesOption = _merge( 28 | { 29 | type: 'pie', 30 | radius: composeRadiusOption(radius, donut), 31 | center: ['50%', '50%'], 32 | } as const, 33 | rest 34 | ); 35 | 36 | if (label !== undefined) { 37 | pieOption.label = transformTextOption(label); 38 | } 39 | 40 | return pieOption; 41 | } 42 | 43 | if (!option.series) { 44 | option.series = []; 45 | } 46 | 47 | (option.series as PieSeriesOption[]).push(getSeriesOption()); 48 | }; 49 | 50 | if (process.env.NODE_ENV !== 'production') { 51 | Pie.displayName = 'Pie'; 52 | } 53 | 54 | export default Pie; 55 | 56 | export function composeRadiusOption( 57 | radiusProp: PieProps['radius'], 58 | donutProp?: boolean 59 | ): PieSeriesOption['radius'] { 60 | if (Array.isArray(radiusProp)) return radiusProp; 61 | 62 | let outerRadius = 80; 63 | 64 | if (typeof radiusProp === 'string') { 65 | outerRadius = parseFloat(radiusProp) || 80; 66 | } else if (typeof radiusProp === 'number') { 67 | outerRadius = radiusProp; 68 | } 69 | 70 | const innerRadius = outerRadius - 15; 71 | 72 | return donutProp ? [`${innerRadius}%`, `${outerRadius}%`] : `${outerRadius}%`; 73 | } 74 | -------------------------------------------------------------------------------- /packages/charts/src/series/RadarLine.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import RadarLine from './RadarLine'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-radar option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'radar' })])); 17 | }); 18 | 19 | test('Multiple s transform into a single series-bar option', () => { 20 | expect( 21 | createEChartsOptionFromChildren( 22 | ( 23 | <> 24 | 25 | 26 | 27 | ).props.children, 28 | {} 29 | ).series 30 | ).toHaveLength(1); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/charts/src/series/RadarLine.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { RadarChart, RadarSeriesOption } from 'echarts/charts'; 3 | import { symbols } from '../constants'; 4 | import { OptionComponent } from '../types'; 5 | 6 | echarts.use([RadarChart]); 7 | 8 | export type RadarLineProps = Omit & { 9 | data?: number[]; 10 | }; 11 | 12 | /** 13 | * TODO Consider deprecate this component as it can be only used within RadarChart 14 | */ 15 | const RadarLine: OptionComponent = (_: RadarLineProps) => null; 16 | 17 | RadarLine[symbols.typeKey] = symbols.radarLine; 18 | 19 | RadarLine.tapEChartsOption = (option, props) => { 20 | const { name, data } = props; 21 | 22 | if (!option.series) { 23 | option.series = []; 24 | } 25 | 26 | let radarSerieOption: RadarSeriesOption | undefined = ( 27 | option.series as RadarSeriesOption[] 28 | )?.find((series) => series.type === 'radar'); 29 | 30 | if (!radarSerieOption) { 31 | radarSerieOption = { 32 | type: 'radar', 33 | symbol: 'none', 34 | lineStyle: { 35 | width: 2, 36 | }, 37 | emphasis: { 38 | lineStyle: { 39 | width: 3, 40 | }, 41 | areaStyle: { 42 | opacity: 0.2, 43 | }, 44 | }, 45 | data: [], 46 | }; 47 | 48 | (option.series as RadarSeriesOption[]).push(radarSerieOption); 49 | } 50 | 51 | if (!radarSerieOption.data) { 52 | radarSerieOption.data = []; 53 | } 54 | 55 | radarSerieOption.data.push({ 56 | name, 57 | value: data, 58 | }); 59 | }; 60 | 61 | if (process.env.NODE_ENV !== 'production') { 62 | RadarLine.displayName = 'RadarLine'; 63 | } 64 | 65 | export default RadarLine; 66 | -------------------------------------------------------------------------------- /packages/charts/src/series/Sankey.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Sankey from './Sankey'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-sankey option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'sankey' })])); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/series/Sankey.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { SankeyChart, SankeySeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([SankeyChart]); 8 | 9 | export type SankeyProps = SankeySeriesOption; 10 | 11 | const Sankey: OptionComponent = (_: SankeyProps) => null; 12 | 13 | Sankey[symbols.typeKey] = symbols.sankey; 14 | 15 | Sankey.tapEChartsOption = (option, props) => { 16 | function getSeriesOption(): SankeySeriesOption { 17 | return _merge( 18 | { 19 | type: 'sankey', 20 | nodeWidth: 30, 21 | nodeGap: 20, 22 | itemStyle: { 23 | borderWidth: 0, 24 | }, 25 | lineStyle: { 26 | color: '#cfcfcf', 27 | curveness: 0.5, 28 | }, 29 | }, 30 | props 31 | ); 32 | } 33 | 34 | if (!option.series) { 35 | option.series = []; 36 | } 37 | 38 | (option.series as SankeySeriesOption[]).push(getSeriesOption()); 39 | }; 40 | 41 | if (process.env.NODE_ENV !== 'production') { 42 | Sankey.displayName = 'Sankey'; 43 | } 44 | 45 | export default Sankey; 46 | -------------------------------------------------------------------------------- /packages/charts/src/series/Scatter.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Scatter from './Scatter'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-scatter option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty( 17 | 'series', 18 | expect.arrayContaining([expect.objectContaining({ type: 'scatter' })]) 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/charts/src/series/Scatter.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { ScatterChart, ScatterSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([ScatterChart]); 8 | 9 | export type ScatterProps = Omit; 10 | 11 | const Scatter: OptionComponent = (_: ScatterProps) => null; 12 | 13 | Scatter[symbols.typeKey] = symbols.scatter; 14 | 15 | Scatter.tapEChartsOption = (option, props, context) => { 16 | function getSeriesOption(): ScatterSeriesOption { 17 | const { ...rest } = props; 18 | 19 | const { chartType } = context; 20 | 21 | return _merge( 22 | { 23 | type: 'scatter', 24 | symbol: chartType === 'bar' ? 'emptyCircle' : 'circle', 25 | symbolSize: 9, 26 | itemStyle: { 27 | opacity: chartType === 'bar' ? 1 : 0.7, 28 | }, 29 | emphasis: { 30 | itemStyle: { 31 | opacity: 1, 32 | }, 33 | }, 34 | } as const, 35 | rest 36 | ); 37 | } 38 | 39 | if (!option.series) { 40 | option.series = []; 41 | } 42 | 43 | (option.series as ScatterSeriesOption[]).push(getSeriesOption()); 44 | }; 45 | 46 | if (process.env.NODE_ENV !== 'production') { 47 | Scatter.displayName = 'Scatter'; 48 | } 49 | 50 | export default Scatter; 51 | -------------------------------------------------------------------------------- /packages/charts/src/series/Tree.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Tree from './Tree'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-tree option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty('series', expect.arrayContaining([expect.objectContaining({ type: 'tree' })])); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/charts/src/series/Tree.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { TreeChart, TreeSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([TreeChart]); 8 | 9 | export type TreeProps = TreeSeriesOption; 10 | 11 | const Tree: OptionComponent = (_: TreeProps) => null; 12 | 13 | Tree.defaultProps = { 14 | data: [], 15 | }; 16 | 17 | Tree[symbols.typeKey] = symbols.tree; 18 | 19 | Tree.tapEChartsOption = (option, props) => { 20 | function getSeriesOption(): TreeSeriesOption { 21 | const { name, data, ...rest } = props; 22 | 23 | return _merge( 24 | { 25 | type: 'tree', 26 | name, 27 | data, 28 | symbolSize: 8, 29 | itemStyle: { 30 | color: '#34c3ff', 31 | borderColor: '#34c3ff', 32 | borderWidth: 2, 33 | }, 34 | label: { 35 | position: 'left', 36 | verticalAlign: 'middle', 37 | align: 'right', 38 | }, 39 | 40 | leaves: { 41 | label: { 42 | position: 'right', 43 | verticalAlign: 'middle', 44 | align: 'left', 45 | }, 46 | }, 47 | }, 48 | rest 49 | ); 50 | } 51 | 52 | if (!option.series) { 53 | option.series = []; 54 | } 55 | 56 | (option.series as TreeSeriesOption[]).push(getSeriesOption()); 57 | }; 58 | 59 | if (process.env.NODE_ENV !== 'production') { 60 | Tree.displayName = 'Tree'; 61 | } 62 | 63 | export default Tree; 64 | -------------------------------------------------------------------------------- /packages/charts/src/series/Treemap.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Treemap from './Treemap'; 4 | import { createEChartsOptionFromChildren } from '../utils'; 5 | 6 | test('Transforms into series-treemap option', () => { 7 | expect( 8 | createEChartsOptionFromChildren( 9 | ( 10 | <> 11 | 12 | 13 | ).props.children, 14 | {} 15 | ) 16 | ).toHaveProperty( 17 | 'series', 18 | expect.arrayContaining([expect.objectContaining({ type: 'treemap' })]) 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/charts/src/series/Treemap.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | import { TreemapChart, TreemapSeriesOption } from 'echarts/charts'; 3 | import _merge from 'lodash.merge'; 4 | import { symbols } from '../constants'; 5 | import { OptionComponent } from '../types'; 6 | 7 | echarts.use([TreemapChart]); 8 | 9 | export type TreemapProps = TreemapSeriesOption; 10 | 11 | const Treemap: OptionComponent = () => null; 12 | 13 | Treemap.defaultProps = { 14 | data: [], 15 | }; 16 | Treemap[symbols.typeKey] = symbols.treemap; 17 | 18 | Treemap.tapEChartsOption = (option, props) => { 19 | function transformData(node: NonNullable[0]) { 20 | if (!node) { 21 | return node; 22 | } 23 | if (!Array.isArray(node)) { 24 | return node; 25 | } 26 | const [name, value, children] = node; 27 | return { 28 | name, 29 | value, 30 | children: children && children.map(transformData), 31 | }; 32 | } 33 | 34 | function getSeriesOption(): TreemapSeriesOption { 35 | const { data, ...rest } = props; 36 | 37 | return _merge( 38 | { 39 | type: 'treemap', 40 | data: data?.map(transformData), 41 | itemStyle: { 42 | areaColor: '#BEDBED', 43 | borderColor: '#ffffff', 44 | borderWidth: 1, 45 | }, 46 | visibleMin: 300, 47 | leafDepth: 1, 48 | drillDownIcon: null, 49 | label: { 50 | position: 'insideTopLeft', 51 | color: '#ffffff', 52 | fontSize: 12, 53 | lineHeight: 17, 54 | formatter({ name, value }) { 55 | return `{a|${name}\n${value}}`; 56 | }, 57 | rich: { 58 | a: { 59 | color: '#ffffff', 60 | fontSize: 12, 61 | lineHeight: 17, 62 | }, 63 | }, 64 | }, 65 | levels: [ 66 | { 67 | itemStyle: { 68 | borderColor: '#fff', 69 | borderWidth: 1, 70 | gapWidth: 1, 71 | }, 72 | }, 73 | ], 74 | }, 75 | rest 76 | ); 77 | } 78 | 79 | if (!option.series) { 80 | option.series = []; 81 | } 82 | 83 | (option.series as TreemapSeriesOption[]).push(getSeriesOption()); 84 | }; 85 | if (process.env.NODE_ENV !== 'production') { 86 | Treemap.displayName = 'Treemap'; 87 | } 88 | 89 | export default Treemap; 90 | -------------------------------------------------------------------------------- /packages/charts/src/svgr.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | import * as React from 'react'; 3 | 4 | export const ReactComponent: React.FunctionComponent< 5 | React.ComponentProps<'svg'> & { title?: string } 6 | >; 7 | } 8 | -------------------------------------------------------------------------------- /packages/charts/src/types.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import type { EChartsOption } from 'echarts'; 3 | 4 | export type AxisLabelFormatter = (value: string | number) => string; 5 | 6 | export type OptionComponent

= React.ComponentType

& { 7 | tapEChartsOption( 8 | option: EChartsOption, 9 | props: P, 10 | context: { 11 | [key: string]: unknown; 12 | series: React.ReactElement[]; 13 | } 14 | ); 15 | }; 16 | -------------------------------------------------------------------------------- /packages/charts/src/utils.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _merge from 'lodash.merge'; 3 | import _omit from 'lodash.omit'; 4 | import flattenChildren from 'react-keyed-flatten-children'; 5 | import type { DatasetComponentOption, EChartsOption, SeriesOption } from 'echarts'; 6 | import * as echarts from 'echarts/core'; 7 | import { TitleComponent } from 'echarts/components'; 8 | import { symbols } from './constants'; 9 | import { ChartComponentProps } from './ECharts'; 10 | import type { OptionComponent } from './types'; 11 | 12 | echarts.use([TitleComponent]); 13 | 14 | export function is(element: React.ReactElement, name: string): boolean { 15 | return element.type[symbols.typeKey] === Symbol.for(`$$${name}`); 16 | } 17 | 18 | export function isSeries(element: React.ReactElement) { 19 | return (symbols as any).series.includes(element.type[symbols.typeKey]); 20 | } 21 | 22 | export function transformTextOption(option: any, defaultOption?: any) { 23 | if (option === undefined || option === true) { 24 | return defaultOption; 25 | } 26 | if (option === false) { 27 | return { show: false }; 28 | } 29 | if (typeof option === 'function') { 30 | return { 31 | ...defaultOption, 32 | show: true, 33 | formatter: option, 34 | }; 35 | } 36 | if (typeof option === 'object') { 37 | return _merge( 38 | { 39 | ...defaultOption, 40 | show: true, 41 | }, 42 | option 43 | ); 44 | } 45 | return { 46 | ...defaultOption, 47 | show: true, 48 | formatter() { 49 | return option; 50 | }, 51 | }; 52 | } 53 | 54 | export function randstr(length = 16) { 55 | let text = ''; 56 | const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 57 | 58 | for (let i = 0; i < length; i += 1) { 59 | text += possible.charAt(Math.floor(Math.random() * possible.length)); 60 | } 61 | 62 | return text; 63 | } 64 | 65 | export function excludeEchartsProps(props: ChartComponentProps) { 66 | return _omit(props, ['option', 'locale', 'height', 'loading']); 67 | } 68 | 69 | export function createEChartsOptionFromChildren( 70 | children: React.ReactNode, 71 | _: Record 72 | ): EChartsOption { 73 | const option = {}; 74 | 75 | const validChildren = flattenChildren(children).filter((child) => 76 | React.isValidElement(child) 77 | ) as React.ReactElement[]; 78 | 79 | const series = validChildren.filter((child) => { 80 | return (symbols as any).series.includes(child.type[symbols.typeKey]); 81 | }); 82 | 83 | const context = { 84 | ..._, 85 | series, 86 | }; 87 | 88 | validChildren.forEach((child) => { 89 | // 处理 child 的 props 90 | // 根据 child 的 type 上的 symbol 91 | (child.type as OptionComponent).tapEChartsOption?.( 92 | option, 93 | excludeEchartsProps(child.props), 94 | context 95 | ); 96 | }); 97 | 98 | return option; 99 | } 100 | 101 | /** 102 | * 判断 option 是否没有数据, 103 | * 用于显示数据为空的 placeholder 104 | */ 105 | export function isDataEmpty(option: EChartsOption) { 106 | if (option.dataset) { 107 | return isDatasetEmpty(option.dataset as DatasetComponentOption); 108 | } 109 | 110 | return isSeriesEmpty(option.series); 111 | } 112 | 113 | /** 114 | * 进入此方法时一定存在 option.dataset 115 | */ 116 | function isDatasetEmpty(dataset: DatasetComponentOption) { 117 | if (!dataset.source) { 118 | return true; 119 | } 120 | 121 | if (Array.isArray(dataset.source)) { 122 | return dataset.source.length < 1; 123 | } 124 | 125 | return Object.getOwnPropertyNames(dataset.source).length < 1; 126 | } 127 | 128 | function isSeriesEmpty(series: EChartsOption['series']) { 129 | return ( 130 | !series || 131 | (series as SeriesOption[]).every((serie) => { 132 | if (serie.type === 'sankey') { 133 | return (!serie.nodes || serie.nodes.length < 1) && (!serie.data || serie.data.length < 1); 134 | } 135 | 136 | return !serie.data || (serie.data as unknown[]).length < 1; 137 | }) 138 | ); 139 | } 140 | -------------------------------------------------------------------------------- /packages/charts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/charts/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | import svgrPlugin from 'esbuild-plugin-svgr'; 3 | 4 | export default defineConfig({ 5 | format: ['cjs', 'esm'], 6 | clean: true, 7 | dts: true, 8 | legacyOutput: true, 9 | esbuildPlugins: [ 10 | svgrPlugin({ 11 | exportType: 'named', 12 | }), 13 | ], 14 | }); 15 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # echarts-theme-rsuite 2 | 3 | ## 1.0.0 4 | 5 | ### Major Changes 6 | 7 | - d247c45: Separate echarts-theme-rsuite as a standalone package 8 | 9 | ## 0.0.0-beta.0 10 | 11 | ### Major Changes 12 | 13 | - d247c45: Separate echarts-theme-rsuite as a standalone package 14 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/README.md: -------------------------------------------------------------------------------- 1 | # `echarts-theme-rsuite` 2 | 3 | React Suite theme for ECharts. 4 | 5 | npm i echarts-theme-rsuite 6 | 7 | ## Usage 8 | 9 | ```js 10 | import * as echarts from 'echarts'; 11 | import * as themes from 'echarts-theme-rsuite'; 12 | 13 | echarts.registerTheme('rsuite_light', themes.light); 14 | ``` 15 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "echarts-theme-rsuite", 3 | "version": "1.0.0", 4 | "description": "React Suite theme for ECharts", 5 | "files": [ 6 | "dist" 7 | ], 8 | "main": "./dist/index.js", 9 | "module": "./dist/esm/index.js", 10 | "exports": { 11 | "require": "./dist/index.js", 12 | "import": "./dist/esm/index.js" 13 | }, 14 | "types": "./dist/index.d.ts", 15 | "scripts": { 16 | "build": "tsup src/index.ts --clean --format cjs,esm --legacy-output --dts", 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/rsuite/charts.git", 22 | "directory": "packages/echarts-theme-rsuite" 23 | }, 24 | "author": "Doma ", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/rsuite/charts/issues" 28 | }, 29 | "homepage": "https://github.com/rsuite/charts#readme", 30 | "dependencies": { 31 | "lodash.merge": "^4.6.2" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/src/index.ts: -------------------------------------------------------------------------------- 1 | import light from './rsuite_light'; 2 | import dark from './rsuite_dark'; 3 | 4 | export { light, dark }; 5 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/src/rsuite_dark.project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "themeName": "rsuite_dark", 4 | "theme": { 5 | "seriesCnt": "7", 6 | "backgroundColor": "#1a1d24", 7 | "titleColor": "#ffffff", 8 | "subtitleColor": "#aaaaaa", 9 | "textColorShow": false, 10 | "textColor": "#333", 11 | "markTextColor": "#eeeeee", 12 | "color": [ 13 | "#34c3ff", 14 | "#a873e6", 15 | "#13ba9e", 16 | "#ee5765", 17 | "#f5a623", 18 | "#2575fc", 19 | "#df6ecd", 20 | "#8338ec", 21 | "#e6b980", 22 | "#51E8FF" 23 | ], 24 | "borderColor": "#cccccc", 25 | "borderWidth": 0, 26 | "visualMapColor": ["#c2edff", "#009de6"], 27 | "legendTextColor": "#8e8e93", 28 | "kColor": "#e01f54", 29 | "kColor0": "#001852", 30 | "kBorderColor": "#f5e8c8", 31 | "kBorderColor0": "#b8d2c7", 32 | "kBorderWidth": 1, 33 | "lineWidth": 2, 34 | "symbolSize": "0", 35 | "symbol": "circle", 36 | "symbolBorderWidth": "0", 37 | "lineSmooth": false, 38 | "graphLineWidth": 1, 39 | "graphLineColor": "#aaaaaa", 40 | "mapLabelColor": "#000000", 41 | "mapLabelColorE": "rgb(100,0,0)", 42 | "mapBorderColor": "#444444", 43 | "mapBorderColorE": "#444444", 44 | "mapBorderWidth": 0.5, 45 | "mapBorderWidthE": 1, 46 | "mapAreaColor": "#eeeeee", 47 | "mapAreaColorE": "rgba(255,215,0,0.8)", 48 | "axes": [ 49 | { 50 | "type": "all", 51 | "name": "通用坐标轴", 52 | "axisLineShow": true, 53 | "axisLineColor": "#e5e5ea", 54 | "axisTickShow": false, 55 | "axisTickColor": "#333", 56 | "axisLabelShow": true, 57 | "axisLabelColor": "#575757", 58 | "splitLineShow": true, 59 | "splitLineColor": ["#e5e5ea"], 60 | "splitAreaShow": false, 61 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 62 | }, 63 | { 64 | "type": "category", 65 | "name": "类目坐标轴", 66 | "axisLineShow": true, 67 | "axisLineColor": "#3c3f43", 68 | "axisTickShow": false, 69 | "axisTickColor": "#333", 70 | "axisLabelShow": true, 71 | "axisLabelColor": "#e9ebf0", 72 | "splitLineShow": false, 73 | "splitLineColor": ["#e5e5ea"], 74 | "splitAreaShow": false, 75 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 76 | }, 77 | { 78 | "type": "value", 79 | "name": "数值坐标轴", 80 | "axisLineShow": false, 81 | "axisLineColor": "#e5e5ea", 82 | "axisTickShow": false, 83 | "axisTickColor": "#8e8e93", 84 | "axisLabelShow": true, 85 | "axisLabelColor": "#e9ebf0", 86 | "splitLineShow": true, 87 | "splitLineColor": ["#3c3f43"], 88 | "splitAreaShow": false, 89 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 90 | }, 91 | { 92 | "type": "log", 93 | "name": "对数坐标轴", 94 | "axisLineShow": true, 95 | "axisLineColor": "#3c3f43", 96 | "axisTickShow": true, 97 | "axisTickColor": "#333", 98 | "axisLabelShow": true, 99 | "axisLabelColor": "#e9ebf0", 100 | "splitLineShow": true, 101 | "splitLineColor": ["#3c3f43"], 102 | "splitAreaShow": false, 103 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 104 | }, 105 | { 106 | "type": "time", 107 | "name": "时间坐标轴", 108 | "axisLineShow": true, 109 | "axisLineColor": "#3c3f43", 110 | "axisTickShow": true, 111 | "axisTickColor": "#333", 112 | "axisLabelShow": true, 113 | "axisLabelColor": "#e9ebf0", 114 | "splitLineShow": true, 115 | "splitLineColor": ["#3c3f43"], 116 | "splitAreaShow": false, 117 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 118 | } 119 | ], 120 | "axisSeperateSetting": true, 121 | "toolboxColor": "#999999", 122 | "toolboxEmpasisColor": "#666666", 123 | "tooltipAxisColor": "#cccccc", 124 | "tooltipAxisWidth": 1, 125 | "timelineLineColor": "#293c55", 126 | "timelineLineWidth": 1, 127 | "timelineItemColor": "#293c55", 128 | "timelineItemColorE": "#a9334c", 129 | "timelineCheckColor": "#e43c59", 130 | "timelineCheckBorderColor": "#c23531", 131 | "timelineItemBorderWidth": 1, 132 | "timelineControlColor": "#293c55", 133 | "timelineControlBorderColor": "#293c55", 134 | "timelineControlBorderWidth": 0.5, 135 | "timelineLabelColor": "#293c55", 136 | "datazoomBackgroundColor": "rgba(47,69,84,0)", 137 | "datazoomDataColor": "rgba(47,69,84,0.3)", 138 | "datazoomFillColor": "rgba(167,183,204,0.4)", 139 | "datazoomHandleColor": "#a7b7cc", 140 | "datazoomHandleWidth": "100", 141 | "datazoomLabelColor": "#333333" 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/src/rsuite_dark.ts: -------------------------------------------------------------------------------- 1 | import _merge from 'lodash.merge'; 2 | 3 | /** 4 | * DO NOT directly edit this theme object 5 | * If you need to edit the rsuite_dark theme, follow these steps: 6 | * 7 | * 1. Visit https://echarts.apache.org/zh/theme-builder.html 8 | * 2. Import rsuite_dark.project.json to the theme builder 9 | * 3. Make changes in the theme builder GUI 10 | * 4. Download (not export) the edited theme 11 | * 5. Replace the theme object with the latest theme JSON 12 | * 6. Export the edited theme and update rsuite_dark.project.json 13 | */ 14 | const theme = { 15 | color: [ 16 | '#34c3ff', 17 | '#a873e6', 18 | '#13ba9e', 19 | '#ee5765', 20 | '#f5a623', 21 | '#2575fc', 22 | '#df6ecd', 23 | '#8338ec', 24 | '#e6b980', 25 | '#51E8FF', 26 | ], 27 | backgroundColor: '#1a1d24', 28 | textStyle: {}, 29 | title: { 30 | textStyle: { 31 | color: '#ffffff', 32 | }, 33 | subtextStyle: { 34 | color: '#aaaaaa', 35 | }, 36 | }, 37 | line: { 38 | itemStyle: { 39 | borderWidth: '0', 40 | }, 41 | lineStyle: { 42 | width: 2, 43 | }, 44 | symbolSize: '0', 45 | symbol: 'circle', 46 | smooth: false, 47 | }, 48 | radar: { 49 | itemStyle: { 50 | borderWidth: '0', 51 | }, 52 | lineStyle: { 53 | width: 2, 54 | }, 55 | symbolSize: '0', 56 | symbol: 'circle', 57 | smooth: false, 58 | }, 59 | bar: { 60 | itemStyle: { 61 | barBorderWidth: 0, 62 | barBorderColor: '#cccccc', 63 | }, 64 | }, 65 | pie: { 66 | itemStyle: { 67 | borderWidth: 0, 68 | borderColor: '#cccccc', 69 | }, 70 | }, 71 | scatter: { 72 | itemStyle: { 73 | borderWidth: 0, 74 | borderColor: '#cccccc', 75 | }, 76 | }, 77 | boxplot: { 78 | itemStyle: { 79 | borderWidth: 0, 80 | borderColor: '#cccccc', 81 | }, 82 | }, 83 | parallel: { 84 | itemStyle: { 85 | borderWidth: 0, 86 | borderColor: '#cccccc', 87 | }, 88 | }, 89 | sankey: { 90 | itemStyle: { 91 | borderWidth: 0, 92 | borderColor: '#cccccc', 93 | }, 94 | }, 95 | funnel: { 96 | itemStyle: { 97 | borderWidth: 0, 98 | borderColor: '#cccccc', 99 | }, 100 | }, 101 | gauge: { 102 | itemStyle: { 103 | borderWidth: 0, 104 | borderColor: '#cccccc', 105 | }, 106 | }, 107 | candlestick: { 108 | itemStyle: { 109 | color: '#e01f54', 110 | color0: '#001852', 111 | borderColor: '#f5e8c8', 112 | borderColor0: '#b8d2c7', 113 | borderWidth: 1, 114 | }, 115 | }, 116 | graph: { 117 | itemStyle: { 118 | borderWidth: 0, 119 | borderColor: '#cccccc', 120 | }, 121 | lineStyle: { 122 | width: 1, 123 | color: '#aaaaaa', 124 | }, 125 | symbolSize: '0', 126 | symbol: 'circle', 127 | smooth: false, 128 | color: [ 129 | '#34c3ff', 130 | '#a873e6', 131 | '#13ba9e', 132 | '#ee5765', 133 | '#f5a623', 134 | '#2575fc', 135 | '#df6ecd', 136 | '#8338ec', 137 | '#e6b980', 138 | '#51E8FF', 139 | ], 140 | label: { 141 | color: '#e9ebf0', 142 | }, 143 | }, 144 | map: { 145 | itemStyle: { 146 | areaColor: '#eeeeee', 147 | borderColor: '#444444', 148 | borderWidth: 0.5, 149 | }, 150 | label: { 151 | color: '#000000', 152 | }, 153 | emphasis: { 154 | itemStyle: { 155 | areaColor: 'rgba(255,215,0,0.8)', 156 | borderColor: '#444444', 157 | borderWidth: 1, 158 | }, 159 | label: { 160 | color: 'rgb(100,0,0)', 161 | }, 162 | }, 163 | }, 164 | geo: { 165 | itemStyle: { 166 | areaColor: '#eeeeee', 167 | borderColor: '#444444', 168 | borderWidth: 0.5, 169 | }, 170 | label: { 171 | color: '#000000', 172 | }, 173 | emphasis: { 174 | itemStyle: { 175 | areaColor: 'rgba(255,215,0,0.8)', 176 | borderColor: '#444444', 177 | borderWidth: 1, 178 | }, 179 | label: { 180 | color: 'rgb(100,0,0)', 181 | }, 182 | }, 183 | }, 184 | categoryAxis: { 185 | axisLine: { 186 | show: true, 187 | lineStyle: { 188 | color: '#3c3f43', 189 | }, 190 | }, 191 | axisTick: { 192 | show: false, 193 | lineStyle: { 194 | color: '#333', 195 | }, 196 | }, 197 | axisLabel: { 198 | show: true, 199 | color: '#e9ebf0', 200 | }, 201 | splitLine: { 202 | show: false, 203 | lineStyle: { 204 | color: ['#e5e5ea'], 205 | }, 206 | }, 207 | splitArea: { 208 | show: false, 209 | areaStyle: { 210 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 211 | }, 212 | }, 213 | }, 214 | valueAxis: { 215 | axisLine: { 216 | show: false, 217 | lineStyle: { 218 | color: '#e5e5ea', 219 | }, 220 | }, 221 | axisTick: { 222 | show: false, 223 | lineStyle: { 224 | color: '#8e8e93', 225 | }, 226 | }, 227 | axisLabel: { 228 | show: true, 229 | color: '#e9ebf0', 230 | }, 231 | splitLine: { 232 | show: true, 233 | lineStyle: { 234 | color: ['#3c3f43'], 235 | }, 236 | }, 237 | splitArea: { 238 | show: false, 239 | areaStyle: { 240 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 241 | }, 242 | }, 243 | }, 244 | logAxis: { 245 | axisLine: { 246 | show: true, 247 | lineStyle: { 248 | color: '#3c3f43', 249 | }, 250 | }, 251 | axisTick: { 252 | show: true, 253 | lineStyle: { 254 | color: '#333', 255 | }, 256 | }, 257 | axisLabel: { 258 | show: true, 259 | color: '#e9ebf0', 260 | }, 261 | splitLine: { 262 | show: true, 263 | lineStyle: { 264 | color: ['#3c3f43'], 265 | }, 266 | }, 267 | splitArea: { 268 | show: false, 269 | areaStyle: { 270 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 271 | }, 272 | }, 273 | }, 274 | timeAxis: { 275 | axisLine: { 276 | show: true, 277 | lineStyle: { 278 | color: '#3c3f43', 279 | }, 280 | }, 281 | axisTick: { 282 | show: true, 283 | lineStyle: { 284 | color: '#333', 285 | }, 286 | }, 287 | axisLabel: { 288 | show: true, 289 | color: '#e9ebf0', 290 | }, 291 | splitLine: { 292 | show: true, 293 | lineStyle: { 294 | color: ['#3c3f43'], 295 | }, 296 | }, 297 | splitArea: { 298 | show: false, 299 | areaStyle: { 300 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 301 | }, 302 | }, 303 | }, 304 | toolbox: { 305 | iconStyle: { 306 | borderColor: '#999999', 307 | }, 308 | emphasis: { 309 | iconStyle: {}, 310 | }, 311 | }, 312 | legend: { 313 | textStyle: { 314 | color: '#8e8e93', 315 | }, 316 | }, 317 | tooltip: { 318 | axisPointer: { 319 | lineStyle: { 320 | color: '#cccccc', 321 | width: 1, 322 | }, 323 | crossStyle: { 324 | color: '#cccccc', 325 | width: 1, 326 | }, 327 | }, 328 | }, 329 | timeline: { 330 | lineStyle: { 331 | color: '#293c55', 332 | width: 1, 333 | }, 334 | itemStyle: { 335 | color: '#293c55', 336 | borderWidth: 1, 337 | }, 338 | controlStyle: { 339 | color: '#293c55', 340 | borderColor: '#293c55', 341 | borderWidth: 0.5, 342 | }, 343 | checkpointStyle: { 344 | color: '#e43c59', 345 | borderColor: '#c23531', 346 | }, 347 | label: { 348 | color: '#293c55', 349 | }, 350 | emphasis: { 351 | itemStyle: { 352 | color: '#a9334c', 353 | }, 354 | controlStyle: { 355 | color: '#293c55', 356 | borderColor: '#293c55', 357 | borderWidth: 0.5, 358 | }, 359 | label: { 360 | color: '#293c55', 361 | }, 362 | }, 363 | }, 364 | visualMap: { 365 | color: ['#c2edff', '#009de6'], 366 | }, 367 | dataZoom: { 368 | backgroundColor: 'rgba(47,69,84,0)', 369 | dataBackgroundColor: 'rgba(47,69,84,0.3)', 370 | fillerColor: 'rgba(167,183,204,0.4)', 371 | handleColor: '#a7b7cc', 372 | handleSize: '100%', 373 | textStyle: { 374 | color: '#333333', 375 | }, 376 | }, 377 | markPoint: { 378 | label: { 379 | color: '#e9ebf0', 380 | }, 381 | emphasis: { 382 | label: { 383 | color: '#e9ebf0', 384 | }, 385 | }, 386 | }, 387 | }; 388 | 389 | /** 390 | * Theme properties that are not supported by the theme builder GUI 391 | */ 392 | const additionalSettings = { 393 | textStyle: { 394 | color: '#e9ebf0', 395 | }, 396 | legend: { 397 | textStyle: { 398 | fontSize: 14, 399 | }, 400 | }, 401 | }; 402 | 403 | export default _merge(theme, additionalSettings); 404 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/src/rsuite_light.project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "themeName": "rsuite_light", 4 | "theme": { 5 | "seriesCnt": "7", 6 | "backgroundColor": "rgba(0,0,0,0)", 7 | "titleColor": "#333333", 8 | "subtitleColor": "#aaaaaa", 9 | "textColorShow": false, 10 | "textColor": "#333", 11 | "markTextColor": "#eeeeee", 12 | "color": [ 13 | "#34c3ff", 14 | "#a873e6", 15 | "#13ba9e", 16 | "#ee5765", 17 | "#f5a623", 18 | "#2575fc", 19 | "#df6ecd", 20 | "#8338ec", 21 | "#e6b980", 22 | "#51E8FF" 23 | ], 24 | "borderColor": "#ccc", 25 | "borderWidth": 0, 26 | "visualMapColor": ["#c2edff", "#009de6"], 27 | "legendTextColor": "#8e8e93", 28 | "kColor": "#e01f54", 29 | "kColor0": "#001852", 30 | "kBorderColor": "#f5e8c8", 31 | "kBorderColor0": "#b8d2c7", 32 | "kBorderWidth": 1, 33 | "lineWidth": 2, 34 | "symbolSize": "0", 35 | "symbol": "circle", 36 | "symbolBorderWidth": "0", 37 | "lineSmooth": false, 38 | "graphLineWidth": 1, 39 | "graphLineColor": "#aaaaaa", 40 | "mapLabelColor": "#000000", 41 | "mapLabelColorE": "rgb(100,0,0)", 42 | "mapBorderColor": "#444444", 43 | "mapBorderColorE": "#444444", 44 | "mapBorderWidth": 0.5, 45 | "mapBorderWidthE": 1, 46 | "mapAreaColor": "#eeeeee", 47 | "mapAreaColorE": "rgba(255,215,0,0.8)", 48 | "axes": [ 49 | { 50 | "type": "all", 51 | "name": "通用坐标轴", 52 | "axisLineShow": true, 53 | "axisLineColor": "#e5e5ea", 54 | "axisTickShow": false, 55 | "axisTickColor": "#333", 56 | "axisLabelShow": true, 57 | "axisLabelColor": "#575757", 58 | "splitLineShow": true, 59 | "splitLineColor": ["#e5e5ea"], 60 | "splitAreaShow": false, 61 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 62 | }, 63 | { 64 | "type": "category", 65 | "name": "类目坐标轴", 66 | "axisLineShow": true, 67 | "axisLineColor": "#e5e5ea", 68 | "axisTickShow": false, 69 | "axisTickColor": "#333", 70 | "axisLabelShow": true, 71 | "axisLabelColor": "#575757", 72 | "splitLineShow": false, 73 | "splitLineColor": ["#e5e5ea"], 74 | "splitAreaShow": false, 75 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 76 | }, 77 | { 78 | "type": "value", 79 | "name": "数值坐标轴", 80 | "axisLineShow": false, 81 | "axisLineColor": "#e5e5ea", 82 | "axisTickShow": false, 83 | "axisTickColor": "#8e8e93", 84 | "axisLabelShow": true, 85 | "axisLabelColor": "#575757", 86 | "splitLineShow": true, 87 | "splitLineColor": ["#e5e5ea"], 88 | "splitAreaShow": false, 89 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 90 | }, 91 | { 92 | "type": "log", 93 | "name": "对数坐标轴", 94 | "axisLineShow": true, 95 | "axisLineColor": "#e5e5ea", 96 | "axisTickShow": true, 97 | "axisTickColor": "#333", 98 | "axisLabelShow": true, 99 | "axisLabelColor": "#575757", 100 | "splitLineShow": true, 101 | "splitLineColor": ["#e5e5ea"], 102 | "splitAreaShow": false, 103 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 104 | }, 105 | { 106 | "type": "time", 107 | "name": "时间坐标轴", 108 | "axisLineShow": true, 109 | "axisLineColor": "#e5e5ea", 110 | "axisTickShow": true, 111 | "axisTickColor": "#333", 112 | "axisLabelShow": true, 113 | "axisLabelColor": "#575757", 114 | "splitLineShow": true, 115 | "splitLineColor": ["#e5e5ea"], 116 | "splitAreaShow": false, 117 | "splitAreaColor": ["rgba(250,250,250,0.3)", "rgba(200,200,200,0.3)"] 118 | } 119 | ], 120 | "axisSeperateSetting": true, 121 | "toolboxColor": "#999999", 122 | "toolboxEmpasisColor": "#666666", 123 | "tooltipAxisColor": "#cccccc", 124 | "tooltipAxisWidth": 1, 125 | "timelineLineColor": "#293c55", 126 | "timelineLineWidth": 1, 127 | "timelineItemColor": "#293c55", 128 | "timelineItemColorE": "#a9334c", 129 | "timelineCheckColor": "#e43c59", 130 | "timelineCheckBorderColor": "#c23531", 131 | "timelineItemBorderWidth": 1, 132 | "timelineControlColor": "#293c55", 133 | "timelineControlBorderColor": "#293c55", 134 | "timelineControlBorderWidth": 0.5, 135 | "timelineLabelColor": "#293c55", 136 | "datazoomBackgroundColor": "rgba(47,69,84,0)", 137 | "datazoomDataColor": "rgba(47,69,84,0.3)", 138 | "datazoomFillColor": "rgba(167,183,204,0.4)", 139 | "datazoomHandleColor": "#a7b7cc", 140 | "datazoomHandleWidth": "100", 141 | "datazoomLabelColor": "#333333" 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/src/rsuite_light.ts: -------------------------------------------------------------------------------- 1 | import _merge from 'lodash.merge'; 2 | 3 | /** 4 | * DO NOT directly edit this theme object 5 | * If you need to edit the rsuite_light theme, follow these steps: 6 | * 7 | * 1. Visit https://echarts.apache.org/zh/theme-builder.html 8 | * 2. Import rsuite_light.project.json to the theme builder 9 | * 3. Make changes in the theme builder GUI 10 | * 4. Download (not export) the edited theme 11 | * 5. Replace the theme object with the latest theme JSON 12 | * 6. Export the edited theme and update rsuite_light.project.json 13 | */ 14 | const theme = { 15 | color: [ 16 | '#34c3ff', 17 | '#a873e6', 18 | '#13ba9e', 19 | '#ee5765', 20 | '#f5a623', 21 | '#2575fc', 22 | '#df6ecd', 23 | '#8338ec', 24 | '#e6b980', 25 | '#51E8FF', 26 | ], 27 | backgroundColor: 'rgba(0,0,0,0)', 28 | textStyle: {}, 29 | title: { 30 | textStyle: { 31 | color: '#333333', 32 | }, 33 | subtextStyle: { 34 | color: '#aaaaaa', 35 | }, 36 | }, 37 | line: { 38 | itemStyle: { 39 | borderWidth: '0', 40 | }, 41 | lineStyle: { 42 | width: 2, 43 | }, 44 | symbolSize: '0', 45 | symbol: 'circle', 46 | smooth: false, 47 | }, 48 | radar: { 49 | itemStyle: { 50 | borderWidth: '0', 51 | }, 52 | lineStyle: { 53 | width: 2, 54 | }, 55 | symbolSize: '0', 56 | symbol: 'circle', 57 | smooth: false, 58 | }, 59 | bar: { 60 | itemStyle: { 61 | barBorderWidth: 0, 62 | barBorderColor: '#ccc', 63 | }, 64 | }, 65 | pie: { 66 | itemStyle: { 67 | borderWidth: 0, 68 | borderColor: '#ccc', 69 | }, 70 | }, 71 | scatter: { 72 | itemStyle: { 73 | borderWidth: 0, 74 | borderColor: '#ccc', 75 | }, 76 | }, 77 | boxplot: { 78 | itemStyle: { 79 | borderWidth: 0, 80 | borderColor: '#ccc', 81 | }, 82 | }, 83 | parallel: { 84 | itemStyle: { 85 | borderWidth: 0, 86 | borderColor: '#ccc', 87 | }, 88 | }, 89 | sankey: { 90 | itemStyle: { 91 | borderWidth: 0, 92 | borderColor: '#ccc', 93 | }, 94 | }, 95 | funnel: { 96 | itemStyle: { 97 | borderWidth: 0, 98 | borderColor: '#ccc', 99 | }, 100 | }, 101 | gauge: { 102 | itemStyle: { 103 | borderWidth: 0, 104 | borderColor: '#ccc', 105 | }, 106 | }, 107 | candlestick: { 108 | itemStyle: { 109 | color: '#e01f54', 110 | color0: '#001852', 111 | borderColor: '#f5e8c8', 112 | borderColor0: '#b8d2c7', 113 | borderWidth: 1, 114 | }, 115 | }, 116 | graph: { 117 | itemStyle: { 118 | borderWidth: 0, 119 | borderColor: '#ccc', 120 | }, 121 | lineStyle: { 122 | width: 1, 123 | color: '#aaaaaa', 124 | }, 125 | symbolSize: '0', 126 | symbol: 'circle', 127 | smooth: false, 128 | color: [ 129 | '#34c3ff', 130 | '#a873e6', 131 | '#13ba9e', 132 | '#ee5765', 133 | '#f5a623', 134 | '#2575fc', 135 | '#df6ecd', 136 | '#8338ec', 137 | '#e6b980', 138 | '#51E8FF', 139 | ], 140 | label: { 141 | color: '#eeeeee', 142 | }, 143 | }, 144 | map: { 145 | itemStyle: { 146 | areaColor: '#eeeeee', 147 | borderColor: '#444444', 148 | borderWidth: 0.5, 149 | }, 150 | label: { 151 | color: '#000000', 152 | }, 153 | emphasis: { 154 | itemStyle: { 155 | areaColor: 'rgba(255,215,0,0.8)', 156 | borderColor: '#444444', 157 | borderWidth: 1, 158 | }, 159 | label: { 160 | color: 'rgb(100,0,0)', 161 | }, 162 | }, 163 | }, 164 | geo: { 165 | itemStyle: { 166 | areaColor: '#eeeeee', 167 | borderColor: '#444444', 168 | borderWidth: 0.5, 169 | }, 170 | label: { 171 | color: '#000000', 172 | }, 173 | emphasis: { 174 | itemStyle: { 175 | areaColor: 'rgba(255,215,0,0.8)', 176 | borderColor: '#444444', 177 | borderWidth: 1, 178 | }, 179 | label: { 180 | color: 'rgb(100,0,0)', 181 | }, 182 | }, 183 | }, 184 | categoryAxis: { 185 | axisLine: { 186 | show: true, 187 | lineStyle: { 188 | color: '#e5e5ea', 189 | }, 190 | }, 191 | axisTick: { 192 | show: false, 193 | lineStyle: { 194 | color: '#333', 195 | }, 196 | }, 197 | axisLabel: { 198 | show: true, 199 | color: '#575757', 200 | }, 201 | splitLine: { 202 | show: false, 203 | lineStyle: { 204 | color: ['#e5e5ea'], 205 | }, 206 | }, 207 | splitArea: { 208 | show: false, 209 | areaStyle: { 210 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 211 | }, 212 | }, 213 | }, 214 | valueAxis: { 215 | axisLine: { 216 | show: false, 217 | lineStyle: { 218 | color: '#e5e5ea', 219 | }, 220 | }, 221 | axisTick: { 222 | show: false, 223 | lineStyle: { 224 | color: '#8e8e93', 225 | }, 226 | }, 227 | axisLabel: { 228 | show: true, 229 | color: '#575757', 230 | }, 231 | splitLine: { 232 | show: true, 233 | lineStyle: { 234 | color: ['#e5e5ea'], 235 | }, 236 | }, 237 | splitArea: { 238 | show: false, 239 | areaStyle: { 240 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 241 | }, 242 | }, 243 | }, 244 | logAxis: { 245 | axisLine: { 246 | show: true, 247 | lineStyle: { 248 | color: '#e5e5ea', 249 | }, 250 | }, 251 | axisTick: { 252 | show: true, 253 | lineStyle: { 254 | color: '#333', 255 | }, 256 | }, 257 | axisLabel: { 258 | show: true, 259 | color: '#575757', 260 | }, 261 | splitLine: { 262 | show: true, 263 | lineStyle: { 264 | color: ['#e5e5ea'], 265 | }, 266 | }, 267 | splitArea: { 268 | show: false, 269 | areaStyle: { 270 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 271 | }, 272 | }, 273 | }, 274 | timeAxis: { 275 | axisLine: { 276 | show: true, 277 | lineStyle: { 278 | color: '#e5e5ea', 279 | }, 280 | }, 281 | axisTick: { 282 | show: true, 283 | lineStyle: { 284 | color: '#333', 285 | }, 286 | }, 287 | axisLabel: { 288 | show: true, 289 | color: '#575757', 290 | }, 291 | splitLine: { 292 | show: true, 293 | lineStyle: { 294 | color: ['#e5e5ea'], 295 | }, 296 | }, 297 | splitArea: { 298 | show: false, 299 | areaStyle: { 300 | color: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'], 301 | }, 302 | }, 303 | }, 304 | toolbox: { 305 | iconStyle: { 306 | borderColor: '#999999', 307 | }, 308 | emphasis: { 309 | iconStyle: {}, 310 | }, 311 | }, 312 | legend: { 313 | textStyle: { 314 | color: '#8e8e93', 315 | }, 316 | }, 317 | tooltip: { 318 | axisPointer: { 319 | lineStyle: { 320 | color: '#cccccc', 321 | width: 1, 322 | }, 323 | crossStyle: { 324 | color: '#cccccc', 325 | width: 1, 326 | }, 327 | }, 328 | }, 329 | timeline: { 330 | lineStyle: { 331 | color: '#293c55', 332 | width: 1, 333 | }, 334 | itemStyle: { 335 | color: '#293c55', 336 | borderWidth: 1, 337 | }, 338 | controlStyle: { 339 | color: '#293c55', 340 | borderColor: '#293c55', 341 | borderWidth: 0.5, 342 | }, 343 | checkpointStyle: { 344 | color: '#e43c59', 345 | borderColor: '#c23531', 346 | }, 347 | label: { 348 | color: '#293c55', 349 | }, 350 | emphasis: { 351 | itemStyle: { 352 | color: '#a9334c', 353 | }, 354 | controlStyle: { 355 | color: '#293c55', 356 | borderColor: '#293c55', 357 | borderWidth: 0.5, 358 | }, 359 | label: { 360 | color: '#293c55', 361 | }, 362 | }, 363 | }, 364 | visualMap: { 365 | color: ['#c2edff', '#009de6'], 366 | }, 367 | dataZoom: { 368 | backgroundColor: 'rgba(47,69,84,0)', 369 | dataBackgroundColor: 'rgba(47,69,84,0.3)', 370 | fillerColor: 'rgba(167,183,204,0.4)', 371 | handleColor: '#a7b7cc', 372 | handleSize: '100%', 373 | textStyle: { 374 | color: '#333333', 375 | }, 376 | }, 377 | markPoint: { 378 | label: { 379 | color: '#eeeeee', 380 | }, 381 | emphasis: { 382 | label: { 383 | color: '#eeeeee', 384 | }, 385 | }, 386 | }, 387 | }; 388 | 389 | const additionalSettings = { 390 | textStyle: { 391 | color: '#575757', 392 | }, 393 | legend: { 394 | textStyle: { 395 | fontSize: 14, 396 | }, 397 | }, 398 | }; 399 | 400 | export default _merge(additionalSettings, theme); 401 | -------------------------------------------------------------------------------- /packages/echarts-theme-rsuite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "esnext", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "moduleResolution": "node", 8 | "skipLibCheck": true, 9 | "noUnusedLocals": true, 10 | "noImplicitAny": false, 11 | "allowJs": true, 12 | "noEmit": true, 13 | "outDir": "dist", 14 | "jsx": "react", 15 | "resolveJsonModule": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "baseBranch": "origin/master", 4 | "pipeline": { 5 | "dev": { 6 | "dependsOn": ["^build"] 7 | }, 8 | "build": { 9 | "dependsOn": ["^build"], 10 | "outputs": ["dist/**"] 11 | }, 12 | "build-docs": { 13 | "dependsOn": ["^build"] 14 | } 15 | } 16 | } 17 | --------------------------------------------------------------------------------