├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── build ├── rollup.config.js └── webpack.config.js ├── docs ├── .nojekyll ├── bar.md ├── bmap.md ├── event.md ├── favicon.ico ├── funnel.md ├── heatmap.md ├── histogram.md ├── index.html ├── install.md ├── line.md ├── map.md ├── pie.md ├── props-demo1.md ├── props-demo2.md ├── props.md ├── radar.md ├── ring.md ├── sankey.md ├── sidebar.md ├── skill-demo.md ├── start.md ├── style.css ├── toggle.md └── waterfall.md ├── examples ├── App.vue ├── components │ ├── code-section.vue │ └── sidebar.vue ├── data │ ├── bar.js │ ├── chart.js │ ├── funnel.js │ ├── global.js │ ├── heatmap.js │ ├── histogram.js │ ├── index.js │ ├── line.js │ ├── map.js │ ├── pie.js │ ├── radar.js │ ├── ring.js │ ├── sankey.js │ └── waterfall.js ├── favicon.ico ├── index.html ├── main.js ├── pages │ ├── bmap.vue │ ├── chart.vue │ ├── eventer.vue │ ├── install.vue │ ├── test.vue │ └── toggle.vue ├── router.js └── static │ └── logo.png ├── package.json ├── src ├── component-list.js ├── components │ ├── data-empty.vue │ └── loading.vue ├── core.js ├── echarts-base.js ├── index.es.js ├── packages │ ├── bar-mini │ │ ├── index.js │ │ └── main.js │ ├── bar │ │ ├── index.js │ │ └── main.js │ ├── bmap │ │ ├── index.js │ │ └── main.js │ ├── chart │ │ └── index.js │ ├── funnel │ │ ├── index.js │ │ └── main.js │ ├── heatmap │ │ ├── index.js │ │ └── main.js │ ├── histogram-mini │ │ └── index.js │ ├── histogram │ │ └── index.js │ ├── index │ │ └── index.js │ ├── line-mini │ │ ├── index.js │ │ └── main.js │ ├── line │ │ ├── index.js │ │ └── main.js │ ├── map │ │ ├── index.js │ │ └── main.js │ ├── pie │ │ ├── index.js │ │ └── main.js │ ├── radar │ │ ├── index.js │ │ └── main.js │ ├── ring │ │ └── index.js │ ├── sankey │ │ ├── index.js │ │ └── main.js │ └── waterfall │ │ ├── index.js │ │ └── main.js └── utils.js ├── test ├── index.js ├── karma.conf.js └── load │ ├── cdn │ ├── all │ │ └── index.html │ ├── bmap │ │ └── index.html │ ├── heatmap │ │ └── index.html │ └── line │ │ └── index.html │ └── webpack │ ├── all │ ├── App.vue │ ├── index.js │ └── webpack.config.js │ ├── css-part │ ├── App.vue │ ├── index.js │ └── webpack.config.js │ ├── esm │ ├── App.vue │ ├── index.js │ └── webpack.config.js │ ├── heatmap │ ├── App.vue │ ├── index.js │ └── webpack.config.js │ ├── index.html │ └── line │ ├── App.vue │ ├── index.js │ └── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["latest", { 4 | "es2015": { "modules": false } 5 | }], 6 | "stage-2" 7 | ], 8 | "plugins": ["transform-object-assign"] 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/* 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | extends: 'standard', 13 | plugins: [ 14 | 'html' 15 | ], 16 | rules: { 17 | 'no-mixed-operators': 'off' 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### Check List 2 | - [ ] Every Commit message is meaningful 3 | - [ ] Synchronized with the master branch 4 | - [ ] CI passed 5 | - [ ] Add suitable label 6 | 7 | #### What Changed 8 | - 9 | 10 | #### Breaking Change 11 | - [ ] Yes 12 | - [ ] No 13 | 14 | #### Document Update 15 | - [ ] Yes 16 | - [ ] No 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | umd 3 | node_modules 4 | dist 5 | npm-debug.log 6 | yarn-error.log 7 | lib 8 | docs/index.min.js 9 | docs/style.min.css 10 | .idea/ 11 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | build 2 | examples 3 | docs 4 | .babelrc 5 | .eslintrc.js 6 | .travis.yml 7 | yarn.lock 8 | node_modules 9 | yarn-error.log 10 | npm-debug.log 11 | dist 12 | test 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | branches: 5 | only: 6 | - master 7 | install: 8 | - yarn 9 | script: 10 | - npm run build 11 | - npm run test 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # t-charts 2 | 3 | [![Build Status](https://travis-ci.org/ElemeFE/v-charts.svg?branch=master)](https://travis-ci.org/ElemeFE/v-charts) 4 | [![NPM downloads](http://img.shields.io/npm/dm/v-charts.svg)](https://npmjs.org/package/v-charts) 5 | ![JS gzip size](http://img.badgesize.io/https://unpkg.com/v-charts/lib/index.js?compression=gzip&label=gzip%20size:%20JS) 6 | [![Npm package](https://img.shields.io/npm/v/v-charts.svg)](https://www.npmjs.org/package/v-charts) 7 | ![Language](https://img.shields.io/badge/language-javascript-yellow.svg) 8 | ![License](https://img.shields.io/badge/license-MIT-000000.svg) 9 | [![Join the chat at https://gitter.im/ElemeFE/v-charts](https://badges.gitter.im/ElemeFE/v-charts.svg)](https://gitter.im/ElemeFE/v-charts?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 10 | 11 | 在使用echarts生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,t-charts的出现正是为了解决这个 12 | 痛点。基于Vue2.0和echarts封装的t-charts图表组件,只需要统一提供一种对前后端都友好的数据格式 13 | 设置简单的配置项,便可轻松生成常见的图表。 14 | 15 | ### 文档 16 | 17 | [https://talkingdata.github.io/t-charts/](https://talkingdata.github.io/t-charts/#/) 18 | 19 | ### 安装 20 | --- 21 | 22 | ``` 23 | npm i t-charts -S 24 | ``` 25 | 26 | ### 快速上手 27 | --- 28 | 29 | ```html 30 | 35 | 36 | 56 | ``` 57 | 58 | ### LICENSE 59 | --- 60 | 61 | MIT 62 | -------------------------------------------------------------------------------- /build/rollup.config.js: -------------------------------------------------------------------------------- 1 | const rollup = require('rollup') 2 | const vue = require('rollup-plugin-vue') 3 | const resolve = require('rollup-plugin-node-resolve') 4 | const babel = require('rollup-plugin-babel') 5 | const eslint = require('rollup-plugin-eslint') 6 | const componentInfo = require('../src/component-list') 7 | const uglify = require('rollup-plugin-uglify') 8 | const autoprefixer = require('autoprefixer') 9 | const cssnano = require('cssnano') 10 | 11 | let pkg = [] 12 | const pkgTypeList = [ 13 | { type: 'cjs', min: false, suffix: '.common.js' }, 14 | { type: 'cjs', min: true, suffix: '.common.min.js' }, 15 | { type: 'umd', min: false, suffix: '.js' }, 16 | { type: 'umd', min: true, suffix: '.min.js' } 17 | ] 18 | 19 | pkgTypeList.forEach(({ type, min, suffix }) => { 20 | Object.keys(componentInfo).forEach(name => { 21 | const { src, dist } = componentInfo[name] 22 | pkg.push({ 23 | min, 24 | type, 25 | suffix, 26 | globalName: name, 27 | src, 28 | dist 29 | }) 30 | }) 31 | }) 32 | 33 | const addons = [ 34 | { 35 | min: false, 36 | type: 'es', 37 | suffix: '.esm.js', 38 | globalName: '', 39 | src: 'src/index.es.js', 40 | dist: 'lib/index' 41 | } 42 | ] 43 | pkg = pkg.concat(addons) 44 | 45 | pkg.forEach(item => { rollupFn(item) }) 46 | 47 | function rollupFn (item) { 48 | const vueSettings = item.min 49 | ? { css: 'lib/style.min.css', postcss: [autoprefixer, cssnano] } 50 | : { css: 'lib/style.css', postcss: [autoprefixer] } 51 | 52 | const plugins = [ 53 | eslint({ 54 | throwError: true, 55 | exclude: 'node_modules/**' 56 | }), 57 | vue(vueSettings), 58 | resolve({ 59 | extensions: ['.js', '.vue'] 60 | }), 61 | babel({ 62 | exclude: 'node_modules/**', 63 | plugins: ['external-helpers'] 64 | }) 65 | ] 66 | if (item.min) plugins.push(uglify()) 67 | 68 | rollup.rollup({ 69 | entry: item.src, 70 | external: id => /^echarts/.test(id), 71 | plugins 72 | }).then(function (bundle) { 73 | const dest = item.dist + item.suffix 74 | 75 | bundle.write({ 76 | format: item.type, 77 | moduleName: item.globalName, 78 | globals: { 79 | 'echarts/lib/echarts': 'echarts' 80 | }, 81 | dest 82 | }) 83 | }).catch((e) => { 84 | console.log(e) 85 | process.exit(1) 86 | }) 87 | } 88 | -------------------------------------------------------------------------------- /build/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const webpack = require('webpack') 3 | const CopyWebpackPlugin = require('copy-webpack-plugin') 4 | const HtmlWebpackPlugin = require('html-webpack-plugin') 5 | const opn = require('opn') 6 | 7 | opn('http://localhost:8099') 8 | function resolve (dir) { 9 | return path.join(__dirname, '..', dir) 10 | } 11 | 12 | module.exports = { 13 | entry: { 14 | app: './examples/main.js' 15 | }, 16 | output: { 17 | path: path.resolve(__dirname, '../dist'), 18 | filename: 'index.js', 19 | publicPath: '/' 20 | }, 21 | resolve: { 22 | extensions: ['.js', '.vue'], 23 | alias: { 24 | 'vue$': 'vue/dist/vue.esm.js', 25 | '@': './src' 26 | } 27 | }, 28 | devServer: { 29 | port: '8099', 30 | hot: true, 31 | contentBase: path.join(__dirname, 'dist'), 32 | stats: 'errors-only' 33 | }, 34 | module: { 35 | rules: [ 36 | { 37 | test: /\.(js|vue)$/, 38 | loader: 'eslint-loader', 39 | enforce: 'pre', 40 | include: [resolve('examples'), resolve('src')], 41 | options: { 42 | formatter: require('eslint-friendly-formatter') 43 | } 44 | }, 45 | { 46 | test: /\.vue$/, 47 | loader: 'vue-loader', 48 | options: { 49 | sourceMap: true 50 | } 51 | }, 52 | { 53 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 54 | loader: 'url-loader', 55 | options: { 56 | limit: 10000, 57 | name: 'img/[name].[hash:7].[ext]' 58 | } 59 | }, 60 | { 61 | test: /\.js$/, 62 | loader: 'babel-loader', 63 | include: [resolve('./src'), resolve('./examples')] 64 | }, 65 | { 66 | test: /\.css$/, 67 | use: [ 'style-loader', 'css-loader' ] 68 | } 69 | ] 70 | }, 71 | plugins: [ 72 | new CopyWebpackPlugin([ 73 | { 74 | from: path.resolve(__dirname, '../examples/favicon.ico') 75 | } 76 | ]), 77 | new webpack.DefinePlugin({ 78 | 'process.env': { 79 | NODE_ENV: '"development"' 80 | } 81 | }), 82 | new webpack.HotModuleReplacementPlugin(), 83 | new HtmlWebpackPlugin({ 84 | filename: 'index.html', 85 | template: './examples/index.html', 86 | inject: true 87 | }) 88 | ] 89 | } 90 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalkingData/t-charts/d553261687e19c92be2333421f74cb8e0fc86e4d/docs/.nojekyll -------------------------------------------------------------------------------- /docs/bar.md: -------------------------------------------------------------------------------- 1 | ### 条形图 2 | 3 | #### 示例 4 | 5 | 6 | 7 | #### 指定指标维度 8 | 9 | 10 | 11 | 37 | 38 | 39 | #### 排序条形图 40 | 41 | 42 | 43 | 72 | 73 | 74 | #### 条形轴配置双y轴 75 | 76 | 77 | 78 | 107 | 108 | 109 | #### 设置legend别名漏斗图 110 | 111 | 112 | 113 | 140 | 141 | 142 | #### 堆叠条形图 143 | 144 | 145 | 146 | 173 | 174 | 175 | #### 设置纵轴为连续的数值轴 176 | 177 | 178 | 179 | 204 | 205 | 206 | #### settings 配置项 207 | 208 | | 配置项 | 简介 | 类型 | 备注 | 209 | | --- | --- | --- | --- | 210 | | dimension | 维度 | Array | 默认columns第一项为维度 | 211 | | metrics | 指标 | Array | 默认columns第二项起为指标 | 212 | | xAxisType | 上下坐标轴数据类型 | Array | 可选值: KMB, normal, percent | 213 | | xAxisName | 上下坐标轴标题 | Array | - | 214 | | axisSite | 指标所在的轴 | Object | 默认不在top轴的指标都在bottom轴 | 215 | | stack | 堆叠选项 | Object | - | 216 | | digit | 设置数据类型为percent时保留的位数 | Number | 默认为2 | 217 | | dataOrder | 设置数据排序方式 | Boolean, Object | 默认为false | 218 | | scale | 是否是脱离 0 值比例 | Array | 默认为[false, false],表示左右
两个轴都不会脱离0值比例。
设置成 true 后坐标刻度不会
强制包含零刻度
| 219 | | min | 左右坐标轴最小值 | Array | - | 220 | | max | 左右坐标轴最大值 | Array | - | 221 | | labelMap | 设置指标的别名,同时作用于提示框和图例| Object | - | 222 | | legendName | 设置图表上方图例的别名 | Object | - | 223 | | label | 设置图形上的文本标签 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-bar.label) | 224 | | itemStyle | 图形样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-bar.itemStyle) | 225 | | yAxisType | 纵轴的类型 | String | 可选值'category','value',默认为'category' | 226 | | opacity | 透明度 | Number | - | 227 | 228 | > 备注1. axisSite 可以设置 top 和 bottom,例如示例所示 `axisSite: { top: ['占比'] }` 即将占比的数据置于上轴上。 229 | 230 | > 备注2. stack 用于将两数据堆叠起来,例如实例中所示`stack: { '销售额': ['销售额-1季度', '销售额-2季度'] }` 即将'销售额-1季度', '销售额-2季度'相应的数据堆叠在一起。 231 | 232 | > 备注3. dataOrder 用于设置数据的排序方式,用于更加清晰的展示数据的升降。例如: `{ label: '成本', order: 'asc }` 表示数据按照成本指标升序展示,降序为`desc`。 233 | 234 | > 备注4. min和max的值可以直接设置为数字,例如:`[100, 300]`;也可以设置为`['dataMin', 'dataMin']`, `['dataMax', 'dataMax']`,此时表示使用该坐标轴上的最小值或最大值为最小或最大刻度。 235 | 236 | > 备注5. 为了优化连续的数值型横轴显示多指标的时候样式,在此情况下默认设置opacity为0.5。 237 | -------------------------------------------------------------------------------- /docs/bmap.md: -------------------------------------------------------------------------------- 1 | ### 百度地图 2 | 3 | 为了使在echarts上更简单的使用百度地图,t-charts封装了一个百度地图的‘壳子’,在settings中添加 4 | 关于图表的配置(key,bmap),在组件上直接设置 series, tooltip 等,便可生成以百度地图为坐标系 5 | 的 Echarts 图表。 6 | 7 | #### 示例 8 | 9 | ##### 简单地图 10 | 11 | 12 | 13 | #### 获取地图实例 14 | 15 | 16 | 17 | 18 | #### settings 配置项 19 | 20 | | 配置项 | 简介 | 类型 | 备注 | 21 | | --- | --- | --- | --- | 22 | | key | 百度地图 access_key | String | 可[由此](http://lbsyun.baidu.com/apiconsole/key)获取 | 23 | | bmap | 百度地图配置项 | Object | 参考[文档](https://github.com/ecomfe/echarts/tree/master/extension/bmap#使用)配置 | 24 | 25 | > 备注:百度地图在与其他地图搭配使用时,需要额外引入相应的 echarts 模块,例如使用热力图,则需 26 | 要`import 'echarts/lib/chart/heatmap'`。 27 | -------------------------------------------------------------------------------- /docs/event.md: -------------------------------------------------------------------------------- 1 | ### 事件监听 2 | 3 | #### 示例 4 | 5 | 6 | 7 | 绑定事件通过传递一个带绑定事件和对应回调函数的对象实现,回调函数内的参数是点击部分,可以据此做相应的处理 8 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalkingData/t-charts/d553261687e19c92be2333421f74cb8e0fc86e4d/docs/favicon.ico -------------------------------------------------------------------------------- /docs/funnel.md: -------------------------------------------------------------------------------- 1 | ### 漏斗图 2 | 3 | #### 示例 4 | 5 | 6 | 7 | #### 指定指标维度 8 | 9 | 10 | 11 | 35 | 36 | 37 | #### 定制顺序漏斗图 38 | 39 | 40 | 41 | 64 | 65 | 66 | #### 指定数据类型漏斗图 67 | 68 | 69 | 70 | 93 | 94 | 95 | #### 修改legend别名漏斗图 96 | 97 | 98 | 99 | 124 | 125 | 126 | #### 金字塔 127 | 128 | 129 | 130 | 153 | 154 | 155 | #### settings 配置项 156 | 157 | | 配置项 | 简介 | 类型 | 备注 | 158 | | --- | --- | --- | --- | 159 | | dimension | 维度 | String | 默认columns第一项为维度 | 160 | | metrics | 指标 | String | 默认columns第二项为指标 | 161 | | dataType | 数据类型 | String | 可选值: KMB, normal, percent | 162 | | sequence | 数据显示顺序 | Array | 默认按照数据大小顺序 | 163 | | ascending | 是否显示为金字塔 | Boolean | 默认为false | 164 | | digit | 设置数据类型为percent时保留的位数 | Number | 默认为2 | 165 | | label | 设置文本标签样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-funnel.label) | 166 | | labelLine | 设置标签的视觉引导线样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-funnel.labelLine) | 167 | | itemStyle | 设置图形样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-funnel.itemStyle) | 168 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | t-charts 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 24 | 25 |
26 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | ### 安装 2 | 3 | #### npm安装 4 | 5 | ``` 6 | npm i t-charts -S 7 | ``` 8 | 9 | #### cdn 10 | 11 | ```html 12 | 13 | 14 | 15 | ``` 16 | 17 | #### 示例 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/props-demo1.md: -------------------------------------------------------------------------------- 1 | ### 属性配置示例(1) 2 | 3 | #### 隐藏提示框与图例 4 | 5 | 6 | 7 | 33 | 34 | 35 | #### 设置图表容器样式 36 | 37 | 38 | 39 | 71 | 72 | 73 | #### 设置图表标线与标点 74 | 75 | 76 | 77 | 122 | 123 | 124 | #### 设置视觉映射组件 125 | 126 | 127 | 128 | 169 | 170 | 171 | #### 设置区域缩放组件 172 | 173 | 174 | 175 | 209 | 210 | 211 | #### 设置工具箱 212 | 213 | 214 | 215 | 248 | 249 | 250 | #### 修改颜色列表 251 | 252 | 253 | 254 | 280 | 281 | 282 | -------------------------------------------------------------------------------- /docs/props-demo2.md: -------------------------------------------------------------------------------- 1 | ### 属性配置示例(2) 2 | 3 | #### 设置extend配置项 4 | 5 | 6 | 7 | 56 | 57 | 58 | #### 设置afterConfig函数 59 | 60 | 61 | 62 | 95 | 96 | 97 | #### 设置加载状态 98 | 99 | 100 | 101 | 131 | 132 | 133 | #### 设置暂无数据状态 134 | 135 | 136 | 137 | 160 | 161 | 162 | #### 增加自定义内容 163 | 164 | 165 | 166 | 202 | 203 | -------------------------------------------------------------------------------- /docs/props.md: -------------------------------------------------------------------------------- 1 | ### t-charts属性 2 | 3 | ##### t-charts 的属性分为两种,一种是全部图表都具有的属性,例如 `colors`, `grid` 等 4 | 5 | `` 6 | 7 | 这样的属性有 8 | 9 | | 配置项 | 简介 | 类型 | 备注 | 10 | | --- | --- | --- | --- | 11 | | data | 图表数据 | Object | columns 代表指标和维度名称,
rows 为数据内容 | 12 | | width | 图表宽度 | String | 默认 auto | 13 | | height | 图表高度 | String | 默认 400px | 14 | | settings | 图表配置项 | Object | 内容参考图表具体的配置 | 15 | | colors | 颜色列表 | Array | 默认
`['#19d4ae', '#5ab1ef', '#fa6e86',`
` '#ffb980', '#0067a6', '#c4b4e4',`
` '#d87a80', '#9cbbff', '#d9d0c7',`
` '#87a997', '#d49ea2', '#5b4947']` | 16 | | tooltip-visible | 是否显示提示框 | Boolean | 默认为 true | 17 | | legend-visible | 是否显示图例 | Boolean | 默认为 true | 18 | | legend-position | 图例显示位置 | String | 可选`'left', 'top', 'right', 'bottom'` | 19 | | grid | 网格配置 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#grid) | 20 | | events | 为图表绑定事件 | Object | 内容为包含事件名-事件处理函数的对象 | 21 | | before-config | 对数据提前进行额外的处理 | Function | 在数据转化为配置项开始前触发
参数为 data,返回值为表格数据 | 22 | | after-config | 对生成好的echarts配置
进行额外的处理 | Function | 在数据转化为配置项结束后触发
参数为 options,返回值为 echarts 配置 | 23 | | after-set-option | 生成图后获取echarts实例 | Function | 参数为echarts实例 | 24 | | after-set-option-once | 生成图后获取echarts实例(只执行一次) | Function | 参数为echarts实例 | 25 | | mark-line | 图表标线 | Object | 配置项内容对应echarts中
关于markLine的部分
使用时需额外引入对应模块
`'echarts/lib/component/markLine'` | 26 | | mark-point | 图表标点 | Object | 配置项内容对应echarts中
关于markPoint的部分
使用时需额外引入对应模块
`'echarts/lib/component/markPoint'` | 27 | | mark-area | 图表标志区域 | Object | 配置项内容对应echarts中
关于markArea的部分
使用时需额外引入对应模块
`'echarts/lib/component/markAreae'` | 28 | | visual-map | 视觉映射组件 | Array, Object | 内容参考[文档](http://echarts.baidu.com/option.html#visualMap)
使用时需额外引入对应模块
`'echarts/lib/component/visualMap'` | 29 | | data-zoom | 区域缩放组件 | Array, Object | 内容参考[文档](http://echarts.baidu.com/option.html#dataZoom)
使用时需额外引入对应模块
`'echarts/lib/component/dataZoom'` | 30 | | toolbox | 工具箱 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#toolbox)
使用时需额外引入对应模块
`'echarts/lib/component/toolbox'` | 31 | | title | 图表标题 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#title)
使用时需额外引入对应模块
`'echarts/lib/component/title'` | 32 | | init-options | init 附加参数 | Object | 内容参考[文档](http://echarts.baidu.com/api.html#echarts.init) | 33 | | theme | 自定义主题 | Object | 内容为自定义主题参数 | 34 | | theme-name | 自定义主题名称 | String | 内容为全局注册的自定义主题名称 | 35 | | loading | 加载状态 | Boolean | 默认为false | 36 | | data-empty | 暂无数据状态 | Boolean | 默认为false | 37 | | judge-width | 是否处理生成图表时的宽度问题 | Boolean | 默认为 true | 38 | | width-change-delay | 容器宽度变化的延迟 | Number | 默认为300 | 39 | 40 | > 备注:使用loading和dataEmpty属性前需引入css `import 't-charts/lib/style.css'` 41 | 42 | 同时,为了能够更方便的设置属性配置项等,可以通过`extend`属性实现对已配置好的内部属性进行单独的设置,`extend`为对象类型,对象内的属性可以是函数,也可以对象,也可以是其他类型的值 43 | - 当属性为函数时,设置的是函数的返回值 44 | - 当属性为对象时,如果在options中对应的属性为对象(eg: tooltip)或包含对象的数组(eg: series),对应的配置会被合并,否则将直接覆盖对应的配置 45 | 46 | 具体使用方法可以参考下面的属性配置示例 47 | 48 | 最后,下面这些与echarts配置项对应的属性也被加到了组件上,设置后将会直接覆盖options原有的对应属性,使用方式可参考[文档](http://echarts.baidu.com/option.html) 49 | ``` 50 | legend: Object 51 | xAxis: Object 52 | yAxis: Object 53 | radar: Object 54 | tooltip: Object 55 | axisPointer: Object 56 | brush: Object 57 | geo: Object 58 | timeline: Object 59 | graphic: Object 60 | series: [Object, Array] 61 | backgroundColor: [Object, String] 62 | textStyle: Object 63 | ``` 64 | 65 | > 备注:如果某属性加上去之后没有生效,很可能是没有引入相应的模块,模块的位置可以参考此[文件](https://github.com/ecomfe/echarts/blob/master/index.js) 66 | 67 | 68 | ##### 另外一种是图表自身的属性,比如用户设置数据类型的`dataType`,这样的属性被置于settings内,每种图表的配置项不完全相同,具体参数参考下述图表文档中的配置项 69 | 70 | ### 示例 71 | 72 | 73 | -------------------------------------------------------------------------------- /docs/radar.md: -------------------------------------------------------------------------------- 1 | ### 雷达图 2 | 3 | #### 示例 4 | 5 | 6 | 7 | #### 设置显示的指标维度 8 | 9 | 10 | 11 | 38 | 39 | 40 | #### 修改指标名称 41 | 42 | 43 | 44 | 75 | 76 | 77 | #### settings 配置项 78 | 79 | | 配置项 | 简介 | 类型 | 备注 | 80 | | --- | --- | --- | --- | 81 | | dimension | 维度 | String | 默认columns第一项为维度 | 82 | | metrics | 指标 | String | 默认columns第二项起为指标 | 83 | | dataType | 数据类型 | Object | 可选值: KMB, normal, percent | 84 | | digit | 设置数据类型为percent时保留的位数 | Number | 默认为2 | 85 | | label | 图形上的文本标签 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-radar.label) | 86 | | itemStyle | 折线拐点标志的样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-radar.itemStyle) | 87 | | lineStyle | 线条样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-radar.lineStyle) | 88 | | areaStyle | 区域填充样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-radar.areaStyle) | 89 | 90 | 91 | > 备注:dataType中直接设置对应维度的数据类型,例如示例的`{ '占比': 'percent' }`,即将占比数据设置为百分比类型 92 | -------------------------------------------------------------------------------- /docs/ring.md: -------------------------------------------------------------------------------- 1 | ### 环图 2 | 3 | #### 示例 4 | 5 | 6 | 7 | #### 设置指标维度 8 | 9 | 10 | 11 | 37 | 38 | 39 | #### 玫瑰图 40 | 41 | 42 | 43 | 68 | 69 | 70 | #### 限制显示条数环图 71 | 72 | 73 | 74 | 104 | 105 | 106 | #### 设置数据类型 107 | 108 | 109 | 110 | 135 | 136 | 137 | #### 设置环图半径 138 | 139 | 140 | 141 | 167 | 168 | 169 | #### settings 配置项 170 | 171 | | 配置项 | 简介 | 类型 | 备注 | 172 | | --- | --- | --- | --- | 173 | | dimension | 维度 | String | 默认columns第一项为维度 | 174 | | metrics | 指标 | String | 默认columns第二项为指标 | 175 | | dataType | 数据类型 | String | 可选值: KMB, normal, percent | 176 | | legendLimit | legend显示数量限制 | Number | legend数量过多会导致环图样式错误,限制legend最大值并且当超过此值时,隐藏legend可以解决这个问题 | 177 | | selectedMode | 选中模式 | String | 可选值:single, multiple,默认为false | 178 | | hoverAnimation | 是否开启 hover 在扇区上的放大动画效果 | Boolean | 默认值为true | 179 | | radius | 环图外半径与内半径 | Array | - | 180 | | offsetY | 纵向偏移量 | Number | - | 181 | | digit | 设置数据类型为percent时保留的位数 | Number | 默认为2 | 182 | | roseType | 显示为南丁格尔玫瑰图 | String | 默认不展示为南丁格尔玫瑰图,可设置为`'radius', 'area'` | 183 | | label | 环图图形上的文本标签 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-pie.label) | 184 | | labelLine | 标签的视觉引导线样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-pie.labelLine) | 185 | | itemStyle | 图形样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-pie.itemStyle) | 186 | | limitShowNum | 设置超过此数字时使用‘其他’代替 | Number | 此时数据会按照由大到小顺序显示 | 187 | -------------------------------------------------------------------------------- /docs/sankey.md: -------------------------------------------------------------------------------- 1 | ### 桑基图 2 | 3 | #### 示例 4 | 5 | 6 | 7 | #### 设置数据类型 8 | 9 | 10 | 11 | 45 | 46 | 47 | 48 | 49 | #### settings 配置项 50 | 51 | | 配置项 | 简介 | 类型 | 备注 | 52 | | --- | --- | --- | --- | 53 | | dimension | 维度 | String | 默认columns第一项为维度 | 54 | | metrics | 指标 | String | 默认columns第二项为指标 | 55 | | dataType | 数据类型 | Array | 数组的第一项为item的数据类型,
第二项为line的数据类型,
可选值: KMB, normal, percent | 56 | | links | 节点间的关系数据 | Array | 内容参考[文档](http://echarts.baidu.com/option.html#series-sankey.links) | 57 | | digit | 设置数据类型为percent时保留的位数 | Number | 默认为2 | 58 | | label | 每个矩形节点中文本标签的样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-sankey.label) | 59 | | itemStyle | 节点矩形的样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-sankey.itemStyle) | 60 | | lineStyle | 桑基图边的样式 | Object | 内容参考[文档](http://echarts.baidu.com/option.html#series-sankey.lineStyle) | 61 | -------------------------------------------------------------------------------- /docs/sidebar.md: -------------------------------------------------------------------------------- 1 | - 介绍 2 | - [安装](/) 3 | - [开始使用](/start) 4 | - [图表属性](/props) 5 | - 图表 6 | - [折线图](/line) 7 | - [柱状图](/histogram) 8 | - [条形图](/bar) 9 | - [饼图](/pie) 10 | - [环图](/ring) 11 | - [瀑布图](/waterfall) 12 | - [漏斗图](/funnel) 13 | - [雷达图](/radar) 14 | - [地图](/map) 15 | - [桑基图](/sankey) 16 | - [热力图](/heatmap) 17 | - 其他 18 | - [事件监听](/event) 19 | - [图表切换](/toggle) 20 | - [百度地图](/bmap) 21 | - [属性配置示例(1)](/props-demo1) 22 | - [属性配置示例(2)](/props-demo2) 23 | - [常见问题示例](/skill-demo) 24 | -------------------------------------------------------------------------------- /docs/skill-demo.md: -------------------------------------------------------------------------------- 1 | ### 常见问题示例 2 | 3 | #### 容器的初始宽度未知 4 | 5 | 在一个初始宽度未知的容器内绘制图表时,因为无法获取宽度,所以图表会绘制失败,解决的办法是在容器宽度已知后, 6 | 调用echarts的resize方法。 7 | 8 | 9 | 10 | 57 | 58 | 59 | #### 小数显示精度 60 | 61 | t-charts处理数据类型时默认保留两位有效数字,但是当数字较小并设置为百分比类型时,这种方式会导致显示上的问题,例如 62 | 63 | 64 | 65 | 91 | 92 | 93 | 每个图表内都有digit配置项,设置此属性,保证设置类型后,数值较小也能够正常显示 94 | 95 | 96 | 97 | 124 | 125 | -------------------------------------------------------------------------------- /docs/start.md: -------------------------------------------------------------------------------- 1 | ## t-charts 2 | 3 | 在使用 echarts 生成图表时,经常需要做繁琐的数据类型转化、修改复杂的配置项,t-charts 的出现正是为了解决这个痛点。基于 Vue2.0 和 echarts 封装的 t-charts 图表组件,只需要统一提供一种对前后端都友好的数据格式设置简单的配置项,便可轻松生成常见的图表。 4 | 5 | t-charts 已经处理了关于echarts依赖引入的问题,保证所使用的图表,都是最小的文件。 6 | 7 | ### 引入t-charts 8 | 9 | #### 完整引入 10 | ----- 11 | 12 | ```js 13 | // main.js 14 | import Vue from 'vue' 15 | import VCharts from 't-charts' 16 | import App from './App.vue' 17 | 18 | Vue.use(VCharts) 19 | 20 | new Vue({ 21 | el: '#app', 22 | render: h => h(App) 23 | }) 24 | ``` 25 | 26 | #### 按需引入 27 | ----- 28 | 29 | t-charts的每种图表组件,都单独打包到lib文件夹下 30 | ``` 31 | |- lib/ 32 | |- line.js -------------- 折线图 33 | |- bar.js --------------- 条形图 34 | |- histogram.js --------- 柱状图 35 | |- pie.js --------------- 饼图 36 | |- ring.js -------------- 环图 37 | |- funnel.js ------------ 漏斗图 38 | |- waterfall.js --------- 瀑布图 39 | |- radar.js ------------- 雷达图 40 | |- map.js --------------- 地图 41 | |- bmap.js -------------- 百度地图 42 | ``` 43 | 使用时,可以直接将单个图表引入到项目中 44 | ```js 45 | import Vue from 'vue' 46 | import VeLine from 't-charts/lib/line' 47 | import App from './App.vue' 48 | 49 | Vue.component(VeLine.name, VeLine) 50 | 51 | new Vue({ 52 | el: '#app', 53 | render: h => h(App) 54 | }) 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | iframe { 2 | border: 2px solid #eee; 3 | } 4 | 5 | .vuep { 6 | height: 460px; 7 | } 8 | 9 | .cm-error { 10 | color: rgba(255, 83, 112, 1) !important; 11 | background-color: inherit !important; 12 | } 13 | 14 | .data-empty { 15 | position: absolute; 16 | left: 0; 17 | right: 0; 18 | top: 0; 19 | bottom: 0; 20 | display: flex; 21 | justify-content: center; 22 | align-items: center; 23 | background-color: rgba(255, 255, 255, .7); 24 | color: #888; 25 | font-size: 14px; 26 | } 27 | -------------------------------------------------------------------------------- /docs/toggle.md: -------------------------------------------------------------------------------- 1 | ### 图表切换 2 | 3 | #### 示例 4 | 5 | 6 | 7 | 为了方便使用一份数据即可生成不同的表格,可以使用``组件,切换图表类型则只需要改变settings即可 8 | -------------------------------------------------------------------------------- /docs/waterfall.md: -------------------------------------------------------------------------------- 1 | ### 瀑布图 2 | 3 | #### 示例 4 | 5 | 6 | 7 | #### 设置指标维度 8 | 9 | 10 | 11 | 34 | 35 | 36 | #### 设置数据类型 37 | 38 | 39 | 40 | 62 | 63 | 64 | #### 修改指标名称 65 | 66 | 67 | 68 | 92 | 93 | 94 | #### 设置 总计、剩余 的名称 95 | 96 | 97 | 98 | 122 | 123 | 124 | #### settings 配置项 125 | 126 | | 配置项 | 简介 | 类型 | 备注 | 127 | | --- | --- | --- | --- | 128 | | dimension | 维度 | String | 默认columns第一项为维度 | 129 | | metrics | 指标 | String | 默认columns第二项为指标 | 130 | | dataType | 数据类型 | String | 可选值: KMB, normal, percent | 131 | | totalNum | 总量 | Number | 默认瀑布图总量为所有数据的和 | 132 | | totalName | 总量的显示文案 | String | 默认显示总计 | 133 | | remainName | 剩余的显示文案 | String | 默认显示其他 | 134 | | digit | 设置数据类型为percent时保留的位数 | Number | 默认为2 | 135 | -------------------------------------------------------------------------------- /examples/App.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 27 | 28 | 75 | -------------------------------------------------------------------------------- /examples/components/code-section.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 32 | 33 | 39 | -------------------------------------------------------------------------------- /examples/components/sidebar.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 42 | 43 | 90 | -------------------------------------------------------------------------------- /examples/data/bar.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '条形图', 3 | type: 'bar', 4 | data: [ 5 | { 6 | name: '简单条形图', 7 | data: { 8 | columns: ['日期', '余额', '年龄'], 9 | rows: [ 10 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 11 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 12 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 13 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 14 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 15 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 16 | ] 17 | }, 18 | settings: {} 19 | }, 20 | { 21 | name: '排序条形图', 22 | data: { 23 | columns: ['日期', '余额', '年龄'], 24 | rows: [ 25 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 26 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 27 | { '日期': '1-3', '余额': 2123, '年龄': 90 }, 28 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 29 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 30 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 31 | ] 32 | }, 33 | settings: { 34 | metrics: ['年龄'], 35 | dataOrder: { 36 | label: '年龄', 37 | order: 'desc' 38 | } 39 | } 40 | }, 41 | { 42 | name: '带有较小百分比数值', 43 | data: { 44 | columns: ['日期', '比率'], 45 | rows: [ 46 | { '日期': '1-1', '余额': 123, '比率': 0.00001 }, 47 | { '日期': '1-2', '余额': 1223, '比率': 0.00002 }, 48 | { '日期': '1-3', '余额': 2123, '比率': 0.00003 }, 49 | { '日期': '1-4', '余额': 4123, '比率': 0.00007 }, 50 | { '日期': '1-5', '余额': 3123, '比率': 0.00001 }, 51 | { '日期': '1-6', '余额': 7123, '比率': 0.00003 } 52 | ] 53 | }, 54 | settings: { 55 | xAxisType: ['percent'], 56 | digit: 4 57 | } 58 | }, 59 | { 60 | name: '坐标轴配置', 61 | data: { 62 | columns: ['日期', '余额', '年龄'], 63 | rows: [ 64 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 65 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 66 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 67 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 68 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 69 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 70 | ] 71 | }, 72 | settings: { 73 | xAxisType: ['KMB', 'percent'], 74 | xAxisName: ['余额', '年龄'], 75 | axisSite: { 76 | top: ['年龄'] 77 | } 78 | } 79 | }, 80 | { 81 | name: '复杂坐标轴配置', 82 | data: { 83 | columns: ['日期', 'a', 'b', 'c'], 84 | rows: [ 85 | { '日期': '1-1', 'a': 123, 'b': 3, c: 1 }, 86 | { '日期': '1-2', 'a': 1223, 'b': 6, c: 1 }, 87 | { '日期': '1-3', 'a': 2123, 'b': 9, c: 1 }, 88 | { '日期': '1-4', 'a': 4123, 'b': 12, c: 1 }, 89 | { '日期': '1-5', 'a': 3123, 'b': 15, c: 1 }, 90 | { '日期': '1-6', 'a': 7123, 'b': 20, c: 1 } 91 | ] 92 | }, 93 | settings: { 94 | axisSite: { 95 | top: ['a'], 96 | bottom: ['b'] 97 | } 98 | } 99 | }, 100 | { 101 | name: '指标维度配置', 102 | data: { 103 | columns: ['日期', '余额', '年龄'], 104 | rows: [ 105 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 106 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 107 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 108 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 109 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 110 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 111 | ] 112 | }, 113 | settings: { 114 | dimension: ['余额'], 115 | metrics: ['年龄'] 116 | } 117 | }, 118 | { 119 | name: '堆叠条形图', 120 | data: { 121 | columns: ['日期', '余额', '年龄'], 122 | rows: [ 123 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 124 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 125 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 126 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 127 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 128 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 129 | ] 130 | }, 131 | settings: { 132 | stack: { 133 | 'xxx': ['余额', '年龄'] 134 | } 135 | } 136 | } 137 | ] 138 | } 139 | -------------------------------------------------------------------------------- /examples/data/chart.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '图', 3 | type: 'chart', 4 | data: [ 5 | { 6 | name: '折线图', 7 | data: { 8 | columns: ['日期', '余额', '年龄'], 9 | rows: [ 10 | { '日期': 1, '余额': 123, '年龄': 3 }, 11 | { '日期': 2, '余额': 1223, '年龄': 6 }, 12 | { '日期': 3, '余额': 2123, '年龄': 9 }, 13 | { '日期': 4, '余额': 4123, '年龄': 12 }, 14 | { '日期': 5, '余额': 3123, '年龄': 15 }, 15 | { '日期': 6, '余额': 7123, '年龄': 20 } 16 | ] 17 | }, 18 | settings: { 19 | type: 'line' 20 | } 21 | }, 22 | { 23 | name: '柱状图', 24 | data: { 25 | columns: ['日期', '余额', '年龄'], 26 | rows: [ 27 | { '日期': 1, '余额': 123, '年龄': 3 }, 28 | { '日期': 2, '余额': 1223, '年龄': 6 }, 29 | { '日期': 3, '余额': 2123, '年龄': 9 }, 30 | { '日期': 4, '余额': 4123, '年龄': 12 }, 31 | { '日期': 5, '余额': 3123, '年龄': 15 }, 32 | { '日期': 6, '余额': 7123, '年龄': 20 } 33 | ] 34 | }, 35 | settings: { 36 | type: 'histogram' 37 | } 38 | }, 39 | { 40 | name: '饼图', 41 | data: { 42 | columns: ['日期', '余额', '年龄'], 43 | rows: [ 44 | { '日期': 1, '余额': 123, '年龄': 3 }, 45 | { '日期': 2, '余额': 1223, '年龄': 6 }, 46 | { '日期': 3, '余额': 2123, '年龄': 9 }, 47 | { '日期': 4, '余额': 4123, '年龄': 12 }, 48 | { '日期': 5, '余额': 3123, '年龄': 15 }, 49 | { '日期': 6, '余额': 7123, '年龄': 20 } 50 | ] 51 | }, 52 | settings: { 53 | type: 'pie' 54 | } 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /examples/data/funnel.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '漏斗图', 3 | type: 'funnel', 4 | data: [ 5 | { 6 | name: '简单漏斗图', 7 | data: { 8 | columns: ['状态', '数值'], 9 | rows: [ 10 | { '状态': '展示', '数值': 900 }, 11 | { '状态': '访问', '数值': 600 }, 12 | { '状态': '点击', '数值': 300 }, 13 | { '状态': '订单', '数值': 100 } 14 | ] 15 | }, 16 | settings: {} 17 | }, 18 | { 19 | name: '定制维度顺序', 20 | data: { 21 | columns: ['状态', '数值'], 22 | rows: [ 23 | { '状态': '展示', '数值': 900 }, 24 | { '状态': '访问', '数值': 600 }, 25 | { '状态': '点击', '数值': 300 }, 26 | { '状态': '订单', '数值': 100 } 27 | ] 28 | }, 29 | settings: { 30 | sequence: ['订单', '点击', '访问', '展示'] 31 | } 32 | }, 33 | { 34 | name: '数据类型配置', 35 | data: { 36 | columns: ['状态', '数值'], 37 | rows: [ 38 | { '状态': '展示', '数值': 0.9 }, 39 | { '状态': '访问', '数值': 0.6 }, 40 | { '状态': '点击', '数值': 0.3 }, 41 | { '状态': '订单', '数值': 0.00001 } 42 | ] 43 | }, 44 | settings: { 45 | dataType: 'percent', 46 | digit: 4 47 | } 48 | }, 49 | { 50 | name: '金字塔', 51 | data: { 52 | columns: ['状态', '数值'], 53 | rows: [ 54 | { '状态': '展示', '数值': 900 }, 55 | { '状态': '访问', '数值': 600 }, 56 | { '状态': '点击', '数值': 300 }, 57 | { '状态': '订单', '数值': 100 } 58 | ] 59 | }, 60 | settings: { 61 | ascending: true 62 | } 63 | }, 64 | { 65 | name: '指标维度配置', 66 | data: { 67 | columns: ['状态', '状态1', '数值'], 68 | rows: [ 69 | { '状态': '展示', '状态1': '展示1', '数值': 900 }, 70 | { '状态': '访问', '状态1': '访问1', '数值': 600 }, 71 | { '状态': '点击', '状态1': '点击1', '数值': 300 }, 72 | { '状态': '订单', '状态1': '订单1', '数值': 100 } 73 | ] 74 | }, 75 | settings: { 76 | dimension: '状态1', 77 | metrics: '数值' 78 | } 79 | }, 80 | { 81 | name: '样式配置', 82 | data: { 83 | columns: ['状态', '状态1', '数值'], 84 | rows: [ 85 | { '状态': '展示', '状态1': '展示1', '数值': 900 }, 86 | { '状态': '访问', '状态1': '访问1', '数值': 600 }, 87 | { '状态': '点击', '状态1': '点击1', '数值': 300 }, 88 | { '状态': '订单', '状态1': '订单1', '数值': 100 } 89 | ] 90 | }, 91 | settings: { 92 | dimension: '状态1', 93 | metrics: '数值', 94 | label: { 95 | normal: { 96 | show: true, 97 | color: '#00f' 98 | } 99 | } 100 | } 101 | }, 102 | { 103 | name: '设置legend别名漏斗图', 104 | data: { 105 | columns: ['状态', '数值'], 106 | rows: [ 107 | { '状态': '展示', '数值': 0.9 }, 108 | { '状态': '访问', '数值': 0.6 }, 109 | { '状态': '点击', '数值': 0.3 }, 110 | { '状态': '订单', '数值': 0.00001 } 111 | ] 112 | }, 113 | settings: { 114 | legendName: { 115 | '订单': '订单biubiu~' 116 | } 117 | } 118 | } 119 | ] 120 | } 121 | -------------------------------------------------------------------------------- /examples/data/global.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: { 3 | columns: ['日期', '余额', '年龄'], 4 | rows: [ 5 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 6 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 7 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 8 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 9 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 10 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 11 | ] 12 | }, 13 | grid: { left: 20, right: 20, top: 20, bottom: 20 }, 14 | colors: ['#eee', '#222', '#333', '#444'], 15 | scale: { x: true, y: true } 16 | } 17 | -------------------------------------------------------------------------------- /examples/data/heatmap.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '热力图', 3 | type: 'heatmap', 4 | data: [ 5 | { 6 | name: '简单热力图', 7 | data: { 8 | columns: ['时间', '地点', '人数'], 9 | rows: [ 10 | { '时间': '星期一', '地点': '北京', '人数': 1000 }, 11 | { '时间': '星期二', '地点': '上海', '人数': 400 }, 12 | { '时间': '星期三', '地点': '杭州', '人数': 800 }, 13 | { '时间': '星期二', '地点': '深圳', '人数': 200 }, 14 | { '时间': '星期三', '地点': '长春', '人数': 100 }, 15 | { '时间': '星期五', '地点': '南京', '人数': 300 }, 16 | { '时间': '星期四', '地点': '江苏', '人数': 800 }, 17 | { '时间': '星期一', '地点': '北京', '人数': 700 }, 18 | { '时间': '星期三', '地点': '上海', '人数': 300 }, 19 | { '时间': '星期二', '地点': '杭州', '人数': 500 } 20 | ] 21 | } 22 | }, 23 | { 24 | name: '配置坐标轴显示内容', 25 | data: { 26 | columns: ['时间', '地点', '人数'], 27 | rows: [ 28 | { '时间': '星期一', '地点': '北京', '人数': 1000 }, 29 | { '时间': '星期二', '地点': '上海', '人数': 400 }, 30 | { '时间': '星期三', '地点': '杭州', '人数': 800 }, 31 | { '时间': '星期二', '地点': '深圳', '人数': 200 }, 32 | { '时间': '星期三', '地点': '长春', '人数': 100 }, 33 | { '时间': '星期五', '地点': '南京', '人数': 300 }, 34 | { '时间': '星期四', '地点': '江苏', '人数': 800 }, 35 | { '时间': '星期三', '地点': '北京', '人数': 700 }, 36 | { '时间': '星期三', '地点': '上海', '人数': 300 }, 37 | { '时间': '星期二', '地点': '杭州', '人数': 500 } 38 | ] 39 | }, 40 | settings: { 41 | xAxisList: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'], 42 | yAxisList: ['北京', '上海', '杭州', '深圳', '长春', '南京', '江苏'] 43 | } 44 | }, 45 | { 46 | name: '地图+热力图', 47 | data: { 48 | columns: ['lat', 'lng', '人数'], 49 | rows: [ 50 | { 'lat': 115.892151, 'lng': 28.676493, '人数': 1000 }, 51 | { 'lat': 117.000923, 'lng': 36.675807, '人数': 400 }, 52 | { 'lat': 113.665412, 'lng': 34.757975, '人数': 800 }, 53 | { 'lat': 114.298572, 'lng': 30.584355, '人数': 200 }, 54 | { 'lat': 112.982279, 'lng': 28.19409, '人数': 100 }, 55 | { 'lat': 113.280637, 'lng': 23.125178, '人数': 300 }, 56 | { 'lat': 110.33119, 'lng': 20.031971, '人数': 800 }, 57 | { 'lat': 104.065735, 'lng': 30.659462, '人数': 700 }, 58 | { 'lat': 108.948024, 'lng': 34.263161, '人数': 300 }, 59 | { 'lat': 103.823557, 'lng': 36.058039, '人数': 500 } 60 | ] 61 | }, 62 | settings: { 63 | position: 'china', 64 | type: 'map', 65 | geo: { 66 | label: { 67 | emphasis: { 68 | show: false 69 | } 70 | }, 71 | itemStyle: { 72 | normal: { 73 | areaColor: '#323c48', 74 | borderColor: '#111' 75 | }, 76 | emphasis: { 77 | areaColor: '#2a333d' 78 | } 79 | } 80 | } 81 | } 82 | }, 83 | { 84 | name: '百度地图+热力图', 85 | data: { 86 | columns: ['lat', 'lng'], 87 | rows: [ 88 | { 'lat': 120.14322240845, 'lng': 30.236064370321 }, 89 | { 'lat': 120.14301682797, 'lng': 30.236035316745 }, 90 | { 'lat': 120.14138577045, 'lng': 30.236113748704 }, 91 | { 'lat': 120.1400398833, 'lng': 30.235973050702 }, 92 | { 'lat': 120.13893453465, 'lng': 30.23517220446 }, 93 | { 'lat': 120.1382899739, 'lng': 30.234062922977 }, 94 | { 'lat': 120.13265960629, 'lng': 30.231641351722 }, 95 | { 'lat': 120.13170681763, 'lng': 30.229925745619 }, 96 | { 'lat': 120.13119614803, 'lng': 30.228996846637 }, 97 | { 'lat': 120.13023980134, 'lng': 30.228226570416 } 98 | ] 99 | }, 100 | settings: { 101 | key: 'oBvDtR6nzWtVchkY4cLHtnah1VVZQKRK', 102 | bmap: { 103 | center: [120.14322240845, 30.236064370321], 104 | zoom: 14, 105 | roam: true 106 | }, 107 | type: 'bmap' 108 | } 109 | } 110 | ] 111 | } 112 | -------------------------------------------------------------------------------- /examples/data/histogram.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '柱状图', 3 | type: 'histogram', 4 | data: [ 5 | { 6 | name: '简单柱状图', 7 | data: { 8 | columns: ['日期', '余额', '年龄'], 9 | rows: [ 10 | { '日期': '1-1', '余额': 12, '年龄': 3 }, 11 | { '日期': '1-2', '余额': 12, '年龄': 6 }, 12 | { '日期': '1-3', '余额': 21, '年龄': 9 }, 13 | { '日期': '1-4', '余额': 41, '年龄': 12 }, 14 | { '日期': '1-5', '余额': 31, '年龄': 15 }, 15 | { '日期': '1-6', '余额': 71, '年龄': 20 } 16 | ] 17 | }, 18 | settings: { 19 | stack: { '对比': ['余额', '年龄'] } 20 | } 21 | }, 22 | { 23 | name: '数值轴柱状图', 24 | data: { 25 | columns: ['日期', '余额', '年龄', '成绩'], 26 | rows: [ 27 | { '日期': 10, '余额': 12, '年龄': 3, '成绩': 32 }, 28 | { '日期': 20, '余额': 12, '年龄': 6, '成绩': 53 }, 29 | { '日期': 30, '余额': 21, '年龄': 9, '成绩': 33 }, 30 | { '日期': 40, '余额': 41, '年龄': 12, '成绩': 36 }, 31 | { '日期': 50, '余额': 34, '年龄': 15, '成绩': 23 }, 32 | { '日期': 60, '余额': 71, '年龄': 20, '成绩': 13 }, 33 | { '日期': 70, '余额': 71, '年龄': 20, '成绩': 13 }, 34 | { '日期': 80, '余额': 71, '年龄': 20, '成绩': 13 } 35 | ] 36 | }, 37 | settings: { 38 | // xAxisType: 'value' 39 | } 40 | }, 41 | { 42 | name: '柱状图+折线图', 43 | data: { 44 | columns: ['日期', '余额', '年龄'], 45 | rows: [ 46 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 47 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 48 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 49 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 50 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 51 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 52 | ] 53 | }, 54 | settings: { 55 | axisSite: { 56 | right: ['年龄'] 57 | }, 58 | showLine: ['年龄'] 59 | } 60 | }, 61 | { 62 | name: '默认在柱子上显示数据', 63 | data: { 64 | columns: ['日期', '余额', '年龄'], 65 | rows: [ 66 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 67 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 68 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 69 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 70 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 71 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 72 | ] 73 | }, 74 | settings: { 75 | label: { 76 | normal: { 77 | show: true, 78 | position: 'top' 79 | } 80 | } 81 | } 82 | }, 83 | { 84 | name: '设置指标维度名称', 85 | data: { 86 | columns: ['date', 'resume', 'uplevel'], 87 | rows: [ 88 | { 'date': '1-1', 'resume': 123, 'uplevel': 0.3 }, 89 | { 'date': '1-2', 'resume': 1223, 'uplevel': 0.6 }, 90 | { 'date': '1-3', 'resume': 2123, 'uplevel': 0.9 }, 91 | { 'date': '1-4', 'resume': 4123, 'uplevel': 0.12 }, 92 | { 'date': '1-5', 'resume': 3123, 'uplevel': 0.15 }, 93 | { 'date': '1-6', 'resume': 7123, 'uplevel': 0.2 } 94 | ] 95 | }, 96 | settings: { 97 | labelMap: { 98 | date: '日期', 99 | resume: '余额', 100 | uplevel: '增长率' 101 | }, 102 | yAxisType: ['KMB', 'percent'], 103 | axisSite: { 104 | right: ['uplevel'] 105 | } 106 | } 107 | }, 108 | { 109 | name: '坐标轴值域配置', 110 | data: { 111 | columns: ['日期', '余额', '年龄'], 112 | rows: [ 113 | { '日期': '1-1', '余额': 1232, '年龄': 3 }, 114 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 115 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 116 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 117 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 118 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 119 | ] 120 | }, 121 | settings: { 122 | min: [1000] 123 | } 124 | }, 125 | { 126 | name: '带有较小百分比数值', 127 | data: { 128 | columns: ['日期', '比率'], 129 | rows: [ 130 | { '日期': '1-1', '余额': 123, '比率': 0.00001 }, 131 | { '日期': '1-2', '余额': 1223, '比率': 0.00002 }, 132 | { '日期': '1-3', '余额': 2123, '比率': 0.00003 }, 133 | { '日期': '1-4', '余额': 4123, '比率': 0.00007 }, 134 | { '日期': '1-5', '余额': 3123, '比率': 0.00001 }, 135 | { '日期': '1-6', '余额': 7123, '比率': 0.00003 } 136 | ] 137 | }, 138 | settings: { 139 | yAxisType: ['percent'], 140 | digit: 4 141 | } 142 | }, 143 | { 144 | name: '坐标轴配置', 145 | data: { 146 | columns: ['日期', '余额', '年龄'], 147 | rows: [ 148 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 149 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 150 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 151 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 152 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 153 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 154 | ] 155 | }, 156 | settings: { 157 | yAxisType: ['KMB', 'percent'], 158 | yAxisName: ['余额', '年龄'], 159 | axisSite: { 160 | right: ['年龄'] 161 | } 162 | } 163 | }, 164 | { 165 | name: '复杂坐标轴配置', 166 | data: { 167 | columns: ['日期', 'a', 'b', 'c'], 168 | rows: [ 169 | { '日期': '1-1', 'a': 123, 'b': 3, c: 1 }, 170 | { '日期': '1-2', 'a': 1223, 'b': 6, c: 1 }, 171 | { '日期': '1-3', 'a': 2123, 'b': 9, c: 1 }, 172 | { '日期': '1-4', 'a': 4123, 'b': 12, c: 1 }, 173 | { '日期': '1-5', 'a': 3123, 'b': 15, c: 1 }, 174 | { '日期': '1-6', 'a': 7123, 'b': 20, c: 1 } 175 | ] 176 | }, 177 | settings: { 178 | axisSite: { 179 | left: ['a'], 180 | right: ['b'] 181 | } 182 | } 183 | }, 184 | { 185 | name: '指标维度配置', 186 | data: { 187 | columns: ['日期', '余额', '年龄'], 188 | rows: [ 189 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 190 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 191 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 192 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 193 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 194 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 195 | ] 196 | }, 197 | settings: { 198 | dimension: ['余额'], 199 | metrics: ['年龄'] 200 | } 201 | }, 202 | { 203 | name: '堆叠柱状图', 204 | data: { 205 | columns: ['日期', '余额', '年龄'], 206 | rows: [ 207 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 208 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 209 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 210 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 211 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 212 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 213 | ] 214 | }, 215 | settings: { 216 | stack: { 217 | 'xxx': ['余额', '年龄'] 218 | } 219 | } 220 | } 221 | ] 222 | } 223 | -------------------------------------------------------------------------------- /examples/data/index.js: -------------------------------------------------------------------------------- 1 | import bar from './bar' 2 | import histogram from './histogram' 3 | import line from './line' 4 | import pie from './pie' 5 | import ring from './ring' 6 | import waterfall from './waterfall' 7 | import funnel from './funnel' 8 | import radar from './radar' 9 | import chart from './chart' 10 | import map from './map' 11 | import sankey from './sankey' 12 | import heatmap from './heatmap' 13 | 14 | export default { 15 | bar, 16 | histogram, 17 | line, 18 | pie, 19 | ring, 20 | waterfall, 21 | funnel, 22 | radar, 23 | chart, 24 | map, 25 | sankey, 26 | heatmap 27 | } 28 | -------------------------------------------------------------------------------- /examples/data/line.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '折线图', 3 | type: 'line', 4 | data: [ 5 | { 6 | name: '简单折线图', 7 | data: { 8 | columns: ['日期', '余额', '年龄'], 9 | rows: [ 10 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 11 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 12 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 13 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 14 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 15 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 16 | ] 17 | }, 18 | settings: {} 19 | }, 20 | { 21 | name: 'label 属性配置', 22 | data: { 23 | columns: ['日期', '余额', '年龄'], 24 | rows: [ 25 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 26 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 27 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 28 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 29 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 30 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 31 | ] 32 | }, 33 | settings: { 34 | label: { 35 | normal: { 36 | show: true 37 | } 38 | } 39 | } 40 | }, 41 | { 42 | name: '设置指标名称', 43 | data: { 44 | columns: ['date', 'balance', 'age'], 45 | rows: [ 46 | { 'date': '1-1', 'balance': 123, 'age': 3 }, 47 | { 'date': '1-2', 'balance': 1223, 'age': 6 }, 48 | { 'date': '1-3', 'balance': 2123, 'age': 9 }, 49 | { 'date': '1-4', 'balance': 4123, 'age': 12 }, 50 | { 'date': '1-5', 'balance': 3123, 'age': 15 }, 51 | { 'date': '1-6', 'balance': 7123, 'age': 20 } 52 | ] 53 | }, 54 | settings: { 55 | labelMap: { 56 | date: '日期', 57 | balance: '余额' 58 | } 59 | } 60 | }, 61 | { 62 | name: '设置legend名称', 63 | data: { 64 | columns: ['日期', '余额', '年龄'], 65 | rows: [ 66 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 67 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 68 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 69 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 70 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 71 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 72 | ] 73 | }, 74 | settings: { 75 | legendName: { 76 | '余额': 'remain' 77 | } 78 | } 79 | }, 80 | { 81 | name: '带有较小百分比数值', 82 | data: { 83 | columns: ['日期', '比率'], 84 | rows: [ 85 | { '日期': '1-1', '余额': 123, '比率': 0.00001 }, 86 | { '日期': '1-2', '余额': 1223, '比率': 0.00002 }, 87 | { '日期': '1-3', '余额': 2123, '比率': 0.00003 }, 88 | { '日期': '1-4', '余额': 4123, '比率': 0.00007 }, 89 | { '日期': '1-5', '余额': 3123, '比率': 0.00001 }, 90 | { '日期': '1-6', '余额': 7123, '比率': 0.00003 } 91 | ] 92 | }, 93 | settings: { 94 | yAxisType: ['percent'], 95 | digit: 4 96 | } 97 | }, 98 | { 99 | name: '坐标轴配置', 100 | data: { 101 | columns: ['日期', '余额', '比率'], 102 | rows: [ 103 | { '日期': '1-1', '余额': 123, '比率': 0.3 }, 104 | { '日期': '1-2', '余额': 1223, '比率': 0.6 }, 105 | { '日期': '1-3', '余额': 2123, '比率': 0.9 }, 106 | { '日期': '1-4', '余额': 4123, '比率': 0.12 }, 107 | { '日期': '1-5', '余额': 3123, '比率': 0.15 }, 108 | { '日期': '1-6', '余额': 7123, '比率': 0.20 } 109 | ] 110 | }, 111 | settings: { 112 | axisSite: { 113 | right: ['比率'] 114 | }, 115 | yAxisType: ['KMB', 'percent'] 116 | } 117 | }, 118 | { 119 | name: '指标维度配置', 120 | data: { 121 | columns: ['日期', '余额', '比率'], 122 | rows: [ 123 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 124 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 125 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 126 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 127 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 128 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 129 | ] 130 | }, 131 | settings: { 132 | dimension: ['比率'], 133 | metrics: ['余额'] 134 | } 135 | }, 136 | { 137 | name: '坐标轴缩放配置', 138 | data: { 139 | columns: ['日期', '余额', '比率'], 140 | rows: [ 141 | { '日期': '1-1', '余额': 1232, '比率': 0.1 }, 142 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 143 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 144 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 145 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 146 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 147 | ] 148 | }, 149 | settings: { 150 | dimension: ['比率'], 151 | metrics: ['余额'], 152 | scale: [true, true] 153 | } 154 | }, 155 | { 156 | name: '坐标轴值域配置', 157 | data: { 158 | columns: ['日期', '余额', '比率'], 159 | rows: [ 160 | { '日期': '1-1', '余额': 1232, '比率': 0.1 }, 161 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 162 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 163 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 164 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 165 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 166 | ] 167 | }, 168 | settings: { 169 | dimension: ['比率'], 170 | metrics: ['余额'], 171 | min: [1000], 172 | max: [5000] 173 | } 174 | }, 175 | { 176 | name: '面积图', 177 | data: { 178 | columns: ['日期', '余额', '比率'], 179 | rows: [ 180 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 181 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 182 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 183 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 184 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 185 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 186 | ] 187 | }, 188 | settings: { 189 | area: true 190 | } 191 | }, 192 | { 193 | name: '堆叠折线图', 194 | data: { 195 | columns: ['日期', '2015', '2016', '2017'], 196 | rows: [ 197 | { '日期': '1-1', '2015': 100, '2016': 40, '2017': 22 }, 198 | { '日期': '1-2', '2015': 110, '2016': 60, '2017': 25 }, 199 | { '日期': '1-3', '2015': 140, '2016': 10, '2017': 14 }, 200 | { '日期': '1-4', '2015': 260, '2016': 30, '2017': 75 }, 201 | { '日期': '1-5', '2015': 300, '2016': 20, '2017': 45 }, 202 | { '日期': '1-6', '2015': 380, '2016': 70, '2017': 310 } 203 | ] 204 | }, 205 | settings: { 206 | area: true, 207 | stack: { 208 | '年份': ['2015', '2016', '2017'] 209 | } 210 | } 211 | } 212 | ] 213 | } 214 | -------------------------------------------------------------------------------- /examples/data/map.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '地图', 3 | type: 'map', 4 | data: [ 5 | { 6 | name: '地图', 7 | data: { 8 | columns: ['位置', 'GDP'], 9 | rows: [ 10 | { '位置': '吉林', 'GDP': 123 }, 11 | { '位置': '北京', 'GDP': 1223 }, 12 | { '位置': '上海', 'GDP': 2123 }, 13 | { '位置': '浙江', 'GDP': 4123 } 14 | ] 15 | }, 16 | settings: { 17 | position: 'china', 18 | dataType: { 19 | 'GDP': 'KMB' 20 | } 21 | } 22 | }, 23 | { 24 | name: '自定义 JSON 地图', 25 | data: { 26 | columns: ['位置', ' 人口'], 27 | rows: [ 28 | { '位置': 'North', ' 人口': 123 } 29 | ] 30 | }, 31 | settings: { 32 | positionJsonLink: 'https://dn-quietcoder.qbox.me/HK_geo.json', 33 | position: 'HK', 34 | beforeRegisterMap (json) { 35 | // edit data here such as: 36 | // json.features[0].properties.cp = [121.509062, 26.044332] 37 | return json 38 | } 39 | } 40 | }, 41 | { 42 | name: '设置数据标示', 43 | data: { 44 | columns: ['位置', 'GDP', '人口'], 45 | rows: [ 46 | { '位置': '吉林', 'GDP': 123, '人口': 234 }, 47 | { '位置': '北京', 'GDP': 1223, '人口': 1234 }, 48 | { '位置': '上海', 'GDP': 2123, '人口': 3234 }, 49 | { '位置': '浙江', 'GDP': 4123, '人口': 4234 } 50 | ] 51 | }, 52 | settings: { 53 | position: 'china', 54 | selectData: true, 55 | label: false 56 | } 57 | }, 58 | { 59 | name: '设置位置选择模式', 60 | data: { 61 | columns: ['位置', 'GDP'], 62 | rows: [ 63 | { '位置': '吉林', 'GDP': 123 }, 64 | { '位置': '北京', 'GDP': 1223 }, 65 | { '位置': '上海', 'GDP': 2123 }, 66 | { '位置': '浙江', 'GDP': 4123 } 67 | ] 68 | }, 69 | settings: { 70 | position: 'china', 71 | selectedMode: 'multiple' 72 | } 73 | }, 74 | { 75 | name: '设置省份显示', 76 | data: { 77 | columns: ['位置', 'GDP'], 78 | rows: [ 79 | { '位置': '长春市', 'GDP': 123 }, 80 | { '位置': '松原市', 'GDP': 1223 }, 81 | { '位置': '辽源市', 'GDP': 2123 }, 82 | { '位置': '白山市', 'GDP': 4123 } 83 | ] 84 | }, 85 | settings: { 86 | position: 'province/jilin', 87 | selectData: true 88 | } 89 | }, 90 | { 91 | name: '设置数据别名', 92 | data: { 93 | columns: ['位置', 'GDP', '人口'], 94 | rows: [ 95 | { '位置': '吉林', 'GDP': 123, '人口': 234 }, 96 | { '位置': '北京', 'GDP': 1223, '人口': 1234 }, 97 | { '位置': '上海', 'GDP': 2123, '人口': 3234 }, 98 | { '位置': '浙江', 'GDP': 4123, '人口': 4234 } 99 | ] 100 | }, 101 | settings: { 102 | labelMap: { 103 | '人口': '人口密度' 104 | } 105 | } 106 | }, 107 | { 108 | name: '设置legendName别名地图', 109 | data: { 110 | columns: ['位置', 'GDP', '人口'], 111 | rows: [ 112 | { '位置': '吉林', 'GDP': 123, '人口': 234 }, 113 | { '位置': '北京', 'GDP': 1223, '人口': 1234 }, 114 | { '位置': '上海', 'GDP': 2123, '人口': 3234 }, 115 | { '位置': '浙江', 'GDP': 4123, '人口': 4234 } 116 | ] 117 | }, 118 | settings: { 119 | legendName: { 120 | '人口': '人口密度' 121 | } 122 | } 123 | } 124 | ] 125 | } 126 | -------------------------------------------------------------------------------- /examples/data/pie.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '饼图', 3 | type: 'pie', 4 | data: [ 5 | { 6 | name: '简单饼图', 7 | data: { 8 | columns: ['日期', '余额', '年龄'], 9 | rows: [ 10 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 11 | { '日期': '1-2', '余额': 123, '年龄': 6 }, 12 | { '日期': '1-3', '余额': 123, '年龄': 9 }, 13 | { '日期': '1-4', '余额': 123, '年龄': 12 }, 14 | { '日期': '1-5', '余额': 123, '年龄': 15 }, 15 | { '日期': '1-6', '余额': 123, '年龄': 20 } 16 | ] 17 | }, 18 | settings: {} 19 | }, 20 | { 21 | name: '玫瑰图', 22 | data: { 23 | columns: ['日期', '余额', '年龄'], 24 | rows: [ 25 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 26 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 27 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 28 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 29 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 30 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 31 | ] 32 | }, 33 | settings: { 34 | roseType: 'radius' 35 | } 36 | }, 37 | { 38 | name: '限制显示条数', 39 | data: { 40 | columns: ['日期', '余额', '年龄'], 41 | rows: [ 42 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 43 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 44 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 45 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 46 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 47 | { '日期': '1-6', '余额': 7123, '年龄': 20 }, 48 | { '日期': '1-7', '余额': 4123, '年龄': 20 }, 49 | { '日期': '1-8', '余额': 1123, '年龄': 20 }, 50 | { '日期': '1-9', '余额': 5223, '年龄': 20 }, 51 | { '日期': '1-10', '余额': 9123, '年龄': 20 }, 52 | { '日期': '1-11', '余额': 4123, '年龄': 20 } 53 | ] 54 | }, 55 | settings: { 56 | limitShowNum: 5 57 | } 58 | }, 59 | { 60 | name: '多圆饼图', 61 | data: { 62 | columns: ['日期', '余额', '年龄'], 63 | rows: [ 64 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 65 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 66 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 67 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 68 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 69 | { '日期': '1-6', '余额': 7123, '年龄': 20 }, 70 | { '日期': '1-7', '余额': 4123, '年龄': 20 }, 71 | { '日期': '1-8', '余额': 1123, '年龄': 20 }, 72 | { '日期': '1-9', '余额': 5223, '年龄': 20 }, 73 | { '日期': '1-10', '余额': 9123, '年龄': 20 }, 74 | { '日期': '1-11', '余额': 4123, '年龄': 20 } 75 | ] 76 | }, 77 | settings: { 78 | level: [ 79 | ['1-1', '1-2', '1-3'], 80 | ['1-4', '1-5'] 81 | ] 82 | } 83 | }, 84 | { 85 | name: '设置数据类型', 86 | data: { 87 | columns: ['日期', '比率'], 88 | rows: [ 89 | { '日期': '1-1', '余额': 123, '比率': 0.00001 }, 90 | { '日期': '1-2', '余额': 1223, '比率': 0.0002 }, 91 | { '日期': '1-3', '余额': 2123, '比率': 0.003 }, 92 | { '日期': '1-4', '余额': 4123, '比率': 0.0004 }, 93 | { '日期': '1-5', '余额': 3123, '比率': 0.005 }, 94 | { '日期': '1-6', '余额': 7123, '比率': 0.06 } 95 | ] 96 | }, 97 | settings: { 98 | dataType: 'percent', 99 | digit: 4 100 | } 101 | }, 102 | { 103 | name: '指标维度配置', 104 | data: { 105 | columns: ['日期', '余额', '年龄'], 106 | rows: [ 107 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 108 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 109 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 110 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 111 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 112 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 113 | ] 114 | }, 115 | settings: { 116 | dimension: '余额', 117 | metrics: '年龄' 118 | } 119 | }, 120 | { 121 | name: '限制legend显示长度', 122 | data: { 123 | columns: ['日期', '余额', '比率'], 124 | rows: [ 125 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 126 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 127 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 128 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 129 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 130 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 131 | ] 132 | }, 133 | settings: { 134 | legendLimit: 2 135 | } 136 | }, 137 | { 138 | name: '设置饼图样式1', 139 | data: { 140 | columns: ['日期', '余额', '比率'], 141 | rows: [ 142 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 143 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 144 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 145 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 146 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 147 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 148 | ] 149 | }, 150 | settings: { 151 | radius: 10, 152 | offsetY: 300 153 | } 154 | }, 155 | { 156 | name: '设置饼图样式2', 157 | data: { 158 | columns: ['日期', '余额', '比率'], 159 | rows: [ 160 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 161 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 162 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 163 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 164 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 165 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 166 | ] 167 | }, 168 | settings: { 169 | itemStyle: { 170 | normal: { 171 | borderWidth: 4, 172 | borderColor: '#58b4ff' 173 | } 174 | } 175 | } 176 | }, 177 | { 178 | name: '设置legend别名饼图', 179 | data: { 180 | columns: ['日期', '余额', '比率'], 181 | rows: [ 182 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 183 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 184 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 185 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 186 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 187 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 188 | ] 189 | }, 190 | settings: { 191 | limitShowNum: 5, 192 | legendName: { 193 | '其他': '别的时间的时候biu~' 194 | } 195 | } 196 | } 197 | ] 198 | } 199 | -------------------------------------------------------------------------------- /examples/data/radar.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '雷达图', 3 | type: 'radar', 4 | data: [ 5 | { 6 | name: '简单雷达图', 7 | data: { 8 | columns: ['城市', '房价', '收入', '人口比例'], 9 | rows: [ 10 | { '房价': 10000, '收入': 4000, '人口比例': 0.4, '城市': '北京' }, 11 | { '房价': 20000, '收入': 6000, '人口比例': 0.6, '城市': '上海' }, 12 | { '房价': 30000, '收入': 8000, '人口比例': 0.2, '城市': '广州' } 13 | ] 14 | }, 15 | settings: { 16 | dataType: { 17 | '人口比例': 'percent' 18 | } 19 | } 20 | }, 21 | { 22 | name: '指标维度配置', 23 | data: { 24 | columns: ['城市', '房价', '收入', '人口比例'], 25 | rows: [ 26 | { '房价': 10000, '收入': 4000, '人口比例': 0.4, '城市': '北京' }, 27 | { '房价': 20000, '收入': 6000, '人口比例': 0.6, '城市': '上海' }, 28 | { '房价': 30000, '收入': 8000, '人口比例': 0.2, '城市': '广州' } 29 | ] 30 | }, 31 | settings: { 32 | dataType: { 33 | '人口比例': 'percent' 34 | }, 35 | dimension: '城市', 36 | metrics: ['收入', '人口比例', '房价'] 37 | } 38 | }, 39 | { 40 | name: '样式配置', 41 | data: { 42 | columns: ['城市', '房价', '收入', '人口比例'], 43 | rows: [ 44 | { '房价': 10000, '收入': 4000, '人口比例': 0.4, '城市': '北京' }, 45 | { '房价': 20000, '收入': 6000, '人口比例': 0.6, '城市': '上海' }, 46 | { '房价': 30000, '收入': 8000, '人口比例': 0.2, '城市': '广州' } 47 | ] 48 | }, 49 | settings: { 50 | label: { 51 | normal: { 52 | color: 'red', 53 | show: true 54 | } 55 | } 56 | } 57 | }, 58 | { 59 | name: '雷达图配置labelMap', 60 | data: { 61 | columns: ['city', 'housePrices', 'income', 'proportion'], 62 | rows: [ 63 | { 'housePrices': 10000, 'income': 4000, 'proportion': 0.4, 'city': '北京' }, 64 | { 'housePrices': 20000, 'income': 6000, 'proportion': 0.6, 'city': '上海' }, 65 | { 'housePrices': 30000, 'income': 8000, 'proportion': 0.2, 'city': '广州' } 66 | ] 67 | }, 68 | settings: { 69 | labelMap: { 70 | 'city': '城市', 71 | 'housePrices': '房价', 72 | 'income': '收入', 73 | 'proportion': '人口比例' 74 | } 75 | } 76 | }, 77 | { 78 | name: '雷达图配置legendName', 79 | data: { 80 | columns: ['城市', '房价', '收入', '人口比例'], 81 | rows: [ 82 | { '房价': 10000, '收入': 4000, '人口比例': 0.4, '城市': '北京' }, 83 | { '房价': 20000, '收入': 6000, '人口比例': 0.6, '城市': '上海' }, 84 | { '房价': 30000, '收入': 8000, '人口比例': 0.2, '城市': '广州' } 85 | ] 86 | }, 87 | settings: { 88 | legendName: { 89 | '北京': 'BeiJing' 90 | } 91 | } 92 | }, 93 | { 94 | name: '雷达图', 95 | data: { 96 | columns: ['投资人', '股票', '基金', '保险', '银行理财', '互联网金融', '期货'], 97 | rows: [ 98 | { '股票': 10000, '基金': 4000, '保险': 0.4, '银行理财': 1, '互联网金融': 1, '期货': 1, '投资人': 'A' }, 99 | { '股票': 20000, '基金': 6000, '保险': 0.6, '银行理财': 2, '互联网金融': 2, '期货': 2, '投资人': 'B' }, 100 | { '股票': 30000, '基金': 8000, '保险': 0.2, '银行理财': 3, '互联网金融': 3, '期货': 3, '投资人': 'C' } 101 | ] 102 | }, 103 | settings: { 104 | } 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /examples/data/ring.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '环图', 3 | type: 'ring', 4 | data: [ 5 | { 6 | name: '简单环图', 7 | data: { 8 | columns: ['日期', '余额', '年龄'], 9 | rows: [ 10 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 11 | { '日期': '1-2', '余额': 123, '年龄': 6 }, 12 | { '日期': '1-3', '余额': 123, '年龄': 9 } 13 | // { '日期': '1-4', '余额': 123, '年龄': 12 }, 14 | // { '日期': '1-5', '余额': 123, '年龄': 15 }, 15 | // { '日期': '1-6', '余额': 123, '年龄': 20 } 16 | ] 17 | }, 18 | settings: { 19 | label: { 20 | normal: { 21 | show: false, 22 | position: 'center' 23 | } 24 | }, 25 | radius: [75, 100] 26 | } 27 | }, 28 | { 29 | name: '简单环图2', 30 | data: { 31 | columns: ['日期', '余额', '年龄'], 32 | rows: [ 33 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 34 | { '日期': '1-2', '余额': 123, '年龄': 6 }, 35 | { '日期': '1-3', '余额': 123, '年龄': 9 }, 36 | { '日期': '1-4', '余额': 123, '年龄': 12 }, 37 | { '日期': '1-5', '余额': 123, '年龄': 15 }, 38 | { '日期': '1-6', '余额': 123, '年龄': 20 } 39 | ] 40 | }, 41 | settings: { 42 | label: { 43 | normal: { 44 | show: false, 45 | position: 'center' 46 | } 47 | }, 48 | radius: [40, 90] 49 | } 50 | }, 51 | { 52 | name: '玫瑰图', 53 | data: { 54 | columns: ['日期', '余额', '年龄'], 55 | rows: [ 56 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 57 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 58 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 59 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 60 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 61 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 62 | ] 63 | }, 64 | settings: { 65 | roseType: 'radius' 66 | } 67 | }, 68 | { 69 | name: '限制显示条数', 70 | data: { 71 | columns: ['日期', '余额', '年龄'], 72 | rows: [ 73 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 74 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 75 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 76 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 77 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 78 | { '日期': '1-6', '余额': 7123, '年龄': 20 }, 79 | { '日期': '1-7', '余额': 4123, '年龄': 20 }, 80 | { '日期': '1-8', '余额': 1123, '年龄': 20 }, 81 | { '日期': '1-9', '余额': 5223, '年龄': 20 }, 82 | { '日期': '1-10', '余额': 9123, '年龄': 20 }, 83 | { '日期': '1-11', '余额': 4123, '年龄': 20 } 84 | ] 85 | }, 86 | settings: { 87 | limitShowNum: 5 88 | } 89 | }, 90 | { 91 | name: '设置数据类型', 92 | data: { 93 | columns: ['日期', '余额', '年龄'], 94 | rows: [ 95 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 96 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 97 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 98 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 99 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 100 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 101 | ] 102 | }, 103 | settings: { 104 | dataType: 'KMB' 105 | } 106 | }, 107 | { 108 | name: '指标维度配置', 109 | data: { 110 | columns: ['日期', '余额', '年龄'], 111 | rows: [ 112 | { '日期': '1-1', '余额': 123, '年龄': 3 }, 113 | { '日期': '1-2', '余额': 1223, '年龄': 6 }, 114 | { '日期': '1-3', '余额': 2123, '年龄': 9 }, 115 | { '日期': '1-4', '余额': 4123, '年龄': 12 }, 116 | { '日期': '1-5', '余额': 3123, '年龄': 15 }, 117 | { '日期': '1-6', '余额': 7123, '年龄': 20 } 118 | ] 119 | }, 120 | settings: { 121 | dimension: '余额', 122 | metrics: '年龄' 123 | } 124 | }, 125 | { 126 | name: '限制legend显示长度', 127 | data: { 128 | columns: ['日期', '余额', '比率'], 129 | rows: [ 130 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 131 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 132 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 133 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 134 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 135 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 136 | ] 137 | }, 138 | settings: { 139 | legendLimit: 2 140 | } 141 | }, 142 | { 143 | name: '设置环图样式', 144 | data: { 145 | columns: ['日期', '余额', '比率'], 146 | rows: [ 147 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 148 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 149 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 150 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 151 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 152 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 153 | ] 154 | }, 155 | settings: { 156 | radius: [100, 10], 157 | offsetY: 300 158 | } 159 | }, 160 | { 161 | name: '设置legend别名环图', 162 | data: { 163 | columns: ['日期', '余额', '比率'], 164 | rows: [ 165 | { '日期': '1-1', '余额': 123, '比率': 0.1 }, 166 | { '日期': '1-2', '余额': 1223, '比率': 0.2 }, 167 | { '日期': '1-3', '余额': 2123, '比率': 0.3 }, 168 | { '日期': '1-4', '余额': 4123, '比率': 0.4 }, 169 | { '日期': '1-5', '余额': 3123, '比率': 0.5 }, 170 | { '日期': '1-6', '余额': 7123, '比率': 0.6 } 171 | ] 172 | }, 173 | settings: { 174 | limitShowNum: 5, 175 | legendName: { 176 | '其他': '别的时间的时候biu~' 177 | } 178 | } 179 | } 180 | ] 181 | } 182 | -------------------------------------------------------------------------------- /examples/data/sankey.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '桑基图', 3 | type: 'sankey', 4 | data: [ 5 | { 6 | name: '简单桑基图', 7 | data: { 8 | columns: ['页面', '访问量'], 9 | rows: [ 10 | { '页面': '首页', '访问量': 1000 }, 11 | { '页面': '列表页a', '访问量': 200 }, 12 | { '页面': '列表页b', '访问量': 800 }, 13 | { '页面': '内容页a-1', '访问量': 100 }, 14 | { '页面': '内容页a-2', '访问量': 100 }, 15 | { '页面': '内容页b-1', '访问量': 600 }, 16 | { '页面': '内容页b-2', '访问量': 200 } 17 | ] 18 | }, 19 | settings: { 20 | links: [ 21 | { source: '首页', target: '列表页a' }, 22 | { source: '首页', target: '列表页b' }, 23 | { source: '列表页a', target: '内容页a-1' }, 24 | { source: '列表页a', target: '内容页a-2' }, 25 | { source: '列表页b', target: '内容页b-1' }, 26 | { source: '列表页b', target: '内容页b-2' } 27 | ] 28 | } 29 | }, 30 | { 31 | name: '强制设置使用 rows 中的数据', 32 | data: { 33 | columns: ['页面', '访问量'], 34 | rows: [ 35 | { '页面': '首页', '访问量': 1000 }, 36 | { '页面': '列表页a', '访问量': 200 }, 37 | { '页面': '列表页b', '访问量': 800 }, 38 | { '页面': '内容页a-1', '访问量': 100 }, 39 | { '页面': '内容页a-2', '访问量': 100 }, 40 | { '页面': '内容页b-1', '访问量': 600 }, 41 | { '页面': '内容页b-2', '访问量': 200 } 42 | ] 43 | }, 44 | settings: { 45 | links: [ 46 | { source: '首页', target: '列表页a', value: '' }, 47 | { source: '首页', target: '列表页b', value: '' }, 48 | { source: '列表页a', target: '内容页a-1', value: '' }, 49 | { source: '列表页a', target: '内容页a-2', value: '' }, 50 | { source: '列表页b', target: '内容页b-1', value: '' }, 51 | { source: '列表页b', target: '内容页b-2', value: '' } 52 | ], 53 | useDataValue: true 54 | } 55 | }, 56 | { 57 | name: '设置数据类型', 58 | data: { 59 | columns: ['页面', '访问量'], 60 | rows: [ 61 | { '页面': '首页', '访问量': 100000 }, 62 | { '页面': '列表页a', '访问量': 20000 }, 63 | { '页面': '列表页b', '访问量': 80000 }, 64 | { '页面': '内容页a-1', '访问量': 10000 }, 65 | { '页面': '内容页a-2', '访问量': 10000 }, 66 | { '页面': '内容页b-1', '访问量': 60000 }, 67 | { '页面': '内容页b-2', '访问量': 20000 } 68 | ] 69 | }, 70 | settings: { 71 | links: [ 72 | { source: '首页', target: '列表页a', value: 0.1 }, 73 | { source: '首页', target: '列表页b', value: 0.1 }, 74 | { source: '列表页a', target: '内容页a-1', value: 0.1 }, 75 | { source: '列表页a', target: '内容页a-2', value: 0.1 }, 76 | { source: '列表页b', target: '内容页b-1', value: 0.1 }, 77 | { source: '列表页b', target: '内容页b-2', value: 0.1 } 78 | ], 79 | dataType: ['KMB', 'percent'] 80 | } 81 | }, 82 | { 83 | name: '样式设置', 84 | data: { 85 | columns: ['页面', '访问量'], 86 | rows: [ 87 | { '页面': '首页', '访问量': 100000 }, 88 | { '页面': '列表页a', '访问量': 20000 }, 89 | { '页面': '列表页b', '访问量': 80000 }, 90 | { '页面': '内容页a-1', '访问量': 10000 }, 91 | { '页面': '内容页a-2', '访问量': 10000 }, 92 | { '页面': '内容页b-1', '访问量': 60000 }, 93 | { '页面': '内容页b-2', '访问量': 20000 } 94 | ] 95 | }, 96 | settings: { 97 | links: [ 98 | { source: '首页', target: '列表页a', value: 0.1 }, 99 | { source: '首页', target: '列表页b', value: 0.1 }, 100 | { source: '列表页a', target: '内容页a-1', value: 0.1 }, 101 | { source: '列表页a', target: '内容页a-2', value: 0.1 }, 102 | { source: '列表页b', target: '内容页b-1', value: 0.1 }, 103 | { source: '列表页b', target: '内容页b-2', value: 0.1 } 104 | ], 105 | label: { 106 | normal: { 107 | show: true, 108 | color: '#00f' 109 | } 110 | } 111 | } 112 | } 113 | ] 114 | } 115 | -------------------------------------------------------------------------------- /examples/data/waterfall.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: '瀑布图', 3 | type: 'waterfall', 4 | data: [ 5 | { 6 | name: '简单瀑布图', 7 | data: { 8 | columns: ['活动', '时间'], 9 | rows: [ 10 | { '活动': '吃饭', '时间': 4 }, 11 | { '活动': '睡觉', '时间': 10 }, 12 | { '活动': '打豆豆', '时间': 5 } 13 | ] 14 | }, 15 | settings: {} 16 | }, 17 | { 18 | name: '设定总量', 19 | data: { 20 | columns: ['活动', '时间'], 21 | rows: [ 22 | { '活动': '吃饭', '时间': 4 }, 23 | { '活动': '睡觉', '时间': 10 }, 24 | { '活动': '打豆豆', '时间': 5 } 25 | ] 26 | }, 27 | settings: { 28 | totalNum: 24 29 | } 30 | }, 31 | { 32 | name: '设定总量并且子项超标', 33 | data: { 34 | columns: ['活动', '时间'], 35 | rows: [ 36 | { '活动': '吃饭', '时间': 4 }, 37 | { '活动': '睡觉', '时间': 20 }, 38 | { '活动': '打豆豆', '时间': 5 } 39 | ] 40 | }, 41 | settings: { 42 | totalNum: 24 43 | } 44 | }, 45 | { 46 | name: '设定数据类型', 47 | data: { 48 | columns: ['活动', '时间'], 49 | rows: [ 50 | { '活动': '吃饭', '时间': 0.1 }, 51 | { '活动': '睡觉', '时间': 0.2 }, 52 | { '活动': '打豆豆', '时间': 0.3 } 53 | ] 54 | }, 55 | settings: { 56 | totalNum: 1, 57 | dataType: 'percent' 58 | } 59 | }, 60 | { 61 | name: '设定总量及其他名称', 62 | data: { 63 | columns: ['活动', '时间'], 64 | rows: [ 65 | { '活动': '吃饭', '时间': 4 }, 66 | { '活动': '睡觉', '时间': 10 }, 67 | { '活动': '打豆豆', '时间': 5 } 68 | ] 69 | }, 70 | settings: { 71 | totalNum: 24, 72 | totalName: '总时间', 73 | remainName: '剩余时间' 74 | } 75 | }, 76 | { 77 | name: '设定数据别名瀑布图', 78 | data: { 79 | columns: ['活动', '时间'], 80 | rows: [ 81 | { '活动': '吃饭', '时间': 4 }, 82 | { '活动': '睡觉', '时间': 10 }, 83 | { '活动': '打豆豆', '时间': 5 } 84 | ] 85 | }, 86 | settings: { 87 | labelMap: { 88 | '时间': 'time' 89 | } 90 | } 91 | } 92 | ] 93 | } 94 | -------------------------------------------------------------------------------- /examples/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalkingData/t-charts/d553261687e19c92be2333421f74cb8e0fc86e4d/examples/favicon.ico -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | v-charts 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | import App from './App' 2 | import Vue from 'vue' 3 | import router from './router' 4 | import CodeSection from './components/code-section' 5 | import 'normalize.css' 6 | 7 | Vue.component(CodeSection.name, CodeSection) 8 | 9 | /* eslint-disable no-new */ 10 | new Vue({ 11 | el: '#app', 12 | template: '', 13 | router, 14 | components: { App } 15 | }) 16 | -------------------------------------------------------------------------------- /examples/pages/bmap.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 49 | -------------------------------------------------------------------------------- /examples/pages/chart.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 84 | 85 | 110 | -------------------------------------------------------------------------------- /examples/pages/eventer.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 49 | -------------------------------------------------------------------------------- /examples/pages/install.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /examples/pages/test.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 54 | 55 | 60 | -------------------------------------------------------------------------------- /examples/pages/toggle.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 145 | -------------------------------------------------------------------------------- /examples/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Install from './pages/install' 4 | import Chart from './pages/chart' 5 | import Eventer from './pages/eventer' 6 | import Toggle from './pages/toggle' 7 | import Test from './pages/test' 8 | import Bmap from './pages/bmap.vue' 9 | 10 | Vue.use(Router) 11 | 12 | export default new Router({ 13 | routes: [ 14 | { path: '/', name: '安装', component: Install }, 15 | { path: '/chart/:type', name: '测试图表', component: Chart }, 16 | { path: '/eventer', name: '事件监听', component: Eventer }, 17 | { path: '/toggle', name: '图表切换', component: Toggle }, 18 | { path: '/test', name: '测试', component: Test }, 19 | { path: '/bmap', name: '百度地图', component: Bmap } 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /examples/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TalkingData/t-charts/d553261687e19c92be2333421f74cb8e0fc86e4d/examples/static/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "t-charts", 3 | "version": "1.2.6", 4 | "description": "", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "dev": "webpack-dev-server --config ./build/webpack.config.js", 8 | "build": "rm -f -r lib && node build/rollup.config.js && cp -f lib/index.min.js lib/style.min.css docs/", 9 | "prepublish": "npm run build", 10 | "test": "karma start ./test/karma.conf.js", 11 | "docs": "docsify serve docs", 12 | "deploy": "gh-pages -d docs" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+git@github.com:TalkingData/t-charts.git" 17 | }, 18 | "keywords": [ 19 | "vue", 20 | "echarts" 21 | ], 22 | "author": "xiguaxigua|t-charts team", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/TalkingData/t-charts/issues" 26 | }, 27 | "homepage": "https://github.com/TalkingData/t-charts#readme", 28 | "dependencies": { 29 | "css-loader": "^0.27.3", 30 | "echarts": "^3.8.3", 31 | "file-loader": "^0.11.1", 32 | "iview": "^2.7.3", 33 | "url-loader": "^0.5.8" 34 | }, 35 | "files": [ 36 | "lib", 37 | "umd" 38 | ], 39 | "devDependencies": { 40 | "autoprefixer": "^7.1.5", 41 | "babel-core": "6.24.0", 42 | "babel-eslint": "7.1.1", 43 | "babel-loader": "6.4.1", 44 | "babel-plugin-external-helpers": "6.22.0", 45 | "babel-plugin-transform-object-assign": "6.22.0", 46 | "babel-polyfill": "6.23.0", 47 | "babel-preset-latest": "6.24.0", 48 | "babel-preset-stage-2": "6.22.0", 49 | "copy-webpack-plugin": "4.0.1", 50 | "css-loader": "0.27.3", 51 | "cssnano": "^3.10.0", 52 | "docsify": "^4.3.8", 53 | "es6-promise": "^4.1.1", 54 | "eslint": "3.17.1", 55 | "eslint-config-standard": "7.0.1", 56 | "eslint-friendly-formatter": "2.0.7", 57 | "eslint-loader": "1.6.3", 58 | "eslint-plugin-html": "3.2.1", 59 | "eslint-plugin-promise": "3.5.0", 60 | "eslint-plugin-standard": "2.1.1", 61 | "extract-text-webpack-plugin": "2.1.0", 62 | "file-loader": "0.11.1", 63 | "gh-pages": "^1.0.0", 64 | "html-webpack-plugin": "2.30.1", 65 | "jasmine-core": "2.6.2", 66 | "karma": "1.7.0", 67 | "karma-babel-preprocessor": "6.0.1", 68 | "karma-chrome-launcher": "2.1.1", 69 | "karma-commonjs": "1.0.0", 70 | "karma-jasmine": "1.1.0", 71 | "karma-phantomjs-launcher": "1.0.4", 72 | "karma-spec-reporter": "0.0.31", 73 | "karma-webpack": "2.0.3", 74 | "less": "2.7.2", 75 | "less-loader": "3.0.0", 76 | "lodash-es": "^4.17.4", 77 | "normalize.css": "5.0.0", 78 | "opn": "4.0.2", 79 | "optimize-css-assets-webpack-plugin": "1.3.0", 80 | "phantomjs-prebuilt": "2.1.14", 81 | "postcss-loader": "1.3.3", 82 | "prismjs": "1.6.0", 83 | "rollup": "0.41.6", 84 | "rollup-plugin-alias": "1.2.1", 85 | "rollup-plugin-babel": "2.7.1", 86 | "rollup-plugin-commonjs": "8.0.2", 87 | "rollup-plugin-eslint": "3.0.0", 88 | "rollup-plugin-node-resolve": "2.0.0", 89 | "rollup-plugin-uglify": "2.0.1", 90 | "rollup-plugin-vue": "2.5.2", 91 | "style-loader": "0.14.1", 92 | "url-loader": "0.5.8", 93 | "vue": "2.4.2", 94 | "vue-loader": "11.1.4", 95 | "vue-router": "2.3.0", 96 | "vue-style-loader": "2.0.4", 97 | "vue-template-compiler": "2.4.2", 98 | "webpack": "2.2.1", 99 | "webpack-dev-server": "2.4.2", 100 | "webpack-merge": "4.1.0" 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/component-list.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | VeBar: { src: 'src/packages/bar/index.js', dist: 'lib/bar' }, 3 | VeBarMini: { src: 'src/packages/bar-mini/index.js', dist: 'lib/bar-mini' }, 4 | VeHistogram: { src: 'src/packages/histogram/index.js', dist: 'lib/histogram' }, 5 | VeHistogramMini: { src: 'src/packages/histogram-mini/index.js', dist: 'lib/histogram-mini' }, 6 | VeFunnel: { src: 'src/packages/funnel/index.js', dist: 'lib/funnel' }, 7 | VeLine: { src: 'src/packages/line/index.js', dist: 'lib/line' }, 8 | VeLineMini: { src: 'src/packages/Line-mini/index.js', dist: 'lib/line-mini' }, 9 | VePie: { src: 'src/packages/pie/index.js', dist: 'lib/pie' }, 10 | VeRing: { src: 'src/packages/ring/index.js', dist: 'lib/ring' }, 11 | VeRadar: { src: 'src/packages/radar/index.js', dist: 'lib/radar' }, 12 | VeWaterfall: { src: 'src/packages/waterfall/index.js', dist: 'lib/waterfall' }, 13 | VeIndex: { src: 'src/packages/index/index.js', dist: 'lib/index' }, 14 | VeChart: { src: 'src/packages/chart/index.js', dist: 'lib/chart' }, 15 | VeMap: { src: 'src/packages/map/index.js', dist: 'lib/map' }, 16 | VeBmap: { src: 'src/packages/bmap/index.js', dist: 'lib/bmap' }, 17 | VeSankey: { src: 'src/packages/sankey/index.js', dist: 'lib/sankey' }, 18 | Veheatmap: { src: 'src/packages/heatmap/index.js', dist: 'lib/heatmap' } 19 | } 20 | -------------------------------------------------------------------------------- /src/components/data-empty.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | -------------------------------------------------------------------------------- /src/components/loading.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 62 | -------------------------------------------------------------------------------- /src/echarts-base.js: -------------------------------------------------------------------------------- 1 | import echarts from 'echarts/lib/echarts' 2 | import 'echarts/lib/component/tooltip' 3 | import 'echarts/lib/component/legend' 4 | 5 | echarts.registerTheme('ve-chart', { 6 | categoryAxis: { 7 | axisLine: { show: false }, 8 | axisTick: { show: false }, 9 | splitLine: { show: false } 10 | }, 11 | valueAxis: { 12 | axisLine: { 13 | show: false 14 | }, 15 | axisLabel: { 16 | show: true, 17 | margin: 15, 18 | textStyle: { 19 | color: '#80848F' 20 | } 21 | }, 22 | splitLine: { 23 | show: true, 24 | lineStyle: { 25 | color: '#E9EAEC' 26 | } 27 | } 28 | }, 29 | line: { 30 | smooth: true 31 | }, 32 | grid: { 33 | containLabel: true, 34 | left: 10, 35 | right: 10 36 | } 37 | }) 38 | 39 | export const itemPoint = (color) => { 40 | return [ 41 | '' 49 | ].join('') 50 | } 51 | 52 | export const color = [ 53 | '#2d8cf0', '#2de2c5', '#fcc45f', 54 | '#ff8454', '#db425a', '#34508c', 55 | '#5bb6fd', '#56d08b', '#b3e768', 56 | '#71808f' 57 | ] 58 | 59 | export const HEAT_MAP_COLOR = ['#313695', '#4575b4', '#74add1', 60 | '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', 61 | '#fdae61', '#f46d43', '#d73027', '#a50026'] 62 | 63 | export const HEAT_BMAP_COLOR = ['blue', 'blue', 'green', 'yellow', 'red'] 64 | 65 | export default echarts 66 | -------------------------------------------------------------------------------- /src/index.es.js: -------------------------------------------------------------------------------- 1 | import VeBar from './packages/bar' 2 | import VeBarMini from './packages/bar-mini' 3 | import VeHistogram from './packages/histogram' 4 | import VeHistogramMini from './packages/histogram-mini' 5 | import VeLine from './packages/line' 6 | import VeLineMini from './packages/line-mini' 7 | import VePie from './packages/pie' 8 | import VeRing from './packages/ring' 9 | import VeWaterfall from './packages/waterfall' 10 | import VeFunnel from './packages/funnel' 11 | import VeRadar from './packages/radar' 12 | import VeChart from './packages/chart' 13 | import VeMap from './packages/map' 14 | import VeBmap from './packages/bmap' 15 | import VeSankey from './packages/sankey' 16 | import VeHeatmap from './packages/heatmap' 17 | 18 | const components = [ 19 | VeBar, 20 | VeBarMini, 21 | VeHistogram, 22 | VeHistogramMini, 23 | VeLine, 24 | VeLineMini, 25 | VePie, 26 | VeRing, 27 | VeWaterfall, 28 | VeFunnel, 29 | VeRadar, 30 | VeChart, 31 | VeMap, 32 | VeBmap, 33 | VeSankey, 34 | VeHeatmap 35 | ] 36 | 37 | function install (Vue, _) { 38 | components.forEach(component => { 39 | Vue.component(component.name, component) 40 | }) 41 | } 42 | 43 | export { 44 | VeBar, 45 | VeBarMini, 46 | VeHistogram, 47 | VeHistogramMini, 48 | VeRing, 49 | VeLine, 50 | VeLineMini, 51 | VePie, 52 | VeWaterfall, 53 | VeFunnel, 54 | VeRadar, 55 | VeChart, 56 | VeMap, 57 | VeBmap, 58 | VeSankey, 59 | VeHeatmap, 60 | install 61 | } 62 | -------------------------------------------------------------------------------- /src/packages/bar-mini/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { barmini } from './main' 3 | import Core from '../../core' 4 | 5 | export default { 6 | name: 'VeBarMini', 7 | mixins: [Core], 8 | created () { 9 | this.chartHandler = barmini 10 | this.echartsLib = echarts 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/packages/bar/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { bar } from './main' 3 | import Core from '../../core' 4 | 5 | export default { 6 | name: 'VeBar', 7 | mixins: [Core], 8 | created () { 9 | this.chartHandler = bar 10 | this.echartsLib = echarts 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/packages/bmap/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { bmap } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeBmap', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = bmap 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/bmap/main.js: -------------------------------------------------------------------------------- 1 | import 'echarts/extension/bmap/bmap' 2 | import { getBmap } from '../../utils' 3 | 4 | export const bmap = (_, __, settings) => { 5 | const { 6 | key, 7 | bmap 8 | } = settings 9 | if (!key) console.warn('settings.key must be a string.') 10 | 11 | return getBmap(key).then(_ => { 12 | return { bmap } 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /src/packages/chart/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { bar, histogram } from '../bar/main' 3 | import { line } from '../line/main' 4 | import { pie, ring } from '../pie/main' 5 | import { funnel } from '../funnel/main' 6 | import { radar } from '../radar/main' 7 | import { waterfall } from '../waterfall/main' 8 | import Core from '../../core' 9 | export default { 10 | name: 'VeChart', 11 | mixins: [Core], 12 | created () { 13 | this.chartLib = { 14 | bar, 15 | histogram, 16 | line, 17 | pie, 18 | ring, 19 | funnel, 20 | radar, 21 | waterfall 22 | } 23 | this.chartHandler = this.chartLib[this.settings.type] 24 | this.echartsLib = echarts 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/packages/funnel/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { funnel } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeFunnel', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = funnel 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/funnel/main.js: -------------------------------------------------------------------------------- 1 | import { itemPoint } from '../../echarts-base' 2 | import { getFormated } from '../../utils' 3 | import 'echarts/lib/chart/funnel' 4 | 5 | function getFunnelTooltip (dataType, digit) { 6 | return { 7 | trigger: 'item', 8 | formatter (item) { 9 | let tpl = [] 10 | tpl.push(itemPoint(item.color)) 11 | tpl.push(`${item.name}: ${getFormated(item.data.realValue, dataType, digit)}`) 12 | return tpl.join('') 13 | } 14 | } 15 | } 16 | 17 | function getFunnelLegend (args) { 18 | const { data, legendName } = args 19 | return { 20 | data, 21 | formatter (name) { 22 | return legendName[name] != null ? legendName[name] : name 23 | } 24 | } 25 | } 26 | 27 | function getFunnelSeries (args) { 28 | const { 29 | dimension, 30 | metrics, 31 | rows, 32 | sequence, 33 | ascending, 34 | label, 35 | labelLine, 36 | itemStyle 37 | } = args 38 | let series = { type: 'funnel' } 39 | rows.sort((a, b) => { 40 | return sequence.indexOf(a[dimension]) - sequence.indexOf(b[dimension]) 41 | }) 42 | 43 | let falseFunnel = false 44 | rows.some((row, index) => { 45 | if (index && row[metrics] > rows[index - 1][metrics]) { 46 | falseFunnel = true 47 | return true 48 | } 49 | }) 50 | 51 | const step = 100 / rows.length 52 | 53 | if (falseFunnel) { 54 | series.data = rows.slice().reverse().map((row, index) => ({ 55 | name: row[dimension], 56 | value: (index + 1) * step, 57 | realValue: row[metrics] 58 | })) 59 | } else { 60 | series.data = rows.map(row => ({ 61 | name: row[dimension], 62 | value: row[metrics], 63 | realValue: row[metrics] 64 | })) 65 | } 66 | 67 | if (ascending) series.sort = 'ascending' 68 | if (label) series.label = label 69 | if (labelLine) series.labelLine = labelLine 70 | if (itemStyle) series.itemStyle = itemStyle 71 | return series 72 | } 73 | 74 | export const funnel = (outerColumns, outerRows, settings, extra) => { 75 | const columns = outerColumns.slice() 76 | const rows = outerRows.slice() 77 | const { 78 | dataType = 'normal', 79 | dimension = columns[0], 80 | sequence = rows.map(row => row[dimension]), 81 | digit = 2, 82 | ascending, 83 | label, 84 | labelLine, 85 | legendName = {}, 86 | itemStyle 87 | } = settings 88 | const { tooltipVisible, legendVisible } = extra 89 | let metrics 90 | if (settings.metrics) { 91 | metrics = settings.metrics 92 | } else { 93 | let metricsTemp = columns.slice() 94 | metricsTemp.splice(columns.indexOf(dimension), 1) 95 | metrics = metricsTemp[0] 96 | } 97 | 98 | const tooltip = tooltipVisible && getFunnelTooltip(dataType, digit) 99 | const seriesParams = { 100 | dimension, 101 | metrics, 102 | rows, 103 | sequence, 104 | ascending, 105 | label, 106 | labelLine, 107 | itemStyle 108 | } 109 | const legend = legendVisible && getFunnelLegend({ data: sequence, legendName }) 110 | const series = getFunnelSeries(seriesParams) 111 | const options = { tooltip, legend, series } 112 | return options 113 | } 114 | -------------------------------------------------------------------------------- /src/packages/heatmap/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { heatmap } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeHeatmap', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = heatmap 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/heatmap/main.js: -------------------------------------------------------------------------------- 1 | import { default as echarts, itemPoint, HEAT_MAP_COLOR, HEAT_BMAP_COLOR } from '../../echarts-base' 2 | import 'echarts/lib/chart/heatmap' 3 | import 'echarts/lib/component/visualMap' 4 | import 'echarts/extension/bmap/bmap' 5 | import 'echarts/lib/chart/map' 6 | import { getBmap, getMapJSON, getFormated } from '../../utils' 7 | 8 | function getAxisList (rows, label) { 9 | const result = [] 10 | rows.forEach(row => { 11 | if (!~result.indexOf(row[label])) result.push(row[label]) 12 | }) 13 | return result 14 | } 15 | 16 | function getData (args) { 17 | const { rows, innerXAxisList, innerYAxisList, xDim, yDim, metrics, type } = args 18 | let result = null 19 | if (type === 'cartesian') { 20 | result = rows.map(row => { 21 | const xIndex = innerXAxisList.indexOf(row[xDim]) 22 | const yIndex = innerYAxisList.indexOf(row[yDim]) 23 | const value = metrics ? row[metrics] : 1 24 | return [xIndex, yIndex, value] 25 | }) 26 | } else { 27 | result = rows.map(row => { 28 | const value = metrics ? row[metrics] : 1 29 | return [row[xDim], row[yDim], value] 30 | }) 31 | } 32 | return result 33 | } 34 | 35 | function getAxis (list, name) { 36 | return { 37 | type: 'category', 38 | data: list, 39 | name, 40 | nameLocation: 'end', 41 | splitArea: { show: true } 42 | } 43 | } 44 | 45 | function getVisualMap (args) { 46 | const { innerMin: min, innerMax: max, type, heatColor } = args 47 | let result = { 48 | min, 49 | max, 50 | calculable: true 51 | } 52 | let extra = null 53 | if (type === 'map') { 54 | extra = { 55 | orient: 'vertical', 56 | left: 0, 57 | bottom: 0, 58 | inRange: { color: heatColor || HEAT_MAP_COLOR } 59 | } 60 | } else if (type === 'bmap') { 61 | extra = { 62 | show: false, 63 | orient: 'vertical', 64 | left: 0, 65 | bottom: 0, 66 | inRange: { color: heatColor || HEAT_BMAP_COLOR } 67 | } 68 | } else { 69 | extra = { 70 | orient: 'horizontal', 71 | left: 'center', 72 | bottom: 10, 73 | inRange: heatColor && { color: heatColor } 74 | } 75 | } 76 | 77 | return Object.assign(result, extra) 78 | } 79 | 80 | function getSeries (args) { 81 | const { chartData } = args 82 | return [{ 83 | type: 'heatmap', 84 | data: chartData 85 | }] 86 | } 87 | 88 | function getTooltip (args) { 89 | const { dataType, innerXAxisList, innerYAxisList, digit } = args 90 | 91 | return { 92 | trigger: 'item', 93 | formatter ({ color, data: [xDim, yDim, value] }) { 94 | const tpl = [] 95 | tpl.push(`${innerYAxisList[yDim]}
`) 96 | tpl.push(`${itemPoint(color)} ${innerXAxisList[xDim]}: `) 97 | tpl.push(getFormated(value, dataType, digit)) 98 | return tpl.join('') 99 | } 100 | } 101 | } 102 | 103 | export const heatmap = (columns, rows, settings, status) => { 104 | const { 105 | type = 'cartesian', // cartesian, map, bmap, 106 | xAxisList, 107 | yAxisList, 108 | dimension = [columns[0], columns[1]], 109 | metrics = columns[2], 110 | dataType = 'normal', 111 | min, 112 | max, 113 | digit, 114 | bmap, 115 | geo, 116 | key, 117 | position, 118 | positionJsonLink, 119 | beforeRegisterMap, 120 | pointSize = 10, 121 | blurSize = 5, 122 | heatColor, 123 | yAxisName, 124 | xAxisName 125 | } = settings 126 | const { tooltipVisible } = status 127 | let innerXAxisList = xAxisList 128 | let innerYAxisList = yAxisList 129 | let chartData = [] 130 | if (type === 'cartesian') { 131 | if (!innerXAxisList || !innerXAxisList.length) { 132 | innerXAxisList = getAxisList(rows, dimension[0]) 133 | } 134 | if (!innerYAxisList || !innerYAxisList.length) { 135 | innerYAxisList = getAxisList(rows, dimension[1]) 136 | } 137 | chartData = getData({ 138 | rows, 139 | innerXAxisList, 140 | innerYAxisList, 141 | xDim: dimension[0], 142 | yDim: dimension[1], 143 | metrics, 144 | type 145 | }) 146 | } else { 147 | chartData = getData({ 148 | rows, 149 | xDim: dimension[0], 150 | yDim: dimension[1], 151 | metrics, 152 | type 153 | }) 154 | } 155 | const metricsList = metrics ? rows.map(row => row[metrics]) : [0, 5] 156 | const innerMin = min || Math.min.apply(null, metricsList) 157 | const innerMax = max || Math.max.apply(null, metricsList) 158 | 159 | const xAxis = getAxis(innerXAxisList, xAxisName) 160 | const yAxis = getAxis(innerYAxisList, yAxisName) 161 | const visualMap = getVisualMap({ innerMin, innerMax, type, heatColor }) 162 | const series = getSeries({ chartData }) 163 | const tooltip = tooltipVisible && getTooltip({ 164 | dataType, 165 | innerXAxisList, 166 | innerYAxisList, 167 | digit 168 | }) 169 | 170 | const options = { visualMap, series } 171 | if (type === 'bmap') { 172 | Object.assign(options.series[0], { coordinateSystem: 'bmap', pointSize, blurSize }) 173 | 174 | return getBmap(key).then(_ => { 175 | return Object.assign({ bmap }, options) 176 | }) 177 | } else if (type === 'map') { 178 | options.series[0].coordinateSystem = 'geo' 179 | 180 | return getMapJSON(position, positionJsonLink).then(json => { 181 | const geoAttr = Object.assign({ map: position }, geo) 182 | if (beforeRegisterMap) json = beforeRegisterMap(json) 183 | echarts.registerMap(position, json) 184 | console.log(Object.assign({ geo: geoAttr }, options)) 185 | return Object.assign({ geo: geoAttr }, options) 186 | }) 187 | } else { 188 | return Object.assign({ xAxis, yAxis, tooltip }, options) 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/packages/histogram-mini/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { histogrammini } from '../bar-mini/main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeHistogramMini', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = histogrammini 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/histogram/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { histogram } from '../bar/main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeHistogram', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = histogram 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/index/index.js: -------------------------------------------------------------------------------- 1 | import VeBar from '../bar' 2 | import VeBarMini from '../bar-mini' 3 | import VeHistogram from '../histogram' 4 | import VeHistogramMini from '../histogram-mini' 5 | import VeLine from '../line' 6 | import VeLineMini from '../line-mini' 7 | import VePie from '../pie' 8 | import VeRing from '../ring' 9 | import VeWaterfall from '../waterfall' 10 | import VeFunnel from '../funnel' 11 | import VeRadar from '../radar' 12 | import VeChart from '../chart' 13 | import VeMap from '../map' 14 | import VeBmap from '../bmap' 15 | import VeSankey from '../sankey' 16 | import VeHeatmap from '../heatmap' 17 | 18 | import 'echarts/lib/chart/bar' 19 | import 'echarts/lib/chart/funnel' 20 | import 'echarts/lib/chart/line' 21 | import 'echarts/lib/chart/pie' 22 | import 'echarts/lib/chart/radar' 23 | 24 | const components = [ 25 | VeBar, 26 | VeBarMini, 27 | VeHistogram, 28 | VeHistogramMini, 29 | VeLine, 30 | VeLineMini, 31 | VePie, 32 | VeRing, 33 | VeWaterfall, 34 | VeFunnel, 35 | VeRadar, 36 | VeChart, 37 | VeMap, 38 | VeBmap, 39 | VeSankey, 40 | VeHeatmap 41 | ] 42 | 43 | function install (Vue, _) { 44 | components.forEach(component => { 45 | Vue.component(component.name, component) 46 | }) 47 | } 48 | 49 | if (typeof window !== 'undefined' && window.Vue) { 50 | install(window.Vue) 51 | } 52 | 53 | export default { 54 | VeBar, 55 | VeHistogram, 56 | VeRing, 57 | VeLine, 58 | VePie, 59 | VeWaterfall, 60 | VeFunnel, 61 | VeRadar, 62 | VeChart, 63 | VeMap, 64 | VeBmap, 65 | VeSankey, 66 | install 67 | } 68 | -------------------------------------------------------------------------------- /src/packages/line-mini/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { linemini } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeLineMini', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = linemini 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/line-mini/main.js: -------------------------------------------------------------------------------- 1 | import { itemPoint } from '../../echarts-base' 2 | import { getFormated, getStackMap } from '../../utils' 3 | import 'echarts/lib/chart/line' 4 | 5 | function getLineXAxis (args) { 6 | const { dimension, rows, xAxisName, axisVisible, xAxisType } = args 7 | return dimension.map((item, index) => ({ 8 | type: xAxisType, 9 | nameLocation: 'middle', 10 | nameGap: 22, 11 | boundaryGap: false, 12 | name: xAxisName[index] || '', 13 | axisTick: { 14 | show: false, 15 | lineStyle: { 16 | color: '#eee' 17 | }, 18 | length: 7 19 | }, 20 | axisLabel: { 21 | show: false, 22 | margin: 15, 23 | color: '#80848F' 24 | }, 25 | axisLine: { 26 | show: false 27 | }, 28 | data: rows.map(row => row[item]), 29 | show: axisVisible 30 | })) 31 | } 32 | 33 | function getLineSeries (args) { 34 | const { 35 | rows, 36 | axisSite, 37 | metrics, 38 | area, 39 | stack, 40 | nullAddZero, 41 | labelMap, 42 | label, 43 | itemStyle, 44 | lineStyle, 45 | areaStyle, 46 | xAxisType, 47 | dimension 48 | } = args 49 | let series = [] 50 | const dataTemp = {} 51 | const stackMap = stack && getStackMap(stack) 52 | metrics.forEach(item => { dataTemp[item] = [] }) 53 | rows.forEach(row => { 54 | metrics.forEach(item => { 55 | let value = null 56 | if (row[item] != null) { 57 | value = row[item] 58 | } else if (nullAddZero) { 59 | value = 0 60 | } 61 | const dataItem = xAxisType === 'category' 62 | ? value 63 | : [row[dimension[0]], value] 64 | dataTemp[item].push(dataItem) 65 | }) 66 | }) 67 | metrics.forEach(item => { 68 | let seriesItem = { 69 | name: labelMap[item] != null ? labelMap[item] : item, 70 | type: 'line', 71 | // 改变symbol 72 | showSymbol: false, 73 | symbolSize: 1, 74 | data: dataTemp[item] 75 | } 76 | 77 | if (area) seriesItem.areaStyle = { normal: {} } 78 | if (axisSite.right) { 79 | seriesItem.yAxisIndex = ~axisSite.right.indexOf(item) ? 1 : 0 80 | } 81 | 82 | if (stack && stackMap[item]) seriesItem.stack = stackMap[item] 83 | 84 | if (label) seriesItem.label = label 85 | if (itemStyle) seriesItem.itemStyle = itemStyle 86 | if (lineStyle) seriesItem.lineStyle = lineStyle 87 | if (areaStyle) seriesItem.areaStyle = areaStyle 88 | 89 | series.push(seriesItem) 90 | }) 91 | return series.length ? series : false 92 | } 93 | 94 | function getLineYAxis (args) { 95 | const { 96 | yAxisName, 97 | yAxisType, 98 | axisVisible, 99 | scale, 100 | min, 101 | max, 102 | digit 103 | } = args 104 | const yAxisBase = { 105 | type: 'value', 106 | axisTick: { 107 | show: false 108 | }, 109 | show: axisVisible 110 | } 111 | let yAxis = [] 112 | for (let i = 0; i < 2; i++) { 113 | if (yAxisType[i]) { 114 | yAxis[i] = Object.assign({}, yAxisBase, { 115 | axisLabel: { 116 | formatter (val) { 117 | return getFormated(val, yAxisType[i], digit) 118 | } 119 | } 120 | }) 121 | } else { 122 | yAxis[i] = Object.assign({}, yAxisBase) 123 | } 124 | yAxis[i].name = yAxisName[i] || '' 125 | yAxis[i].scale = scale[i] || false 126 | yAxis[i].min = min[i] || null 127 | yAxis[i].max = max[i] || null 128 | } 129 | return yAxis 130 | } 131 | 132 | function getLineTooltip (args) { 133 | const { axisSite, yAxisType, digit, labelMap, xAxisType } = args 134 | const rightItems = axisSite.right || [] 135 | const rightList = labelMap 136 | ? rightItems.map(item => { 137 | return labelMap[item] === undefined ? item : labelMap[item] 138 | }) 139 | : rightItems 140 | return { 141 | trigger: 'axis', 142 | // 空字符,图例标线 143 | axisPointer: { 144 | type: 'none' 145 | }, 146 | formatter (items) { 147 | let tpl = [] 148 | tpl.push(`${items[0].name}
`) 149 | items.forEach(item => { 150 | let showData = null 151 | const type = ~rightList.indexOf(item.seriesName) 152 | ? yAxisType[1] 153 | : yAxisType[0] 154 | const data = xAxisType === 'category' 155 | ? item.data 156 | : item.data[1] 157 | showData = getFormated(data, type, digit) 158 | tpl.push(itemPoint(item.color)) 159 | tpl.push(`${item.seriesName}: ${showData}`) 160 | tpl.push('
') 161 | }) 162 | return tpl.join('') 163 | } 164 | } 165 | } 166 | 167 | function getLegend (args) { 168 | const { metrics, legendName, labelMap } = args 169 | if (!legendName && !labelMap) return { data: metrics } 170 | const data = labelMap 171 | ? metrics.map(item => (labelMap[item] == null ? item : labelMap[item])) 172 | : metrics 173 | return { 174 | data, 175 | formatter (name) { 176 | return legendName[name] != null ? legendName[name] : name 177 | }, 178 | icon: 'roundRect', // custome 179 | itemHeight: 15, // custome 180 | itemWidth: 18, // custome 181 | itemGap: 18, // custome 182 | right: '3.4%', // custome 183 | show: false 184 | } 185 | } 186 | 187 | function getGrid () { 188 | return { 189 | show: false, 190 | left: '0%', 191 | right: '10%', 192 | top: '0%', 193 | bottom: '0%', 194 | containLabel: false, 195 | padding: 0 196 | } 197 | } 198 | 199 | export const linemini = (columns, rows, settings, extra) => { 200 | const { 201 | axisSite = {}, 202 | yAxisType = ['normal', 'normal'], 203 | xAxisType = 'category', 204 | yAxisName = [], 205 | dimension = [columns[0]], 206 | xAxisName = [], 207 | axisVisible = false, 208 | area, 209 | stack, 210 | scale = [false, false], 211 | min = [null, null], 212 | max = [null, null], 213 | nullAddZero = false, 214 | digit = 2, 215 | legendName = {}, 216 | labelMap = {}, 217 | label, 218 | itemStyle, 219 | lineStyle, 220 | areaStyle 221 | } = settings 222 | const { tooltipVisible, legendVisible } = extra 223 | let metrics = columns.slice() 224 | 225 | if (axisSite.left && axisSite.right) { 226 | metrics = axisSite.left.concat(axisSite.right) 227 | } else if (axisSite.left && !axisSite.right) { 228 | metrics = axisSite.left 229 | } else if (settings.metrics) { 230 | metrics = settings.metrics 231 | } else { 232 | metrics.splice(columns.indexOf(dimension[0]), 1) 233 | } 234 | 235 | const legend = legendVisible && getLegend({ metrics, legendName, labelMap }) 236 | const tooltip = tooltipVisible && getLineTooltip({ 237 | axisSite, 238 | yAxisType, 239 | digit, 240 | labelMap, 241 | xAxisType 242 | }) 243 | const xAxis = getLineXAxis({ 244 | dimension, 245 | rows, 246 | xAxisName, 247 | axisVisible, 248 | xAxisType 249 | }) 250 | const yAxis = getLineYAxis({ 251 | yAxisName, 252 | yAxisType, 253 | axisVisible, 254 | scale, 255 | min, 256 | max, 257 | digit 258 | }) 259 | const series = getLineSeries({ 260 | rows, 261 | axisSite, 262 | metrics, 263 | area, 264 | stack, 265 | nullAddZero, 266 | labelMap, 267 | label, 268 | itemStyle, 269 | lineStyle, 270 | areaStyle, 271 | xAxisType, 272 | dimension 273 | }) 274 | const grid = getGrid() 275 | if (!xAxis || !series) return false 276 | 277 | let options = { legend, xAxis, series, yAxis, tooltip, grid } 278 | return options 279 | } 280 | -------------------------------------------------------------------------------- /src/packages/line/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { line } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeLine', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = line 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/line/main.js: -------------------------------------------------------------------------------- 1 | import { itemPoint } from '../../echarts-base' 2 | import { getFormated, getStackMap } from '../../utils' 3 | import 'echarts/lib/chart/line' 4 | 5 | function getLineXAxis (args) { 6 | const { dimension, rows, xAxisName, axisVisible, xAxisType } = args 7 | return dimension.map((item, index) => ({ 8 | type: xAxisType, 9 | nameLocation: 'middle', 10 | nameGap: 22, 11 | boundaryGap: false, 12 | name: xAxisName[index] || '', 13 | axisTick: { 14 | show: true, 15 | lineStyle: { 16 | color: '#eee' 17 | }, 18 | length: 7 19 | }, 20 | axisLabel: { 21 | margin: 15, 22 | color: '#80848F' 23 | }, 24 | data: rows.map(row => row[item]), 25 | show: axisVisible 26 | })) 27 | } 28 | 29 | function getLineSeries (args) { 30 | const { 31 | rows, 32 | axisSite, 33 | metrics, 34 | area, 35 | stack, 36 | nullAddZero, 37 | labelMap, 38 | label, 39 | itemStyle, 40 | lineStyle, 41 | areaStyle, 42 | xAxisType, 43 | dimension 44 | } = args 45 | let series = [] 46 | const dataTemp = {} 47 | const stackMap = stack && getStackMap(stack) 48 | metrics.forEach(item => { dataTemp[item] = [] }) 49 | rows.forEach(row => { 50 | metrics.forEach(item => { 51 | let value = null 52 | if (row[item] != null) { 53 | value = row[item] 54 | } else if (nullAddZero) { 55 | value = 0 56 | } 57 | const dataItem = xAxisType === 'category' 58 | ? value 59 | : [row[dimension[0]], value] 60 | dataTemp[item].push(dataItem) 61 | }) 62 | }) 63 | metrics.forEach(item => { 64 | let seriesItem = { 65 | name: labelMap[item] != null ? labelMap[item] : item, 66 | type: 'line', 67 | data: dataTemp[item] 68 | } 69 | 70 | if (area) seriesItem.areaStyle = { normal: {} } 71 | if (axisSite.right) { 72 | seriesItem.yAxisIndex = ~axisSite.right.indexOf(item) ? 1 : 0 73 | } 74 | 75 | if (stack && stackMap[item]) seriesItem.stack = stackMap[item] 76 | 77 | if (label) seriesItem.label = label 78 | if (itemStyle) seriesItem.itemStyle = itemStyle 79 | if (lineStyle) seriesItem.lineStyle = lineStyle 80 | if (areaStyle) seriesItem.areaStyle = areaStyle 81 | 82 | series.push(seriesItem) 83 | }) 84 | return series.length ? series : false 85 | } 86 | 87 | function getLineYAxis (args) { 88 | const { 89 | yAxisName, 90 | yAxisType, 91 | axisVisible, 92 | scale, 93 | min, 94 | max, 95 | digit 96 | } = args 97 | const yAxisBase = { 98 | type: 'value', 99 | axisTick: { 100 | show: false 101 | }, 102 | show: axisVisible 103 | } 104 | let yAxis = [] 105 | for (let i = 0; i < 2; i++) { 106 | if (yAxisType[i]) { 107 | yAxis[i] = Object.assign({}, yAxisBase, { 108 | axisLabel: { 109 | formatter (val) { 110 | return getFormated(val, yAxisType[i], digit) 111 | } 112 | } 113 | }) 114 | } else { 115 | yAxis[i] = Object.assign({}, yAxisBase) 116 | } 117 | yAxis[i].name = yAxisName[i] || '' 118 | yAxis[i].scale = scale[i] || false 119 | yAxis[i].min = min[i] || null 120 | yAxis[i].max = max[i] || null 121 | } 122 | return yAxis 123 | } 124 | 125 | function getLineTooltip (args) { 126 | const { axisSite, yAxisType, digit, labelMap, xAxisType } = args 127 | const rightItems = axisSite.right || [] 128 | const rightList = labelMap 129 | ? rightItems.map(item => { 130 | return labelMap[item] === undefined ? item : labelMap[item] 131 | }) 132 | : rightItems 133 | return { 134 | trigger: 'axis', 135 | formatter (items) { 136 | let tpl = [] 137 | tpl.push(`${items[0].name}
`) 138 | items.forEach(item => { 139 | let showData = null 140 | const type = ~rightList.indexOf(item.seriesName) 141 | ? yAxisType[1] 142 | : yAxisType[0] 143 | const data = xAxisType === 'category' 144 | ? item.data 145 | : item.data[1] 146 | showData = getFormated(data, type, digit) 147 | tpl.push(itemPoint(item.color)) 148 | tpl.push(`${item.seriesName}: ${showData}`) 149 | tpl.push('
') 150 | }) 151 | return tpl.join('') 152 | } 153 | } 154 | } 155 | 156 | function getLegend (args) { 157 | const { metrics, legendName, labelMap } = args 158 | if (!legendName && !labelMap) return { data: metrics } 159 | const data = labelMap 160 | ? metrics.map(item => (labelMap[item] == null ? item : labelMap[item])) 161 | : metrics 162 | return { 163 | data, 164 | formatter (name) { 165 | return legendName[name] != null ? legendName[name] : name 166 | }, 167 | icon: 'roundRect', // custome 168 | itemHeight: 5, // custome 169 | itemWidth: 18, // custome 170 | itemGap: 18, // custome 171 | right: '3.4%' // custome 172 | } 173 | } 174 | 175 | export const line = (columns, rows, settings, extra) => { 176 | const { 177 | axisSite = {}, 178 | yAxisType = ['normal', 'normal'], 179 | xAxisType = 'category', 180 | yAxisName = [], 181 | dimension = [columns[0]], 182 | xAxisName = [], 183 | axisVisible = true, 184 | area, 185 | stack, 186 | scale = [false, false], 187 | min = [null, null], 188 | max = [null, null], 189 | nullAddZero = false, 190 | digit = 2, 191 | legendName = {}, 192 | labelMap = {}, 193 | label, 194 | itemStyle, 195 | lineStyle, 196 | areaStyle 197 | } = settings 198 | const { tooltipVisible, legendVisible } = extra 199 | let metrics = columns.slice() 200 | 201 | if (axisSite.left && axisSite.right) { 202 | metrics = axisSite.left.concat(axisSite.right) 203 | } else if (axisSite.left && !axisSite.right) { 204 | metrics = axisSite.left 205 | } else if (settings.metrics) { 206 | metrics = settings.metrics 207 | } else { 208 | metrics.splice(columns.indexOf(dimension[0]), 1) 209 | } 210 | 211 | const legend = legendVisible && getLegend({ metrics, legendName, labelMap }) 212 | const tooltip = tooltipVisible && getLineTooltip({ 213 | axisSite, 214 | yAxisType, 215 | digit, 216 | labelMap, 217 | xAxisType 218 | }) 219 | const xAxis = getLineXAxis({ 220 | dimension, 221 | rows, 222 | xAxisName, 223 | axisVisible, 224 | xAxisType 225 | }) 226 | const yAxis = getLineYAxis({ 227 | yAxisName, 228 | yAxisType, 229 | axisVisible, 230 | scale, 231 | min, 232 | max, 233 | digit 234 | }) 235 | const series = getLineSeries({ 236 | rows, 237 | axisSite, 238 | metrics, 239 | area, 240 | stack, 241 | nullAddZero, 242 | labelMap, 243 | label, 244 | itemStyle, 245 | lineStyle, 246 | areaStyle, 247 | xAxisType, 248 | dimension 249 | }) 250 | if (!xAxis || !series) return false 251 | 252 | let options = { legend, xAxis, series, yAxis, tooltip } 253 | return options 254 | } 255 | -------------------------------------------------------------------------------- /src/packages/map/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { map } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeMap', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = map 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/map/main.js: -------------------------------------------------------------------------------- 1 | import { default as echarts, itemPoint } from '../../echarts-base' 2 | import { getMapJSON, getFormated } from '../../utils' 3 | import 'echarts/lib/chart/map' 4 | 5 | function getTooltip (dataType, digit, dataStore, metrics, color, labelMap) { 6 | return { 7 | formatter (item) { 8 | let tpl = [] 9 | tpl.push(`${item.name}
`) 10 | metrics.forEach((label, index) => { 11 | let title = labelMap[label] != null ? labelMap[label] : label 12 | tpl.push(`${itemPoint(color[index])} ${title} : `) 13 | if (dataStore[item.name]) { 14 | tpl.push(getFormated(dataStore[item.name][label], dataType[label], digit)) 15 | } else { 16 | tpl.push('-') 17 | } 18 | tpl.push('
') 19 | }) 20 | return tpl.join(' ') 21 | } 22 | } 23 | } 24 | 25 | function getSeries (args) { 26 | const { 27 | position, 28 | selectData, 29 | dimension, 30 | metrics, 31 | rows, 32 | label, 33 | itemStyle, 34 | selectedMode, 35 | roam, 36 | center, 37 | aspectScale, 38 | boundingCoords, 39 | zoom, 40 | labelMap, 41 | scaleLimit, 42 | mapGrid 43 | } = args 44 | const result = [] 45 | const mapBase = { 46 | type: 'map', 47 | mapType: position 48 | } 49 | 50 | metrics.forEach(itemName => { 51 | const itemResult = Object.assign({ 52 | name: labelMap[itemName] != null ? labelMap[itemName] : itemName, 53 | data: [], 54 | selectedMode, 55 | roam, 56 | center, 57 | aspectScale, 58 | boundingCoords, 59 | zoom, 60 | scaleLimit 61 | }, mapBase) 62 | 63 | if (mapGrid) { 64 | Object.keys(mapGrid).forEach(key => { 65 | itemResult[key] = mapGrid[key] 66 | }) 67 | } 68 | 69 | setGeoLabel(itemStyle, itemResult, 'itemStyle') 70 | setGeoLabel(label, itemResult, 'label') 71 | 72 | rows.forEach(row => { 73 | itemResult.data.push({ 74 | name: row[dimension], 75 | value: row[itemName], 76 | selected: selectData 77 | }) 78 | }) 79 | result.push(itemResult) 80 | }) 81 | 82 | return result 83 | } 84 | 85 | function setGeoLabel (value, target, label) { 86 | if (typeof value === 'object') { 87 | target[label] = value 88 | } else if (value) { 89 | target[label] = { 90 | normal: { show: true }, 91 | emphasis: { show: true } 92 | } 93 | } 94 | } 95 | 96 | function getLegendMap (args) { 97 | const { metrics, legendName, labelMap } = args 98 | if (!legendName && !labelMap) return { data: metrics } 99 | const data = labelMap 100 | ? metrics.map(item => (labelMap[item] == null ? item : labelMap[item])) 101 | : metrics 102 | return { 103 | data, 104 | formatter (name) { 105 | return legendName[name] != null ? legendName[name] : name 106 | } 107 | } 108 | } 109 | 110 | export const map = (columns, rows, settings, extra) => { 111 | const { 112 | position = 'china', 113 | selectData = false, 114 | selectedMode, 115 | label = true, 116 | dataType = {}, 117 | digit = 2, 118 | dimension = columns[0], 119 | roam, 120 | center, 121 | aspectScale, 122 | boundingCoords, 123 | zoom, 124 | scaleLimit, 125 | legendName = {}, 126 | labelMap = {}, 127 | mapGrid, 128 | itemStyle, 129 | positionJsonLink, 130 | beforeRegisterMap 131 | } = settings 132 | let metrics = columns.slice() 133 | if (settings.metrics) { 134 | metrics = settings.metrics 135 | } else { 136 | metrics.splice(columns.indexOf(dimension), 1) 137 | } 138 | const { tooltipVisible, legendVisible, color } = extra 139 | const dataStore = {} 140 | rows.forEach(row => { dataStore[row[dimension]] = row }) 141 | const tooltip = tooltipVisible && getTooltip(dataType, digit, dataStore, metrics, color, labelMap) 142 | const legend = legendVisible && getLegendMap({ metrics, legendName, labelMap }) 143 | const seriesParams = { 144 | position, 145 | selectData, 146 | label, 147 | itemStyle, 148 | dimension, 149 | metrics, 150 | rows, 151 | selectedMode, 152 | roam, 153 | center, 154 | aspectScale, 155 | boundingCoords, 156 | zoom, 157 | labelMap, 158 | scaleLimit, 159 | mapGrid 160 | } 161 | const series = getSeries(seriesParams) 162 | 163 | return getMapJSON(position, positionJsonLink).then(json => { 164 | if (beforeRegisterMap) json = beforeRegisterMap(json) 165 | echarts.registerMap(position, json) 166 | return { series, tooltip, legend } 167 | }) 168 | } 169 | -------------------------------------------------------------------------------- /src/packages/pie/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { pie } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VePie', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = pie 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/radar/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { radar } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeRadar', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = radar 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/radar/main.js: -------------------------------------------------------------------------------- 1 | import { itemPoint } from '../../echarts-base' 2 | import { getFormated } from '../../utils' 3 | import 'echarts/lib/chart/radar' 4 | 5 | function getRadarLegend (rows, dimension, legendName) { 6 | let legendData = rows.map(row => row[dimension]) 7 | legendData = legendData.map(each => { 8 | return { 9 | 'name': each, 10 | 'icon': 'emptyCircle' 11 | } 12 | }) 13 | return { 14 | data: legendData, 15 | orient: 'vertical', 16 | right: '5%', 17 | top: '10%', 18 | formatter (name) { 19 | return legendName[name] != null ? legendName[name] : name 20 | } 21 | } 22 | } 23 | 24 | function getRadarTooltip (dataType, radar, digit) { 25 | const typeTemp = [] 26 | const nameTemp = [] 27 | radar.indicator.map((item, index) => { 28 | typeTemp[index] = dataType[item.name] 29 | nameTemp[index] = item.name 30 | }) 31 | return { 32 | formatter (item) { 33 | const tpl = [] 34 | tpl.push(itemPoint(item.color)) 35 | tpl.push(`${item.name}
`) 36 | item.data.value.forEach((val, index) => { 37 | tpl.push(`${nameTemp[index]}: `) 38 | tpl.push(`${getFormated(val, typeTemp[index], digit)}
`) 39 | }) 40 | return tpl.join('') 41 | } 42 | } 43 | } 44 | 45 | function getRadarSetting (rows, metrics, labelMap) { 46 | const settingBase = { 47 | indicator: [], 48 | // shape: 'circle', 49 | splitNumber: 5 50 | } 51 | let indicatorTemp = {} 52 | rows.forEach(items => { 53 | metrics.forEach(item => { 54 | const key = labelMap[item] != null 55 | ? labelMap[item] 56 | : item 57 | if (!indicatorTemp[key]) { 58 | indicatorTemp[key] = [items[item]] 59 | } else { 60 | indicatorTemp[key].push(items[item]) 61 | } 62 | }) 63 | }) 64 | settingBase.indicator = Object.keys(indicatorTemp).map(key => { 65 | return { 66 | name: key, 67 | max: Math.max.apply(null, indicatorTemp[key]) 68 | } 69 | }) 70 | return settingBase 71 | } 72 | 73 | function getRadarSeries (args) { 74 | const { 75 | rows, 76 | dimension, 77 | metrics, 78 | radar, 79 | label, 80 | itemStyle, 81 | lineStyle, 82 | labelMap, 83 | areaStyle 84 | } = args 85 | let radarIndexObj = {} 86 | radar.indicator.forEach((item, index) => { 87 | const name = item.name 88 | radarIndexObj[name] = index 89 | }) 90 | 91 | const seriesData = rows.map(row => { 92 | const serieData = { 93 | value: [], 94 | name: row[dimension] 95 | } 96 | Object.keys(row).forEach(key => { 97 | if (~metrics.indexOf(key)) { 98 | let k = labelMap[key] != null 99 | ? radarIndexObj[labelMap[key]] 100 | : radarIndexObj[key] 101 | serieData.value[k] = row[key] 102 | } 103 | }) 104 | return serieData 105 | }) 106 | const result = { 107 | name: dimension, 108 | type: 'radar', 109 | data: seriesData 110 | } 111 | if (label) result.label = label 112 | if (itemStyle) result.itemStyle = itemStyle 113 | if (lineStyle) result.lineStyle = lineStyle 114 | if (areaStyle) result.areaStyle = areaStyle 115 | return [result] 116 | } 117 | 118 | export const radar = (columns, rows, settings, extra) => { 119 | const { 120 | dataType = {}, 121 | legendName = {}, 122 | labelMap = {}, 123 | dimension = columns[0], 124 | digit = 2, 125 | label, 126 | itemStyle, 127 | lineStyle, 128 | areaStyle 129 | } = settings 130 | const { tooltipVisible, legendVisible } = extra 131 | let metrics = columns.slice() 132 | if (settings.metrics) { 133 | metrics = settings.metrics 134 | } else { 135 | metrics.splice(columns.indexOf(dimension), 1) 136 | } 137 | const legend = legendVisible && getRadarLegend(rows, dimension, legendName) 138 | const radar = getRadarSetting(rows, metrics, labelMap) 139 | const tooltip = tooltipVisible && getRadarTooltip(dataType, radar, digit) 140 | const series = getRadarSeries({ 141 | rows, 142 | dimension, 143 | metrics, 144 | radar, 145 | label, 146 | itemStyle, 147 | lineStyle, 148 | labelMap, 149 | areaStyle 150 | }) 151 | const options = { legend, tooltip, radar, series } 152 | return options 153 | } 154 | -------------------------------------------------------------------------------- /src/packages/ring/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { ring } from '../pie/main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeRing', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = ring 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/sankey/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { sankey } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeSankey', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = sankey 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/sankey/main.js: -------------------------------------------------------------------------------- 1 | import { getFormated } from '../../utils' 2 | import { itemPoint } from '../../echarts-base' 3 | import 'echarts/lib/chart/sankey' 4 | 5 | function getTooltip (args) { 6 | const { 7 | itemDataType, 8 | linksDataType, 9 | digit 10 | } = args 11 | return { 12 | trigger: 'item', 13 | formatter (item) { 14 | const tpl = [] 15 | const { name, data, value, color } = item 16 | tpl.push(itemPoint(color)) 17 | tpl.push(`${name} : `) 18 | if (data && data.source) { 19 | tpl.push(`${getFormated(value, linksDataType, digit)}
`) 20 | } else { 21 | tpl.push(`${getFormated(value, itemDataType, digit)}
`) 22 | } 23 | return tpl.join('') 24 | } 25 | } 26 | } 27 | 28 | function getSeries (args) { 29 | const { 30 | rows, 31 | dimension, 32 | metrics, 33 | links, 34 | valueFull, 35 | useDataValue, 36 | label, 37 | itemStyle, 38 | lineStyle 39 | } = args 40 | const dataMap = {} 41 | const seriesData = rows.map(row => { 42 | dataMap[row[dimension]] = row[metrics] 43 | return { name: row[dimension], value: row[metrics] } 44 | }) 45 | let innerLinks = null 46 | if (useDataValue) { 47 | innerLinks = links.map(link => { 48 | return Object.assign({}, link, { value: dataMap[link.target] }) 49 | }) 50 | } else if (!valueFull) { 51 | innerLinks = links.map(link => { 52 | return link.value == null 53 | ? Object.assign({}, link, { value: dataMap[link.target] }) 54 | : link 55 | }) 56 | } else { 57 | innerLinks = links 58 | } 59 | 60 | const result = { 61 | type: 'sankey', 62 | data: seriesData, 63 | links: innerLinks 64 | } 65 | if (label) result.label = label 66 | if (itemStyle) result.itemStyle = itemStyle 67 | if (lineStyle) result.lineStyle = lineStyle 68 | return [result] 69 | } 70 | 71 | export const sankey = (columns, rows, settings, extra) => { 72 | const { 73 | links, 74 | dimension = columns[0], 75 | metrics = columns[1], 76 | dataType = ['normal', 'normal'], 77 | digit = 2, 78 | valueFull = false, 79 | useDataValue = false, 80 | label, 81 | itemStyle, 82 | lineStyle 83 | } = settings 84 | 85 | if (!links) { 86 | console.warn('links is needed in settings!') 87 | return 88 | } 89 | 90 | const itemDataType = dataType[0] 91 | const linksDataType = dataType[1] 92 | const tooltip = getTooltip({ 93 | itemDataType, 94 | linksDataType, 95 | digit 96 | }) 97 | const series = getSeries({ 98 | rows, 99 | dimension, 100 | metrics, 101 | links, 102 | valueFull, 103 | useDataValue, 104 | label, 105 | itemStyle, 106 | lineStyle 107 | }) 108 | return { tooltip, series } 109 | } 110 | -------------------------------------------------------------------------------- /src/packages/waterfall/index.js: -------------------------------------------------------------------------------- 1 | import echarts from '../../echarts-base' 2 | import { waterfall } from './main' 3 | import Core from '../../core' 4 | export default { 5 | name: 'VeWaterfall', 6 | mixins: [Core], 7 | created () { 8 | this.chartHandler = waterfall 9 | this.echartsLib = echarts 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/packages/waterfall/main.js: -------------------------------------------------------------------------------- 1 | import { getFormated } from '../../utils' 2 | import 'echarts/lib/chart/bar' 3 | 4 | function getWaterfallTooltip (dataType, digit) { 5 | return { 6 | trigger: 'axis', 7 | axisPointer: { type: 'shadow' }, 8 | formatter (items) { 9 | const item = items[1] 10 | return [ 11 | `${item.name}
${item.seriesName} :`, 12 | `${getFormated(item.value, dataType, digit)}` 13 | ].join('') 14 | } 15 | } 16 | } 17 | 18 | function getWaterfallXAxis (args) { 19 | const { 20 | dimension, 21 | rows, 22 | remainStatus, 23 | totalName, 24 | remainName, 25 | labelMap, 26 | xAxisName, 27 | axisVisible 28 | } = args 29 | let xAxisData = [totalName].concat(rows.map(row => row[dimension])) 30 | if (remainStatus === 'have-remain') { 31 | xAxisData = xAxisData.concat([remainName]) 32 | } 33 | 34 | return { 35 | type: 'category', 36 | name: labelMap && labelMap[xAxisName] || xAxisName, 37 | splitLine: { show: false }, 38 | data: xAxisData, 39 | show: axisVisible 40 | } 41 | } 42 | 43 | function getWaterfallYAxis (args) { 44 | const { dataType, yAxisName, axisVisible, digit, labelMap } = args 45 | return { 46 | type: 'value', 47 | name: labelMap[yAxisName] != null ? labelMap[yAxisName] : yAxisName, 48 | axisTick: { show: false }, 49 | axisLabel: { 50 | formatter (val) { 51 | return getFormated(val, dataType, digit) 52 | } 53 | }, 54 | show: axisVisible 55 | } 56 | } 57 | 58 | function getWaterfallSeries (args) { 59 | const { 60 | dataType, 61 | rows, 62 | metrics, 63 | totalNum, 64 | remainStatus, 65 | dataSum, 66 | digit 67 | } = args 68 | const seriesBase = { type: 'bar', stack: '总量' } 69 | let dataSumTemp = dataSum 70 | let totalNumTemp = totalNum 71 | let assistData 72 | let mainData 73 | const rowData = rows.map(row => row[metrics]) 74 | 75 | if (remainStatus === 'have-remain') { 76 | assistData = [0].concat(rows.map(row => { 77 | totalNumTemp -= row[metrics] 78 | return totalNumTemp 79 | })).concat([0]) 80 | mainData = [totalNum].concat(rowData).concat([totalNum - dataSum]) 81 | } else { 82 | assistData = [0].concat(rows.map(row => { 83 | dataSumTemp -= row[metrics] 84 | return dataSumTemp 85 | })) 86 | mainData = [dataSum].concat(rowData) 87 | } 88 | const series = [] 89 | 90 | series.push(Object.assign({ 91 | name: '辅助', 92 | itemStyle: { 93 | normal: { opacity: 0 }, 94 | emphasis: { opacity: 0 } 95 | }, 96 | data: assistData 97 | }, seriesBase)) 98 | 99 | series.push(Object.assign({ 100 | name: '数值', 101 | label: { 102 | normal: { 103 | show: true, 104 | position: 'top', 105 | formatter (item) { 106 | return getFormated(item.value, dataType, digit) 107 | } 108 | } 109 | }, 110 | data: mainData 111 | }, seriesBase)) 112 | return series 113 | } 114 | 115 | function getWaterfallRemainStatus (dataSum, totalNum) { 116 | if (!totalNum) return 'not-total' 117 | return totalNum > dataSum ? 'have-remain' : 'none-remain' 118 | } 119 | 120 | export const waterfall = (columns, rows, settings, extra) => { 121 | const { 122 | dataType = 'normal', 123 | dimension = columns[0], 124 | totalName = '总计', 125 | totalNum, 126 | remainName = '其他', 127 | xAxisName = dimension, 128 | labelMap = {}, 129 | axisVisible = true, 130 | digit = 2 131 | } = settings 132 | const { tooltipVisible } = extra 133 | let metricsTemp = columns.slice() 134 | metricsTemp.splice(metricsTemp.indexOf(dimension), 1) 135 | const metrics = metricsTemp[0] 136 | const yAxisName = metrics 137 | const tooltip = tooltipVisible && getWaterfallTooltip(dataType, digit) 138 | const dataSum = parseFloat(rows.reduce((pre, cur) => { 139 | return pre + Number(cur[metrics]) 140 | }, 0).toFixed(digit)) 141 | const remainStatus = getWaterfallRemainStatus(dataSum, totalNum) 142 | const xAxisParams = { 143 | dimension, 144 | rows, 145 | remainStatus, 146 | totalName, 147 | remainName, 148 | xAxisName, 149 | labelMap, 150 | axisVisible 151 | } 152 | const xAxis = getWaterfallXAxis(xAxisParams) 153 | const yAxis = getWaterfallYAxis({ dataType, yAxisName, axisVisible, digit, labelMap }) 154 | const seriesParams = { 155 | dataType, 156 | rows, 157 | dimension, 158 | metrics, 159 | totalNum, 160 | remainStatus, 161 | dataSum, 162 | digit 163 | } 164 | const series = getWaterfallSeries(seriesParams) 165 | const options = { tooltip, xAxis, yAxis, series } 166 | return options 167 | } 168 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export const numberFormat = (val, digits = 2) => { 2 | if (isNaN(+val)) return val 3 | 4 | let symbolMap = [ 5 | { value: 1E18, symbol: 'E' }, 6 | { value: 1E15, symbol: 'P' }, 7 | { value: 1E12, symbol: 'T' }, 8 | { value: 1E9, symbol: 'B' }, 9 | { value: 1E6, symbol: 'M' }, 10 | { value: 1E3, symbol: 'k' } 11 | ] 12 | 13 | for (let i = 0; i < symbolMap.length; i++) { 14 | if (Math.abs(val) >= symbolMap[i].value) { 15 | return (val / symbolMap[i].value).toFixed(digits) + symbolMap[i].symbol 16 | } 17 | } 18 | 19 | return val.toString() 20 | } 21 | 22 | export const formatTausends = (num) => { 23 | return String(num).replace(/^(\s+|-)?\d+(?=.?\d*($|\s))/g, (m) => { 24 | return m.replace(/(?=(?!\b)(\d{3})+$)/g, ',') 25 | }) 26 | } 27 | 28 | export const getFormated = (val, type, digit = 2, defaultVal = '-') => { 29 | if (val == null || isNaN(val)) return defaultVal 30 | switch (type) { 31 | case 'KMB': return numberFormat(val) 32 | case 'percent': return `${parseFloat((val * 100).toFixed(digit))}%` 33 | case 'normal': return formatTausends(val) 34 | default: return val 35 | } 36 | } 37 | 38 | export const getLineKB = (s, v) => { 39 | const result = [] 40 | result[0] = (s[1] - s[0]) / (v[1] - v[0]) 41 | result[1] = s[0] - result[0] * v[0] 42 | return result 43 | } 44 | 45 | export const getStackMap = (stack) => { 46 | const stackMap = {} 47 | Object.keys(stack).forEach(item => { 48 | stack[item].forEach(name => { 49 | stackMap[name] = item 50 | }) 51 | }) 52 | return stackMap 53 | } 54 | 55 | export const $get = (url) => { 56 | return new Promise((resolve, reject) => { 57 | const xhr = new XMLHttpRequest() 58 | xhr.open('GET', url) 59 | xhr.send(null) 60 | xhr.onload = () => { 61 | resolve(JSON.parse(xhr.responseText)) 62 | } 63 | xhr.onerror = () => { 64 | reject(JSON.parse(xhr.responseText)) 65 | } 66 | }) 67 | } 68 | 69 | const MAP_URL_PREFIX = 'https://unpkg.com/echarts@3.6.2/map/json/' 70 | 71 | export const getMapJSON = (position, positionJsonLink) => { 72 | const link = positionJsonLink || `${MAP_URL_PREFIX}${position}.json` 73 | return $get(link) 74 | } 75 | 76 | let mapPromise = null 77 | 78 | export const getBmap = (key) => { 79 | if (!mapPromise) { 80 | mapPromise = new Promise((resolve, reject) => { 81 | const callbackName = `bmap${Date.now()}` 82 | window[callbackName] = resolve 83 | const script = document.createElement('script') 84 | script.src = [ 85 | 'https://api.map.baidu.com/api?v=2.0', 86 | `ak=${key}`, 87 | `callback=${callbackName}` 88 | ].join('&') 89 | 90 | document.body.appendChild(script) 91 | }) 92 | } 93 | return mapPromise 94 | } 95 | 96 | export const clone = (v) => JSON.parse(JSON.stringify(v)) 97 | 98 | export const getType = (v) => { 99 | return Object.prototype.toString.call(v) 100 | } 101 | 102 | export const toKebab = (v) => v.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() 103 | 104 | export const isArray = (v) => { 105 | return getType(v) === '[object Array]' 106 | } 107 | 108 | export const isObject = (v) => { 109 | return getType(v) === '[object Object]' 110 | } 111 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | import Vue from 'vue' 3 | import chartData from '../examples/data/index.js' 4 | import 'echarts/lib/component/tooltip' 5 | import 'echarts/lib/component/legend' 6 | 7 | window.Promise = require('es6-promise').Promise 8 | import { 9 | VeLine, 10 | VeBar, 11 | VeHistogram, 12 | VePie, 13 | VeRing, 14 | VeFunnel, 15 | VeRadar, 16 | VeWaterfall, 17 | VeChart, 18 | VeMap, 19 | VeSankey, 20 | VeHeatmap 21 | } from '../lib/index.esm' 22 | 23 | const comps = { 24 | line: VeLine, 25 | bar: VeBar, 26 | histogram: VeHistogram, 27 | pie: VePie, 28 | ring: VeRing, 29 | funnel: VeFunnel, 30 | radar: VeRadar, 31 | waterfall: VeWaterfall, 32 | chart: VeChart, 33 | map: VeMap, 34 | sankey: VeSankey, 35 | heatmap: VeHeatmap 36 | } 37 | let box 38 | let vm = {} 39 | createBox() 40 | 41 | afterEach(() => { 42 | if (vm.$el) document.body.removeChild(vm.$el) 43 | createBox() 44 | }) 45 | 46 | Object.keys(comps).forEach(type => { 47 | chartData[type].data.forEach(item => { 48 | describe(type + ': ', () => { 49 | testMount(type, comps[type], item) 50 | }) 51 | }) 52 | }) 53 | 54 | function testMount (type, comp, item) { 55 | it(item.name, () => { 56 | const Ctor = Vue.extend(comp) 57 | const vm = new Ctor({ 58 | propsData: { data: item.data, settings: item.settings } 59 | }).$mount(box) 60 | expect(vm.$el.classList.contains('ve-' + type)).toEqual(true) 61 | }) 62 | } 63 | 64 | function createBox () { 65 | box = document.createElement('div') 66 | box.id = 'app' 67 | document.body.appendChild(box) 68 | } 69 | -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | module.exports = function (config) { 2 | config.set({ 3 | frameworks: ['jasmine'], 4 | files: [ 5 | './index.js' 6 | ], 7 | browsers: ['PhantomJS'], 8 | reporters: ['spec'], 9 | preprocessors: { 10 | './index.js': ['webpack'] 11 | }, 12 | webpack: { 13 | devtool: 'inline-source-map', 14 | module: { 15 | loaders: [ 16 | { 17 | test: /\.(js)$/, 18 | loader: 'babel-loader' 19 | } 20 | ] 21 | }, 22 | resolve: { 23 | extensions: ['.js', '.vue'] 24 | } 25 | }, 26 | singleRun: true 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /test/load/cdn/all/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/load/cdn/bmap/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/load/cdn/heatmap/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /test/load/cdn/line/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 12 |
13 | 14 | 15 | 16 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/load/webpack/all/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 24 | -------------------------------------------------------------------------------- /test/load/webpack/all/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | 4 | import VeCharts from '../../../../lib/index.common' 5 | 6 | Vue.use(VeCharts) 7 | /* eslint-disable no-new */ 8 | new Vue({ 9 | el: '#app', 10 | render: h => h(App) 11 | }) 12 | -------------------------------------------------------------------------------- /test/load/webpack/all/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | entry: { 7 | app: './index.js' 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, '../dist'), 11 | filename: 'index.js', 12 | publicPath: '/' 13 | }, 14 | resolve: { 15 | extensions: ['.js', '.vue'] 16 | }, 17 | devServer: { 18 | port: '8180', 19 | hot: true, 20 | stats: 'errors-only' 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.vue$/, 26 | loader: 'vue-loader' 27 | }, 28 | { 29 | test: /\.js$/, 30 | loader: 'babel-loader' 31 | }, 32 | { 33 | test: /\.css$/, 34 | use: ['style-loader', 'css-loader'] 35 | } 36 | ] 37 | }, 38 | plugins: [ 39 | new webpack.DefinePlugin({ 40 | 'process.env': { 41 | NODE_ENV: '"development"' 42 | } 43 | }), 44 | new webpack.HotModuleReplacementPlugin(), 45 | new HtmlWebpackPlugin({ 46 | filename: 'index.html', 47 | template: '../index.html', 48 | inject: true 49 | }) 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /test/load/webpack/css-part/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | -------------------------------------------------------------------------------- /test/load/webpack/css-part/index.js: -------------------------------------------------------------------------------- 1 | 2 | import Vue from 'vue' 3 | import App from './App' 4 | 5 | /* eslint-disable no-new */ 6 | new Vue({ 7 | el: '#app', 8 | render: h => h(App) 9 | }) 10 | -------------------------------------------------------------------------------- /test/load/webpack/css-part/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | entry: { 7 | app: './index.js' 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, '../dist'), 11 | filename: 'index.js', 12 | publicPath: '/' 13 | }, 14 | resolve: { 15 | extensions: ['.js', '.vue'] 16 | }, 17 | devServer: { 18 | port: '8180', 19 | hot: true, 20 | stats: 'errors-only' 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.vue$/, 26 | loader: 'vue-loader' 27 | }, 28 | { 29 | test: /\.js$/, 30 | loader: 'babel-loader', 31 | query: { compact: false } 32 | }, 33 | { 34 | test: /\.css$/, 35 | use: ['style-loader', 'css-loader'] 36 | } 37 | ] 38 | }, 39 | plugins: [ 40 | new webpack.DefinePlugin({ 41 | 'process.env': { 42 | NODE_ENV: '"development"' 43 | } 44 | }), 45 | new webpack.HotModuleReplacementPlugin(), 46 | new HtmlWebpackPlugin({ 47 | filename: 'index.html', 48 | template: '../index.html', 49 | inject: true 50 | }) 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /test/load/webpack/esm/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 52 | -------------------------------------------------------------------------------- /test/load/webpack/esm/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | 4 | /* eslint-disable no-new */ 5 | new Vue({ 6 | el: '#app', 7 | render: h => h(App) 8 | }) 9 | -------------------------------------------------------------------------------- /test/load/webpack/esm/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | entry: { 7 | app: './index.js' 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, '../dist'), 11 | filename: 'index.js', 12 | publicPath: '/' 13 | }, 14 | resolve: { 15 | extensions: ['.js', '.vue'] 16 | }, 17 | devServer: { 18 | port: '8180', 19 | hot: true, 20 | stats: 'errors-only' 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.vue$/, 26 | loader: 'vue-loader' 27 | }, 28 | { 29 | test: /\.js$/, 30 | loader: 'babel-loader', 31 | query: { compact: false } 32 | }, 33 | { 34 | test: /\.css$/, 35 | use: ['style-loader', 'css-loader'] 36 | } 37 | ] 38 | }, 39 | plugins: [ 40 | new webpack.DefinePlugin({ 41 | 'process.env': { 42 | NODE_ENV: '"development"' 43 | } 44 | }), 45 | new webpack.HotModuleReplacementPlugin(), 46 | new HtmlWebpackPlugin({ 47 | filename: 'index.html', 48 | template: '../index.html', 49 | inject: true 50 | }) 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /test/load/webpack/heatmap/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 40 | -------------------------------------------------------------------------------- /test/load/webpack/heatmap/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | 4 | /* eslint-disable no-new */ 5 | new Vue({ 6 | el: '#app', 7 | render: h => h(App) 8 | }) 9 | -------------------------------------------------------------------------------- /test/load/webpack/heatmap/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | entry: { 7 | app: './index.js' 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, '../dist'), 11 | filename: 'index.js', 12 | publicPath: '/' 13 | }, 14 | resolve: { 15 | extensions: ['.js', '.vue'] 16 | }, 17 | devServer: { 18 | port: '8180', 19 | hot: true, 20 | stats: 'errors-only' 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.vue$/, 26 | loader: 'vue-loader' 27 | }, 28 | { 29 | test: /\.js$/, 30 | loader: 'babel-loader' 31 | }, 32 | { 33 | test: /\.css$/, 34 | use: ['style-loader', 'css-loader'] 35 | } 36 | ] 37 | }, 38 | plugins: [ 39 | new webpack.DefinePlugin({ 40 | 'process.env': { 41 | NODE_ENV: '"development"' 42 | } 43 | }), 44 | new webpack.HotModuleReplacementPlugin(), 45 | new HtmlWebpackPlugin({ 46 | filename: 'index.html', 47 | template: '../index.html', 48 | inject: true 49 | }) 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /test/load/webpack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /test/load/webpack/line/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 27 | -------------------------------------------------------------------------------- /test/load/webpack/line/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | 4 | /* eslint-disable no-new */ 5 | new Vue({ 6 | el: '#app', 7 | render: h => h(App) 8 | }) 9 | -------------------------------------------------------------------------------- /test/load/webpack/line/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack') 2 | const path = require('path') 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | 5 | module.exports = { 6 | entry: { 7 | app: './index.js' 8 | }, 9 | output: { 10 | path: path.resolve(__dirname, '../dist'), 11 | filename: 'index.js', 12 | publicPath: '/' 13 | }, 14 | resolve: { 15 | extensions: ['.js', '.vue'] 16 | }, 17 | devServer: { 18 | port: '8180', 19 | hot: true, 20 | stats: 'errors-only' 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.vue$/, 26 | loader: 'vue-loader' 27 | }, 28 | { 29 | test: /\.js$/, 30 | loader: 'babel-loader' 31 | }, 32 | { 33 | test: /\.css$/, 34 | use: ['style-loader', 'css-loader'] 35 | } 36 | ] 37 | }, 38 | plugins: [ 39 | new webpack.DefinePlugin({ 40 | 'process.env': { 41 | NODE_ENV: '"development"' 42 | } 43 | }), 44 | new webpack.HotModuleReplacementPlugin(), 45 | new HtmlWebpackPlugin({ 46 | filename: 'index.html', 47 | template: '../index.html', 48 | inject: true 49 | }) 50 | ] 51 | } 52 | --------------------------------------------------------------------------------