├── src
├── index.css
├── App.test.js
├── index.js
├── App.css
├── EchartsDemo
│ ├── RadarReact.js
│ ├── BarReact.js
│ ├── PieReact.js
│ ├── LineReact.js
│ ├── ScatterReact.js
│ ├── CandlestickReact.js
│ └── MapReact.js
├── AsyncComponent.js
├── App.js
├── logo.svg
├── registerServiceWorker.js
└── optionConfig
│ └── options.js
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── package.json
├── LICENSE
├── .gitignore
└── README.md
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-love/react-echarts-modules/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import registerServiceWorker from './registerServiceWorker';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 | registerServiceWorker();
9 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 80px;
8 | }
9 |
10 | .App-header {
11 | background-color: #222;
12 | height: 150px;
13 | padding: 20px;
14 | color: white;
15 | }
16 |
17 | .App-intro {
18 | font-size: large;
19 | }
20 |
21 | @keyframes App-logo-spin {
22 | from { transform: rotate(0deg); }
23 | to { transform: rotate(360deg); }
24 | }
25 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-echarts-example",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "echarts": "4.1.0",
7 | "react": "16.5.0",
8 | "react-dom": "16.5.0"
9 | },
10 | "devDependencies": {
11 | "react-scripts": "1.1.5"
12 | },
13 | "scripts": {
14 | "start": "react-scripts start",
15 | "build": "react-scripts build",
16 | "test": "react-scripts test --env=jsdom",
17 | "eject": "react-scripts eject"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/EchartsDemo/RadarReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/chart/radar' //引入雷达图
7 |
8 | export default class RadarReact extends React.Component {
9 |
10 | constructor(props) {
11 | super(props)
12 | this.initPie = this.initPie.bind(this)
13 | }
14 |
15 | initPie() {
16 | const { option={} } = this.props //外部传入的data数据
17 | let myChart = echarts.init(this.ID) //初始化echarts
18 |
19 | //设置options
20 | myChart.setOption(option)
21 | window.onresize = function() {
22 | myChart.resize()
23 | }
24 | }
25 |
26 | componentDidMount() {
27 | this.initPie()
28 | }
29 |
30 | componentDidUpdate() {
31 | this.initPie()
32 | }
33 |
34 | render() {
35 | const { width="100%", height="400px" } = this.props
36 | return
this.ID = ID} style={{width, height}}>
37 | }
38 | }
--------------------------------------------------------------------------------
/src/AsyncComponent.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | const asyncComponent = loadComponent => (
6 | class AsyncComponent extends React.Component {
7 | state = {
8 | Component: null,
9 | }
10 |
11 | componentWillMount() {
12 | if (this.hasLoadedComponent()) {
13 | return;
14 | }
15 |
16 | loadComponent()
17 | .then(module => module.default)
18 | .then((Component) => {
19 | this.setState({ Component });
20 | })
21 | .catch((err) => {
22 | console.error(`Cannot load component in `);
23 | throw err;
24 | });
25 | }
26 |
27 | hasLoadedComponent() {
28 | return this.state.Component != null;
29 | }
30 |
31 | render() {
32 | const { Component } = this.state;
33 | return (Component) ? : null;
34 | }
35 | }
36 | );
37 |
38 | export default asyncComponent
39 |
--------------------------------------------------------------------------------
/src/EchartsDemo/BarReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/component/tooltip'
7 | import 'echarts/lib/component/grid'
8 | import 'echarts/lib/chart/bar'
9 |
10 | export default class BarReact extends React.Component {
11 |
12 | constructor(props) {
13 | super(props)
14 | this.initPie = this.initPie.bind(this)
15 | }
16 |
17 | initPie() {
18 | const { option={} } = this.props //外部传入的data数据
19 | let myChart = echarts.init(this.ID) //初始化echarts
20 |
21 | //设置options
22 | myChart.setOption(option)
23 | window.onresize = function() {
24 | myChart.resize()
25 | }
26 | }
27 |
28 | componentDidMount() {
29 | this.initPie()
30 | }
31 |
32 | componentDidUpdate() {
33 | this.initPie()
34 | }
35 |
36 | render() {
37 | const { width="100%", height="200px"} = this.props
38 | return this.ID = ID} style={{width, height}}>
39 | }
40 | }
--------------------------------------------------------------------------------
/src/EchartsDemo/PieReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/component/tooltip'
7 | import 'echarts/lib/component/legend'
8 | import 'echarts/lib/chart/pie'
9 |
10 | export default class PieReact extends React.Component {
11 |
12 | constructor(props) {
13 | super(props)
14 | this.initPie = this.initPie.bind(this)
15 | }
16 |
17 | initPie() {
18 | const { option={} } = this.props //外部传入的data数据
19 | let myChart = echarts.init(this.ID) //初始化echarts
20 |
21 | //设置options
22 | myChart.setOption(option)
23 | window.onresize = function() {
24 | myChart.resize()
25 | }
26 | }
27 |
28 | componentDidMount() {
29 | this.initPie()
30 | }
31 |
32 | componentDidUpdate() {
33 | this.initPie()
34 | }
35 |
36 | render() {
37 | const { width="100%", height = '200px' } = this.props
38 | return this.ID = ID} style={{width, height}}>
39 | }
40 | }
--------------------------------------------------------------------------------
/src/EchartsDemo/LineReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/component/tooltip'
7 | import 'echarts/lib/component/grid'
8 | import 'echarts/lib/chart/line'
9 |
10 | export default class LineReact extends React.Component {
11 |
12 | constructor(props) {
13 | super(props)
14 | this.initPie = this.initPie.bind(this)
15 | }
16 |
17 | initPie() {
18 | const { option={} } = this.props //外部传入的data数据
19 | let myChart = echarts.init(this.ID) //初始化echarts
20 |
21 | //设置options
22 | myChart.setOption(option)
23 | window.onresize = function() {
24 | myChart.resize()
25 | }
26 | }
27 |
28 | componentDidMount() {
29 | this.initPie()
30 | }
31 |
32 | componentDidUpdate() {
33 | this.initPie()
34 | }
35 |
36 | render() {
37 | const { width="100%", height="300px" } = this.props
38 | return this.ID = ID} style={{width, height}}>
39 | }
40 | }
--------------------------------------------------------------------------------
/src/EchartsDemo/ScatterReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/component/tooltip'
7 | import 'echarts/lib/component/legend'
8 | import 'echarts/lib/component/grid'
9 | import 'echarts/lib/chart/scatter'
10 |
11 | export default class ScatterReact extends React.Component {
12 |
13 | constructor(props) {
14 | super(props)
15 | this.initPie = this.initPie.bind(this)
16 | }
17 |
18 | initPie() {
19 | const { option={} } = this.props //外部传入的data数据
20 | let myChart = echarts.init(this.ID) //初始化echarts
21 |
22 | //设置options
23 | myChart.setOption(option)
24 | window.onresize = function() {
25 | myChart.resize()
26 | }
27 | }
28 |
29 | componentDidMount() {
30 | this.initPie()
31 | }
32 |
33 | componentDidUpdate() {
34 | this.initPie()
35 | }
36 |
37 | render() {
38 | const { width="100%", height="200px" } = this.props
39 | return this.ID = ID} style={{width, height}}>
40 | }
41 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 二月
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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (http://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # Typescript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | .idea
61 | build
--------------------------------------------------------------------------------
/src/EchartsDemo/CandlestickReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/chart/candlestick' //引入雷达图
7 | import 'echarts/lib/component/tooltip'
8 | import 'echarts/lib/component/legend'
9 | import 'echarts/lib/component/grid'
10 | import 'echarts/lib/component/markLine'
11 |
12 | export default class CandlestickReact extends React.Component {
13 |
14 | constructor(props) {
15 | super(props)
16 | this.initPie = this.initPie.bind(this)
17 | }
18 |
19 | initPie() {
20 | const { option={} } = this.props //外部传入的data数据
21 | let myChart = echarts.init(this.ID) //初始化echarts
22 |
23 | //设置options
24 | myChart.setOption(option)
25 | window.onresize = function() {
26 | myChart.resize()
27 | }
28 | }
29 |
30 | componentDidMount() {
31 | this.initPie()
32 | }
33 |
34 | componentDidUpdate() {
35 | this.initPie()
36 | }
37 |
38 | render() {
39 | const { width="100%", height="400px" } = this.props
40 | return this.ID = ID} style={{width, height}}>
41 | }
42 | }
--------------------------------------------------------------------------------
/src/EchartsDemo/MapReact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | import React from 'react'
5 | import echarts from 'echarts/lib/echarts' //必须
6 | import 'echarts/lib/component/tooltip'
7 | import 'echarts/lib/component/legend'
8 | import 'echarts/lib/component/geo'
9 | import 'echarts/lib/chart/map' //引入地图
10 | import 'echarts/lib/chart/lines'
11 | import 'echarts/lib/chart/effectScatter'
12 | import 'echarts/map/js/china' // 引入中国地图
13 |
14 | export default class MapReact extends React.Component {
15 |
16 | constructor(props) {
17 | super(props)
18 | this.initPie = this.initPie.bind(this)
19 | }
20 |
21 | initPie() {
22 | const { option={} } = this.props //外部传入的data数据
23 | let myChart = echarts.init(this.ID) //初始化echarts
24 |
25 | //设置options
26 | myChart.setOption(option)
27 | window.onresize = function() {
28 | myChart.resize()
29 | }
30 | }
31 |
32 | componentDidMount() {
33 | this.initPie()
34 | }
35 |
36 | componentDidUpdate() {
37 | this.initPie()
38 | }
39 |
40 | render() {
41 | const { width="100%", height="200px" } = this.props
42 | return this.ID = ID} style={{width, height}}>
43 | }
44 | }
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import asyncComponent from './AsyncComponent'
3 | import { pieOption, barOption, lineOption, scatterOption, mapOption, radarOption, candlestickOption } from './optionConfig/options'
4 | const PieReact = asyncComponent(() => import(/* webpackChunkName: "Pie" */'./EchartsDemo/PieReact')) //饼图组件
5 | const BarReact = asyncComponent(() => import(/* webpackChunkName: "Bar" */'./EchartsDemo/BarReact')) //柱状图组件
6 | const LineReact = asyncComponent(() => import(/* webpackChunkName: "Line" */'./EchartsDemo/LineReact')) //折线图组件
7 | const ScatterReact = asyncComponent(() => import(/* webpackChunkName: "Scatter" */'./EchartsDemo/ScatterReact')) //散点图组件
8 | const MapReact = asyncComponent(() => import(/* webpackChunkName: "Map" */'./EchartsDemo/MapReact')) //地图组件
9 | const RadarReact = asyncComponent(() => import(/* webpackChunkName: "Radar" */'./EchartsDemo/RadarReact')) //雷达图组件
10 | const CandlestickReact = asyncComponent(() => import(/* webpackChunkName: "Candlestick" */'./EchartsDemo/CandlestickReact')) //k线图组件
11 |
12 | class App extends Component {
13 | render() {
14 | return (
15 |
16 |
饼图react组件实现
17 |
18 |
19 |
20 |
柱状图react组件实现
21 |
22 |
23 |
24 |
折线图react组件实现
25 |
26 |
27 |
28 |
散点图react组件实现
29 |
30 |
31 |
32 |
地图react组件实现
33 |
34 |
35 |
36 |
雷达图react组件实现
37 |
38 |
39 |
40 |
k线图react组件实现
41 |
42 |
43 |
44 | );
45 | }
46 | }
47 |
48 | export default App;
49 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### react16.5.0实现echarts4模块化加载
2 |
3 | **我们真的需要react-echarts插件吗?**
4 |
5 | ## NO
6 |
7 | **注意:该项目仅作为源码学习使用,不能采取npm install --save react-echarts-modules的方式导入你的项目,因为这不是一个插件!!**
8 |
9 | **在这里,我使用echarts提供的模块化加载方式,实现了几个react-echarts图表组件**
10 |
11 | **你可以打开控制台,观察每个图表组件的加载情况。**
12 |
13 | #### 插件版本号
14 |
15 | ```json
16 | "echarts": "4.1.0",
17 | "react": "16.5.0",
18 | "react-dom": "16.5.0"
19 | ```
20 |
21 | #### 实现了哪些图表组件
22 |
23 | 1、饼图
24 |
25 | 2、柱状图
26 |
27 | 3、折线图
28 |
29 | 4、散点图
30 |
31 | 5、地图
32 |
33 | 6、雷达图
34 |
35 | 7、k线图
36 |
37 |
38 | #### echarts体积太大,使用模块化加载
39 |
40 | 以柱状图为例子,我们根据需要渲染的插件采取模块导入,不渲染的组件不导入,最大程度减小js。
41 |
42 | ```javascript
43 | import echarts from 'echarts/lib/echarts' //必须
44 | import 'echarts/lib/component/tooltip'
45 | import 'echarts/lib/component/grid'
46 | import 'echarts/lib/chart/bar'
47 | ```
48 |
49 | #### 组件化开发的福音,react组件模块化加载
50 |
51 | demo中采用单个echarts组件异步打包加载的模式,因为echarts组件普遍偏大,即使压缩也效果不明显,所以异步加载是最好的方式。
52 |
53 | ```javascript
54 | import { pieOption, barOption, lineOption, scatterOption, mapOption, radarOption, candlestickOption } from './optionConfig/options'
55 | const PieReact = asyncComponent(() => import(/* webpackChunkName: "Pie" */'./EchartsDemo/PieReact')) //饼图组件
56 | const BarReact = asyncComponent(() => import(/* webpackChunkName: "Bar" */'./EchartsDemo/BarReact')) //柱状图组件
57 | const LineReact = asyncComponent(() => import(/* webpackChunkName: "Line" */'./EchartsDemo/LineReact')) //折线图组件
58 | const ScatterReact = asyncComponent(() => import(/* webpackChunkName: "Scatter" */'./EchartsDemo/ScatterReact')) //散点图组件
59 | const MapReact = asyncComponent(() => import(/* webpackChunkName: "Map" */'./EchartsDemo/MapReact')) //地图组件
60 | const RadarReact = asyncComponent(() => import(/* webpackChunkName: "Radar" */'./EchartsDemo/RadarReact')) //雷达图组件
61 | const CandlestickReact = asyncComponent(() => import(/* webpackChunkName: "Candlestick" */'./EchartsDemo/CandlestickReact')) //k线图组件
62 | ```
63 |
64 | ### 启动项目
65 |
66 | ```npm
67 | npm install
68 | ```
69 |
70 | ```npm
71 | npm start
72 | ```
73 |
74 | ### 打包项目
75 |
76 | ```npm
77 | npm run build
78 | ```
79 |
80 | ### 实现方案介绍
81 |
82 | 1、每个图表单独封装成一个组件,通过参数传递数据,你会发现,图表内部代码几乎完全一样,只有import的类型不同。
83 |
84 | 2、异步加载是提高图表加载性能的最佳方式,不管是服务端还是客户端渲染。
85 |
86 | 3、在这些demo中,我认为对你来说最有价值的是react组件异步加载模式,很多人异步加载组件是通过拆分路由的方式,而非路由组件的异步加载,并不多人去尝试。但我想告诉你的是,
87 | 非路由组件的异步加载会将你的庞大的父组件拆分的更细,体积更小,加载的更加流畅。
88 |
89 | 4、有时候,我会看到有些人把echarts打包到公共js文件里面,如果你的首屏不需要用到它,完全没有必要这样做。
90 |
91 | ### 附echarts各个模块导出路径
92 |
93 | ```javascript
94 | /**
95 | * 导出echarts主模块
96 | */
97 | module.exports = require('./lib/echarts');
98 |
99 | // 各子模块路径
100 | require('./lib/chart/line');
101 | require('./lib/chart/bar');
102 | require('./lib/chart/pie');
103 | require('./lib/chart/scatter');
104 | require('./lib/chart/radar');
105 |
106 | require('./lib/chart/map');
107 | require('./lib/chart/treemap');
108 | require('./lib/chart/graph');
109 | require('./lib/chart/gauge');
110 | require('./lib/chart/funnel');
111 | require('./lib/chart/parallel');
112 | require('./lib/chart/sankey');
113 | require('./lib/chart/boxplot');
114 | require('./lib/chart/candlestick');
115 | require('./lib/chart/effectScatter');
116 | require('./lib/chart/lines');
117 | require('./lib/chart/heatmap');
118 | require('./lib/chart/pictorialBar');
119 | require('./lib/chart/themeRiver');
120 | require('./lib/chart/custom');
121 |
122 | require('./lib/component/graphic');
123 | require('./lib/component/grid');
124 | require('./lib/component/legend');
125 | require('./lib/component/tooltip');
126 | require('./lib/component/axisPointer');
127 | require('./lib/component/polar');
128 | require('./lib/component/geo');
129 | require('./lib/component/parallel');
130 | require('./lib/component/singleAxis');
131 | require('./lib/component/brush');
132 | require('./lib/component/calendar');
133 |
134 | require('./lib/component/title');
135 |
136 | require('./lib/component/dataZoom');
137 | require('./lib/component/visualMap');
138 |
139 | require('./lib/component/markPoint');
140 | require('./lib/component/markLine');
141 | require('./lib/component/markArea');
142 |
143 | require('./lib/component/timeline');
144 | require('./lib/component/toolbox');
145 |
146 | require('zrender/lib/vml/vml');
147 |
148 | ```
149 |
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (!isLocalhost) {
36 | // Is not local host. Just register service worker
37 | registerValidSW(swUrl);
38 | } else {
39 | // This is running on localhost. Lets check if a service worker still exists or not.
40 | checkValidServiceWorker(swUrl);
41 | }
42 | });
43 | }
44 | }
45 |
46 | function registerValidSW(swUrl) {
47 | navigator.serviceWorker
48 | .register(swUrl)
49 | .then(registration => {
50 | registration.onupdatefound = () => {
51 | const installingWorker = registration.installing;
52 | installingWorker.onstatechange = () => {
53 | if (installingWorker.state === 'installed') {
54 | if (navigator.serviceWorker.controller) {
55 | // At this point, the old content will have been purged and
56 | // the fresh content will have been added to the cache.
57 | // It's the perfect time to display a "New content is
58 | // available; please refresh." message in your web app.
59 | console.log('New content is available; please refresh.');
60 | } else {
61 | // At this point, everything has been precached.
62 | // It's the perfect time to display a
63 | // "Content is cached for offline use." message.
64 | console.log('Content is cached for offline use.');
65 | }
66 | }
67 | };
68 | };
69 | })
70 | .catch(error => {
71 | console.error('Error during service worker registration:', error);
72 | });
73 | }
74 |
75 | function checkValidServiceWorker(swUrl) {
76 | // Check if the service worker can be found. If it can't reload the page.
77 | fetch(swUrl)
78 | .then(response => {
79 | // Ensure service worker exists, and that we really are getting a JS file.
80 | if (
81 | response.status === 404 ||
82 | response.headers.get('content-type').indexOf('javascript') === -1
83 | ) {
84 | // No service worker found. Probably a different app. Reload the page.
85 | navigator.serviceWorker.ready.then(registration => {
86 | registration.unregister().then(() => {
87 | window.location.reload();
88 | });
89 | });
90 | } else {
91 | // Service worker found. Proceed as normal.
92 | registerValidSW(swUrl);
93 | }
94 | })
95 | .catch(() => {
96 | console.log(
97 | 'No internet connection found. App is running in offline mode.'
98 | );
99 | });
100 | }
101 |
102 | export function unregister() {
103 | if ('serviceWorker' in navigator) {
104 | navigator.serviceWorker.ready.then(registration => {
105 | registration.unregister();
106 | });
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/optionConfig/options.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by yongyuehuang on 2017/8/5.
3 | */
4 | //饼图数据
5 | export const pieOption = {
6 | tooltip: {
7 | trigger: 'item',
8 | formatter: "{a}
{b}: {c} ({d}%)"
9 | },
10 | legend: {
11 | orient: 'vertical',
12 | x: 'left',
13 | data:['直接访问','邮件营销','联盟广告','视频广告','搜索引擎']
14 | },
15 | series: [
16 | {
17 | name:'访问来源',
18 | type:'pie',
19 | radius: ['100%', '70%'],
20 | avoidLabelOverlap: false,
21 | label: {
22 | normal: {
23 | show: false,
24 | position: 'center'
25 | },
26 | emphasis: {
27 | show: true,
28 | textStyle: {
29 | fontSize: '30',
30 | fontWeight: 'bold'
31 | }
32 | }
33 | },
34 | labelLine: {
35 | normal: {
36 | show: false
37 | }
38 | },
39 | data:[
40 | {value:335, name:'直接访问'},
41 | {value:310, name:'邮件营销'},
42 | {value:234, name:'联盟广告'},
43 | {value:135, name:'视频广告'},
44 | {value:1548, name:'搜索引擎'}
45 | ]
46 | }
47 | ]
48 | };
49 |
50 | //柱状图数据
51 | export const barOption = {
52 | color: ['#3398DB'],
53 | tooltip : {
54 | trigger: 'axis',
55 | axisPointer : { // 坐标轴指示器,坐标轴触发有效
56 | type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
57 | }
58 | },
59 | grid: {
60 | left: '3%',
61 | right: '4%',
62 | bottom: '3%',
63 | containLabel: true
64 | },
65 | xAxis : [
66 | {
67 | type : 'category',
68 | data : ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
69 | axisTick: {
70 | alignWithLabel: true
71 | }
72 | }
73 | ],
74 | yAxis : [
75 | {
76 | type : 'value'
77 | }
78 | ],
79 | series : [
80 | {
81 | name:'直接访问',
82 | type:'bar',
83 | barWidth: '60%',
84 | data:[10, 52, 200, 334, 390, 330, 220]
85 | }
86 | ]
87 | };
88 |
89 | //折线图数据
90 | export const lineOption = {
91 | title: {
92 | text: '堆叠区域图'
93 | },
94 | tooltip : {
95 | trigger: 'axis',
96 | axisPointer: {
97 | type: 'cross',
98 | label: {
99 | backgroundColor: '#6a7985'
100 | }
101 | }
102 | },
103 | legend: {
104 | data:['邮件营销','联盟广告','视频广告','直接访问','搜索引擎']
105 | },
106 | toolbox: {
107 | feature: {
108 | saveAsImage: {}
109 | }
110 | },
111 | grid: {
112 | left: '3%',
113 | right: '4%',
114 | bottom: '3%',
115 | containLabel: true
116 | },
117 | xAxis : [
118 | {
119 | type : 'category',
120 | boundaryGap : false,
121 | data : ['周一','周二','周三','周四','周五','周六','周日']
122 | }
123 | ],
124 | yAxis : [
125 | {
126 | type : 'value'
127 | }
128 | ],
129 | series : [
130 | {
131 | name:'邮件营销',
132 | type:'line',
133 | stack: '总量',
134 | areaStyle: {normal: {}},
135 | data:[120, 132, 101, 134, 90, 230, 210]
136 | },
137 | {
138 | name:'联盟广告',
139 | type:'line',
140 | stack: '总量',
141 | areaStyle: {normal: {}},
142 | data:[220, 182, 191, 234, 290, 330, 310]
143 | },
144 | {
145 | name:'视频广告',
146 | type:'line',
147 | stack: '总量',
148 | areaStyle: {normal: {}},
149 | data:[150, 232, 201, 154, 190, 330, 410]
150 | },
151 | {
152 | name:'直接访问',
153 | type:'line',
154 | stack: '总量',
155 | areaStyle: {normal: {}},
156 | data:[320, 332, 301, 334, 390, 330, 320]
157 | },
158 | {
159 | name:'搜索引擎',
160 | type:'line',
161 | stack: '总量',
162 | label: {
163 | normal: {
164 | show: true,
165 | position: 'top'
166 | }
167 | },
168 | areaStyle: {normal: {}},
169 | data:[820, 932, 901, 934, 1290, 1330, 1320]
170 | }
171 | ]
172 | };
173 |
174 | //散点图数据
175 | export const scatterOption = {
176 | tooltip : {
177 | trigger: 'axis',
178 | showDelay : 0,
179 | axisPointer:{
180 | show: true,
181 | type : 'cross',
182 | lineStyle: {
183 | type : 'dashed',
184 | width : 1
185 | }
186 | },
187 | zlevel: 1
188 | },
189 | legend: {
190 | data:['sin','cos']
191 | },
192 | toolbox: {
193 | show : true,
194 | feature : {
195 | mark : {show: true},
196 | dataZoom : {show: true},
197 | dataView : {show: true, readOnly: false},
198 | restore : {show: true},
199 | saveAsImage : {show: true}
200 | }
201 | },
202 | xAxis : [
203 | {
204 | type : 'value',
205 | scale:true
206 | }
207 | ],
208 | yAxis : [
209 | {
210 | type : 'value',
211 | scale:true
212 | }
213 | ],
214 | series : [
215 | {
216 | name:'sin',
217 | type:'scatter',
218 | large: true,
219 | symbolSize: 3,
220 | data: (function () {
221 | var d = [];
222 | var len = 10000;
223 | var x = 0;
224 | while (len--) {
225 | x = (Math.random() * 10).toFixed(3) - 0;
226 | d.push([
227 | x,
228 | //Math.random() * 10
229 | (Math.sin(x) - x * (len % 2 ? 0.1 : -0.1) * Math.random()).toFixed(3) - 0
230 | ]);
231 | }
232 | //console.log(d)
233 | return d;
234 | })()
235 | },
236 | {
237 | name:'cos',
238 | type:'scatter',
239 | large: true,
240 | symbolSize: 2,
241 | data: (function () {
242 | var d = [];
243 | var len = 20000;
244 | var x = 0;
245 | while (len--) {
246 | x = (Math.random() * 10).toFixed(3) - 0;
247 | d.push([
248 | x,
249 | //Math.random() * 10
250 | (Math.cos(x) - x * (len % 2 ? 0.1 : -0.1) * Math.random()).toFixed(3) - 0
251 | ]);
252 | }
253 | //console.log(d)
254 | return d;
255 | })()
256 | }
257 | ]
258 | };
259 |
260 | //地图数据
261 | var geoCoordMap = {
262 | '上海': [121.4648,31.2891],
263 | '东莞': [113.8953,22.901],
264 | '东营': [118.7073,37.5513],
265 | '中山': [113.4229,22.478],
266 | '临汾': [111.4783,36.1615],
267 | '临沂': [118.3118,35.2936],
268 | '丹东': [124.541,40.4242],
269 | '丽水': [119.5642,28.1854],
270 | '乌鲁木齐': [87.9236,43.5883],
271 | '佛山': [112.8955,23.1097],
272 | '保定': [115.0488,39.0948],
273 | '兰州': [103.5901,36.3043],
274 | '包头': [110.3467,41.4899],
275 | '北京': [116.4551,40.2539],
276 | '北海': [109.314,21.6211],
277 | '南京': [118.8062,31.9208],
278 | '南宁': [108.479,23.1152],
279 | '南昌': [116.0046,28.6633],
280 | '南通': [121.1023,32.1625],
281 | '厦门': [118.1689,24.6478],
282 | '台州': [121.1353,28.6688],
283 | '合肥': [117.29,32.0581],
284 | '呼和浩特': [111.4124,40.4901],
285 | '咸阳': [108.4131,34.8706],
286 | '哈尔滨': [127.9688,45.368],
287 | '唐山': [118.4766,39.6826],
288 | '嘉兴': [120.9155,30.6354],
289 | '大同': [113.7854,39.8035],
290 | '大连': [122.2229,39.4409],
291 | '天津': [117.4219,39.4189],
292 | '太原': [112.3352,37.9413],
293 | '威海': [121.9482,37.1393],
294 | '宁波': [121.5967,29.6466],
295 | '宝鸡': [107.1826,34.3433],
296 | '宿迁': [118.5535,33.7775],
297 | '常州': [119.4543,31.5582],
298 | '广州': [113.5107,23.2196],
299 | '廊坊': [116.521,39.0509],
300 | '延安': [109.1052,36.4252],
301 | '张家口': [115.1477,40.8527],
302 | '徐州': [117.5208,34.3268],
303 | '德州': [116.6858,37.2107],
304 | '惠州': [114.6204,23.1647],
305 | '成都': [103.9526,30.7617],
306 | '扬州': [119.4653,32.8162],
307 | '承德': [117.5757,41.4075],
308 | '拉萨': [91.1865,30.1465],
309 | '无锡': [120.3442,31.5527],
310 | '日照': [119.2786,35.5023],
311 | '昆明': [102.9199,25.4663],
312 | '杭州': [119.5313,29.8773],
313 | '枣庄': [117.323,34.8926],
314 | '柳州': [109.3799,24.9774],
315 | '株洲': [113.5327,27.0319],
316 | '武汉': [114.3896,30.6628],
317 | '汕头': [117.1692,23.3405],
318 | '江门': [112.6318,22.1484],
319 | '沈阳': [123.1238,42.1216],
320 | '沧州': [116.8286,38.2104],
321 | '河源': [114.917,23.9722],
322 | '泉州': [118.3228,25.1147],
323 | '泰安': [117.0264,36.0516],
324 | '泰州': [120.0586,32.5525],
325 | '济南': [117.1582,36.8701],
326 | '济宁': [116.8286,35.3375],
327 | '海口': [110.3893,19.8516],
328 | '淄博': [118.0371,36.6064],
329 | '淮安': [118.927,33.4039],
330 | '深圳': [114.5435,22.5439],
331 | '清远': [112.9175,24.3292],
332 | '温州': [120.498,27.8119],
333 | '渭南': [109.7864,35.0299],
334 | '湖州': [119.8608,30.7782],
335 | '湘潭': [112.5439,27.7075],
336 | '滨州': [117.8174,37.4963],
337 | '潍坊': [119.0918,36.524],
338 | '烟台': [120.7397,37.5128],
339 | '玉溪': [101.9312,23.8898],
340 | '珠海': [113.7305,22.1155],
341 | '盐城': [120.2234,33.5577],
342 | '盘锦': [121.9482,41.0449],
343 | '石家庄': [114.4995,38.1006],
344 | '福州': [119.4543,25.9222],
345 | '秦皇岛': [119.2126,40.0232],
346 | '绍兴': [120.564,29.7565],
347 | '聊城': [115.9167,36.4032],
348 | '肇庆': [112.1265,23.5822],
349 | '舟山': [122.2559,30.2234],
350 | '苏州': [120.6519,31.3989],
351 | '莱芜': [117.6526,36.2714],
352 | '菏泽': [115.6201,35.2057],
353 | '营口': [122.4316,40.4297],
354 | '葫芦岛': [120.1575,40.578],
355 | '衡水': [115.8838,37.7161],
356 | '衢州': [118.6853,28.8666],
357 | '西宁': [101.4038,36.8207],
358 | '西安': [109.1162,34.2004],
359 | '贵阳': [106.6992,26.7682],
360 | '连云港': [119.1248,34.552],
361 | '邢台': [114.8071,37.2821],
362 | '邯郸': [114.4775,36.535],
363 | '郑州': [113.4668,34.6234],
364 | '鄂尔多斯': [108.9734,39.2487],
365 | '重庆': [107.7539,30.1904],
366 | '金华': [120.0037,29.1028],
367 | '铜川': [109.0393,35.1947],
368 | '银川': [106.3586,38.1775],
369 | '镇江': [119.4763,31.9702],
370 | '长春': [125.8154,44.2584],
371 | '长沙': [113.0823,28.2568],
372 | '长治': [112.8625,36.4746],
373 | '阳泉': [113.4778,38.0951],
374 | '青岛': [120.4651,36.3373],
375 | '韶关': [113.7964,24.7028]
376 | };
377 |
378 | var BJData = [
379 | [{name:'北京'}, {name:'上海',value:95}],
380 | [{name:'北京'}, {name:'广州',value:90}],
381 | [{name:'北京'}, {name:'大连',value:80}],
382 | [{name:'北京'}, {name:'南宁',value:70}],
383 | [{name:'北京'}, {name:'南昌',value:60}],
384 | [{name:'北京'}, {name:'拉萨',value:50}],
385 | [{name:'北京'}, {name:'长春',value:40}],
386 | [{name:'北京'}, {name:'包头',value:30}],
387 | [{name:'北京'}, {name:'重庆',value:20}],
388 | [{name:'北京'}, {name:'常州',value:10}]
389 | ];
390 |
391 | var SHData = [
392 | [{name:'上海'},{name:'包头',value:95}],
393 | [{name:'上海'},{name:'昆明',value:90}],
394 | [{name:'上海'},{name:'广州',value:80}],
395 | [{name:'上海'},{name:'郑州',value:70}],
396 | [{name:'上海'},{name:'长春',value:60}],
397 | [{name:'上海'},{name:'重庆',value:50}],
398 | [{name:'上海'},{name:'长沙',value:40}],
399 | [{name:'上海'},{name:'北京',value:30}],
400 | [{name:'上海'},{name:'丹东',value:20}],
401 | [{name:'上海'},{name:'大连',value:10}]
402 | ];
403 |
404 | var GZData = [
405 | [{name:'广州'},{name:'福州',value:95}],
406 | [{name:'广州'},{name:'太原',value:90}],
407 | [{name:'广州'},{name:'长春',value:80}],
408 | [{name:'广州'},{name:'重庆',value:70}],
409 | [{name:'广州'},{name:'西安',value:60}],
410 | [{name:'广州'},{name:'成都',value:50}],
411 | [{name:'广州'},{name:'常州',value:40}],
412 | [{name:'广州'},{name:'北京',value:30}],
413 | [{name:'广州'},{name:'北海',value:20}],
414 | [{name:'广州'},{name:'海口',value:10}]
415 | ];
416 |
417 | var planePath = 'path://M1705.06,1318.313v-89.254l-319.9-221.799l0.073-208.063c0.521-84.662-26.629-121.796-63.961-121.491c-37.332-0.305-64.482,36.829-63.961,121.491l0.073,208.063l-319.9,221.799v89.254l330.343-157.288l12.238,241.308l-134.449,92.931l0.531,42.034l175.125-42.917l175.125,42.917l0.531-42.034l-134.449-92.931l12.238-241.308L1705.06,1318.313z';
418 |
419 | var convertData = function (data) {
420 | var res = [];
421 | for (var i = 0; i < data.length; i++) {
422 | var dataItem = data[i];
423 | var fromCoord = geoCoordMap[dataItem[0].name];
424 | var toCoord = geoCoordMap[dataItem[1].name];
425 | if (fromCoord && toCoord) {
426 | res.push({
427 | fromName: dataItem[0].name,
428 | toName: dataItem[1].name,
429 | coords: [fromCoord, toCoord]
430 | });
431 | }
432 | }
433 | return res;
434 | };
435 |
436 | var color = ['#a6c84c', '#ffa022', '#46bee9'];
437 | var series = [];
438 | [['北京', BJData], ['上海', SHData], ['广州', GZData]].forEach(function (item, i) {
439 | series.push({
440 | name: item[0] + ' Top10',
441 | type: 'lines',
442 | zlevel: 1,
443 | effect: {
444 | show: true,
445 | period: 6,
446 | trailLength: 0.7,
447 | color: '#fff',
448 | symbolSize: 3
449 | },
450 | lineStyle: {
451 | normal: {
452 | color: color[i],
453 | width: 0,
454 | curveness: 0.2
455 | }
456 | },
457 | data: convertData(item[1])
458 | },
459 | {
460 | name: item[0] + ' Top10',
461 | type: 'lines',
462 | zlevel: 2,
463 | symbol: ['none', 'arrow'],
464 | symbolSize: 10,
465 | effect: {
466 | show: true,
467 | period: 6,
468 | trailLength: 0,
469 | symbol: planePath,
470 | symbolSize: 15
471 | },
472 | lineStyle: {
473 | normal: {
474 | color: color[i],
475 | width: 1,
476 | opacity: 0.6,
477 | curveness: 0.2
478 | }
479 | },
480 | data: convertData(item[1])
481 | },
482 | {
483 | name: item[0] + ' Top10',
484 | type: 'effectScatter',
485 | coordinateSystem: 'geo',
486 | zlevel: 2,
487 | rippleEffect: {
488 | brushType: 'stroke'
489 | },
490 | label: {
491 | normal: {
492 | show: true,
493 | position: 'right',
494 | formatter: '{b}'
495 | }
496 | },
497 | symbolSize: function (val) {
498 | return val[2] / 8;
499 | },
500 | itemStyle: {
501 | normal: {
502 | color: color[i]
503 | }
504 | },
505 | data: item[1].map(function (dataItem) {
506 | return {
507 | name: dataItem[1].name,
508 | value: geoCoordMap[dataItem[1].name].concat([dataItem[1].value])
509 | };
510 | })
511 | });
512 | });
513 |
514 | export const mapOption = {
515 | backgroundColor: '#404a59',
516 | tooltip : {
517 | trigger: 'item'
518 | },
519 | legend: {
520 | orient: 'vertical',
521 | top: 'bottom',
522 | left: 'right',
523 | data:['北京 Top10', '上海 Top10', '广州 Top10'],
524 | textStyle: {
525 | color: '#fff'
526 | },
527 | selectedMode: 'single'
528 | },
529 | geo: {
530 | map: 'china',
531 | label: {
532 | emphasis: {
533 | show: false
534 | }
535 | },
536 | roam: true,
537 | itemStyle: {
538 | normal: {
539 | areaColor: '#323c48',
540 | borderColor: '#404a59'
541 | },
542 | emphasis: {
543 | areaColor: '#2a333d'
544 | }
545 | }
546 | },
547 | series: series
548 | };
549 |
550 | //雷达图数据
551 | export const radarOption = {
552 | legend: {
553 | data: ['预算分配(Allocated Budget)', '实际开销(Actual Spending)']
554 | },
555 | radar: {
556 | // shape: 'circle',
557 | indicator: [
558 | { name: '销售(sales)', max: 6500},
559 | { name: '管理(Administration)', max: 16000},
560 | { name: '信息技术(Information Techology)', max: 30000},
561 | { name: '客服(Customer Support)', max: 38000},
562 | { name: '研发(Development)', max: 52000},
563 | { name: '市场(Marketing)', max: 25000}
564 | ]
565 | },
566 | series: [{
567 | name: '预算 vs 开销(Budget vs spending)',
568 | type: 'radar',
569 | // areaStyle: {normal: {}},
570 | data : [
571 | {
572 | value : [4300, 10000, 28000, 35000, 50000, 19000],
573 | name : '预算分配(Allocated Budget)'
574 | },
575 | {
576 | value : [5000, 14000, 28000, 31000, 42000, 21000],
577 | name : '实际开销(Actual Spending)'
578 | }
579 | ]
580 | }]
581 | };
582 |
583 | //k线图数据
584 | // 数据意义:开盘(open),收盘(close),最低(lowest),最高(highest)
585 | var data0 = splitData([
586 | ['2013/1/24', 2320.26,2320.26,2287.3,2362.94],
587 | ['2013/1/25', 2300,2291.3,2288.26,2308.38],
588 | ['2013/1/28', 2295.35,2346.5,2295.35,2346.92],
589 | ['2013/1/29', 2347.22,2358.98,2337.35,2363.8],
590 | ['2013/1/30', 2360.75,2382.48,2347.89,2383.76],
591 | ['2013/1/31', 2383.43,2385.42,2371.23,2391.82],
592 | ['2013/2/1', 2377.41,2419.02,2369.57,2421.15],
593 | ['2013/2/4', 2425.92,2428.15,2417.58,2440.38],
594 | ['2013/2/5', 2411,2433.13,2403.3,2437.42],
595 | ['2013/2/6', 2432.68,2434.48,2427.7,2441.73],
596 | ['2013/2/7', 2430.69,2418.53,2394.22,2433.89],
597 | ['2013/2/8', 2416.62,2432.4,2414.4,2443.03],
598 | ['2013/2/18', 2441.91,2421.56,2415.43,2444.8],
599 | ['2013/2/19', 2420.26,2382.91,2373.53,2427.07],
600 | ['2013/2/20', 2383.49,2397.18,2370.61,2397.94],
601 | ['2013/2/21', 2378.82,2325.95,2309.17,2378.82],
602 | ['2013/2/22', 2322.94,2314.16,2308.76,2330.88],
603 | ['2013/2/25', 2320.62,2325.82,2315.01,2338.78],
604 | ['2013/2/26', 2313.74,2293.34,2289.89,2340.71],
605 | ['2013/2/27', 2297.77,2313.22,2292.03,2324.63],
606 | ['2013/2/28', 2322.32,2365.59,2308.92,2366.16],
607 | ['2013/3/1', 2364.54,2359.51,2330.86,2369.65],
608 | ['2013/3/4', 2332.08,2273.4,2259.25,2333.54],
609 | ['2013/3/5', 2274.81,2326.31,2270.1,2328.14],
610 | ['2013/3/6', 2333.61,2347.18,2321.6,2351.44],
611 | ['2013/3/7', 2340.44,2324.29,2304.27,2352.02],
612 | ['2013/3/8', 2326.42,2318.61,2314.59,2333.67],
613 | ['2013/3/11', 2314.68,2310.59,2296.58,2320.96],
614 | ['2013/3/12', 2309.16,2286.6,2264.83,2333.29],
615 | ['2013/3/13', 2282.17,2263.97,2253.25,2286.33],
616 | ['2013/3/14', 2255.77,2270.28,2253.31,2276.22],
617 | ['2013/3/15', 2269.31,2278.4,2250,2312.08],
618 | ['2013/3/18', 2267.29,2240.02,2239.21,2276.05],
619 | ['2013/3/19', 2244.26,2257.43,2232.02,2261.31],
620 | ['2013/3/20', 2257.74,2317.37,2257.42,2317.86],
621 | ['2013/3/21', 2318.21,2324.24,2311.6,2330.81],
622 | ['2013/3/22', 2321.4,2328.28,2314.97,2332],
623 | ['2013/3/25', 2334.74,2326.72,2319.91,2344.89],
624 | ['2013/3/26', 2318.58,2297.67,2281.12,2319.99],
625 | ['2013/3/27', 2299.38,2301.26,2289,2323.48],
626 | ['2013/3/28', 2273.55,2236.3,2232.91,2273.55],
627 | ['2013/3/29', 2238.49,2236.62,2228.81,2246.87],
628 | ['2013/4/1', 2229.46,2234.4,2227.31,2243.95],
629 | ['2013/4/2', 2234.9,2227.74,2220.44,2253.42],
630 | ['2013/4/3', 2232.69,2225.29,2217.25,2241.34],
631 | ['2013/4/8', 2196.24,2211.59,2180.67,2212.59],
632 | ['2013/4/9', 2215.47,2225.77,2215.47,2234.73],
633 | ['2013/4/10', 2224.93,2226.13,2212.56,2233.04],
634 | ['2013/4/11', 2236.98,2219.55,2217.26,2242.48],
635 | ['2013/4/12', 2218.09,2206.78,2204.44,2226.26],
636 | ['2013/4/15', 2199.91,2181.94,2177.39,2204.99],
637 | ['2013/4/16', 2169.63,2194.85,2165.78,2196.43],
638 | ['2013/4/17', 2195.03,2193.8,2178.47,2197.51],
639 | ['2013/4/18', 2181.82,2197.6,2175.44,2206.03],
640 | ['2013/4/19', 2201.12,2244.64,2200.58,2250.11],
641 | ['2013/4/22', 2236.4,2242.17,2232.26,2245.12],
642 | ['2013/4/23', 2242.62,2184.54,2182.81,2242.62],
643 | ['2013/4/24', 2187.35,2218.32,2184.11,2226.12],
644 | ['2013/4/25', 2213.19,2199.31,2191.85,2224.63],
645 | ['2013/4/26', 2203.89,2177.91,2173.86,2210.58],
646 | ['2013/5/2', 2170.78,2174.12,2161.14,2179.65],
647 | ['2013/5/3', 2179.05,2205.5,2179.05,2222.81],
648 | ['2013/5/6', 2212.5,2231.17,2212.5,2236.07],
649 | ['2013/5/7', 2227.86,2235.57,2219.44,2240.26],
650 | ['2013/5/8', 2242.39,2246.3,2235.42,2255.21],
651 | ['2013/5/9', 2246.96,2232.97,2221.38,2247.86],
652 | ['2013/5/10', 2228.82,2246.83,2225.81,2247.67],
653 | ['2013/5/13', 2247.68,2241.92,2231.36,2250.85],
654 | ['2013/5/14', 2238.9,2217.01,2205.87,2239.93],
655 | ['2013/5/15', 2217.09,2224.8,2213.58,2225.19],
656 | ['2013/5/16', 2221.34,2251.81,2210.77,2252.87],
657 | ['2013/5/17', 2249.81,2282.87,2248.41,2288.09],
658 | ['2013/5/20', 2286.33,2299.99,2281.9,2309.39],
659 | ['2013/5/21', 2297.11,2305.11,2290.12,2305.3],
660 | ['2013/5/22', 2303.75,2302.4,2292.43,2314.18],
661 | ['2013/5/23', 2293.81,2275.67,2274.1,2304.95],
662 | ['2013/5/24', 2281.45,2288.53,2270.25,2292.59],
663 | ['2013/5/27', 2286.66,2293.08,2283.94,2301.7],
664 | ['2013/5/28', 2293.4,2321.32,2281.47,2322.1],
665 | ['2013/5/29', 2323.54,2324.02,2321.17,2334.33],
666 | ['2013/5/30', 2316.25,2317.75,2310.49,2325.72],
667 | ['2013/5/31', 2320.74,2300.59,2299.37,2325.53],
668 | ['2013/6/3', 2300.21,2299.25,2294.11,2313.43],
669 | ['2013/6/4', 2297.1,2272.42,2264.76,2297.1],
670 | ['2013/6/5', 2270.71,2270.93,2260.87,2276.86],
671 | ['2013/6/6', 2264.43,2242.11,2240.07,2266.69],
672 | ['2013/6/7', 2242.26,2210.9,2205.07,2250.63],
673 | ['2013/6/13', 2190.1,2148.35,2126.22,2190.1]
674 | ]);
675 |
676 |
677 | function splitData(rawData) {
678 | var categoryData = [];
679 | var values = []
680 | for (var i = 0; i < rawData.length; i++) {
681 | categoryData.push(rawData[i].splice(0, 1)[0]);
682 | values.push(rawData[i])
683 | }
684 | return {
685 | categoryData: categoryData,
686 | values: values
687 | };
688 | }
689 |
690 | function calculateMA(dayCount) {
691 | var result = [];
692 | for (var i = 0, len = data0.values.length; i < len; i++) {
693 | if (i < dayCount) {
694 | result.push('-');
695 | continue;
696 | }
697 | var sum = 0;
698 | for (var j = 0; j < dayCount; j++) {
699 | sum += data0.values[i - j][1];
700 | }
701 | result.push(sum / dayCount);
702 | }
703 | return result;
704 | }
705 |
706 |
707 |
708 | export const candlestickOption = {
709 | tooltip: {
710 | trigger: 'axis',
711 | axisPointer: {
712 | type: 'cross'
713 | }
714 | },
715 | legend: {
716 | data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30']
717 | },
718 | grid: {
719 | left: '10%',
720 | right: '10%',
721 | bottom: '15%'
722 | },
723 | xAxis: {
724 | type: 'category',
725 | data: data0.categoryData,
726 | scale: true,
727 | boundaryGap : false,
728 | axisLine: {onZero: false},
729 | splitLine: {show: false},
730 | splitNumber: 20,
731 | min: 'dataMin',
732 | max: 'dataMax'
733 | },
734 | yAxis: {
735 | scale: true,
736 | splitArea: {
737 | show: true
738 | }
739 | },
740 | series: [
741 | {
742 | name: '日K',
743 | type: 'candlestick',
744 | data: data0.values,
745 | markPoint: {
746 | label: {
747 | normal: {
748 | formatter: function (param) {
749 | return param != null ? Math.round(param.value) : '';
750 | }
751 | }
752 | },
753 | data: [
754 | {
755 | name: 'XX标点',
756 | coord: ['2013/5/31', 2300],
757 | value: 2300,
758 | itemStyle: {
759 | normal: {color: 'rgb(41,60,85)'}
760 | }
761 | },
762 | {
763 | name: 'highest value',
764 | type: 'max',
765 | valueDim: 'highest'
766 | },
767 | {
768 | name: 'lowest value',
769 | type: 'min',
770 | valueDim: 'lowest'
771 | },
772 | {
773 | name: 'average value on close',
774 | type: 'average',
775 | valueDim: 'close'
776 | }
777 | ],
778 | tooltip: {
779 | formatter: function (param) {
780 | return param.name + '
' + (param.data.coord || '');
781 | }
782 | }
783 | },
784 | markLine: {
785 | symbol: ['none', 'none'],
786 | data: [
787 | [
788 | {
789 | name: 'from lowest to highest',
790 | type: 'min',
791 | valueDim: 'lowest',
792 | symbol: 'circle',
793 | symbolSize: 10,
794 | label: {
795 | normal: {show: false},
796 | emphasis: {show: false}
797 | }
798 | },
799 | {
800 | type: 'max',
801 | valueDim: 'highest',
802 | symbol: 'circle',
803 | symbolSize: 10,
804 | label: {
805 | normal: {show: false},
806 | emphasis: {show: false}
807 | }
808 | }
809 | ],
810 | {
811 | name: 'min line on close',
812 | type: 'min',
813 | valueDim: 'close'
814 | },
815 | {
816 | name: 'max line on close',
817 | type: 'max',
818 | valueDim: 'close'
819 | }
820 | ]
821 | }
822 | },
823 | {
824 | name: 'MA5',
825 | type: 'line',
826 | data: calculateMA(5),
827 | smooth: true,
828 | lineStyle: {
829 | normal: {opacity: 0.5}
830 | }
831 | },
832 | {
833 | name: 'MA10',
834 | type: 'line',
835 | data: calculateMA(10),
836 | smooth: true,
837 | lineStyle: {
838 | normal: {opacity: 0.5}
839 | }
840 | },
841 | {
842 | name: 'MA20',
843 | type: 'line',
844 | data: calculateMA(20),
845 | smooth: true,
846 | lineStyle: {
847 | normal: {opacity: 0.5}
848 | }
849 | },
850 | {
851 | name: 'MA30',
852 | type: 'line',
853 | data: calculateMA(30),
854 | smooth: true,
855 | lineStyle: {
856 | normal: {opacity: 0.5}
857 | }
858 | },
859 |
860 | ]
861 | };
862 |
863 |
--------------------------------------------------------------------------------