├── timeline-map.png
├── public
├── echarts_timelinemap.html
├── timeline_map.js
├── echarts_timelinemap_editor.html
├── timeline_map.less
├── echarts_timelinemap.js
└── echarts_timelinemap_controller.js
├── index.js
├── package.json
└── README.md
/timeline-map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hivefans/timeline_map/HEAD/timeline-map.png
--------------------------------------------------------------------------------
/public/echarts_timelinemap.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | export default function (kibana) {
2 | return new kibana.Plugin({
3 | uiExports: {
4 | visTypes: ['plugins/timeline_map/timeline_map']
5 | }
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/public/timeline_map.js:
--------------------------------------------------------------------------------
1 | import visTypes from 'ui/registry/vis_types';
2 | define(function (require) {
3 | visTypes.register(require('plugins/timeline_map/echarts_timelinemap'));
4 | });
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "timeline_map",
3 | "version": "0.1.01",
4 | "kibana": {
5 | "version": "5.2.0"
6 | },
7 | "dependencies": {
8 | "echarts": "3.4.0"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/public/echarts_timelinemap_editor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/public/timeline_map.less:
--------------------------------------------------------------------------------
1 | @import (reference) "~ui/styles/mixins.less";
2 |
3 | .echart-vis {
4 | width: 100%;
5 | display: flex;
6 | flex-direction: row;
7 | flex-wrap: wrap;
8 | justify-content: space-around;
9 | align-items: center;
10 | align-content: space-around;
11 |
12 | .echart-container {
13 | text-align: center;
14 | padding: 1em;
15 | width:100%;
16 | position:relative;
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # timeline_map
2 | Kibana的Echarts 时间轴趋势地图插件
3 | 可以支持省份字段中英文,只支持手动选择日期,自动播放问题待解决。
4 |
5 | 
6 | ## 基于:
7 |
8 | Kibana 5.2.0
9 |
10 | Echarts 3.4
11 |
12 | ## 安装方法:
13 | ``` bash
14 | cd node/bin
15 | mv npm npm.bak
16 | ln -s ../lib/node_modules/npm/bin/npm-cli.js npm
17 | cd ../..
18 | vim package.json
19 | 在engines配置上面增加echarts
20 | "dependencies": {
21 | "echarts": "3.4.0"
22 | },
23 | "engines": {
24 | "node": "6.9.0"
25 | }
26 | node/bin/npm update
27 | bin/kibana-plugin install https://github.com/hivefans/timeline_map/files/1030552/timeline_map.1.0.1.zip
28 | ```
29 |
--------------------------------------------------------------------------------
/public/echarts_timelinemap.js:
--------------------------------------------------------------------------------
1 | import 'plugins/timeline_map/timeline_map.less';
2 | import 'plugins/timeline_map/echarts_timelinemap_controller';
3 | import TemplateVisTypeTemplateVisTypeProvider from 'ui/template_vis_type/template_vis_type';
4 | import VisSchemasProvider from 'ui/vis/schemas';
5 | import echartsTimelineMapTemplate from 'plugins/timeline_map/echarts_timelinemap.html';
6 | import echartsTimelineMapParamsTemplate from 'plugins/timeline_map/echarts_timelinemap_editor.html';
7 |
8 |
9 | // require('ui/registry/vis_types').register(echartsPieProvider);
10 |
11 | function echartsTimelineMapProvider(Private) {
12 | const TemplateVisType = Private(TemplateVisTypeTemplateVisTypeProvider);
13 | const Schemas = Private(VisSchemasProvider);
14 | // we also need to load the controller and used by the template
15 | // require('plugins/kibana-plugin-echarts/echartsPieController');
16 |
17 | return new TemplateVisType({
18 | name: 'timeline_map',
19 | title: 'Echarts timeline Map',
20 | icon: 'fa-map-marker',
21 | description: '数据统计中国地图时间轴趋势',
22 | template: echartsTimelineMapTemplate,
23 | params: {
24 | defaults: {
25 | shareYAxis: true,
26 | addTooltip: true,
27 | addLegend: true,
28 | isDonut: false
29 | },
30 | editor: echartsTimelineMapParamsTemplate
31 | },
32 | legendPositions: [{
33 | value: 'left',
34 | text: 'left',
35 | }, {
36 | value: 'right',
37 | text: 'right',
38 | }, {
39 | value: 'top',
40 | text: 'top',
41 | }, {
42 | value: 'bottom',
43 | text: 'bottom',
44 | }],
45 | responseConverter: false,
46 | hierarchicalData: true,
47 | schemas: new Schemas([{
48 | group: 'metrics',
49 | name: 'metric',
50 | title: 'Y-Axis',
51 | min: 1,
52 | max: 1,
53 | aggFilter: '!geohash_grid',
54 | defaults: [{
55 | schema: 'metric',
56 | type: 'count',
57 | }]
58 | }, {
59 | group: 'buckets',
60 | name: 'segment',
61 | icon: 'fa fa-scissors',
62 | title: 'X-Axis',
63 | min: 1,
64 | max: 1,
65 | aggFilter: '!geohash_grid'
66 | },
67 | {
68 | group: 'buckets',
69 | name: 'group',
70 | title: 'Split Area',
71 | min: 0,
72 | max: 1,
73 | aggFilter: '!geohash_grid'
74 | }])
75 | });
76 | };
77 |
78 | export default echartsTimelineMapProvider;
79 |
--------------------------------------------------------------------------------
/public/echarts_timelinemap_controller.js:
--------------------------------------------------------------------------------
1 | import echarts from 'echarts/lib/echarts';
2 | import 'echarts/lib/chart/map';
3 | import 'echarts/map/js/china';
4 | // import 'public_function';
5 |
6 | var module = require('ui/modules').get('timeline_map');
7 |
8 | module.controller('EchartsTimelineMapController', function ($scope, $element, $rootScope, Private, Notifier) {
9 | var tabifyAggResponse = Private(require('ui/agg_response/tabify/tabify'));
10 | var notify = new Notifier({ location: 'timeline_map/EchartsTimelineMapController'});
11 | let mychart = echarts.init($element.get(0));
12 | let rootElement = $element;
13 | let margin = {
14 | top: 10,
15 | right: 10,
16 | bottom: 10,
17 | left: 10
18 | };
19 | let width;
20 | let height;
21 | //state.query
22 | var provinces = [
23 | { name: "anhui", value: "安徽" },
24 | { name: "beijing", value: "北京" },
25 | { name: "fujian", value: "福建" },
26 | { name: "gansu", value: "甘肃" },
27 | { name: "guangdong", value: "广东" },
28 | { name: "guangxi", value: "广西" },
29 | { name: "guizhou", value: "贵州" },
30 | { name: "hainan", value: "海南" },
31 | { name: "hebei", value: "河北" },
32 | { name: "henan", value: "河南" },
33 | { name: "hubei", value: "湖北" },
34 | { name: "hunan", value: "湖南" },
35 | { name: "jilin", value: "吉林" },
36 | { name: "jiangsu", value: "江苏" },
37 | { name: "jiangxi", value: "江西" },
38 | { name: "liaoning", value: "辽宁" },
39 | { name: "ningxia", value: "宁夏" },
40 | { name: "qinghai", value: "青海" },
41 | { name: "shandong", value: "山东" },
42 | { name: "sanxi", value: "山西" },
43 | { name: "shanxi", value: "陕西" },
44 | { name: "shanghai", value: "上海" },
45 | { name: "sichuan", value: "四川" },
46 | { name: "tianjin", value: "天津" },
47 | { name: "xizang", value: "西藏" },
48 | { name: "xinjiang", value: "新疆" },
49 | { name: "yunnan", value: "云南" },
50 | { name: "zhejiang", value: "浙江" },
51 | { name: "chongqing", value: "重庆" },
52 | { name: "aomen", value: "澳门" },
53 | { name: "xianggang", value: "香港" },
54 | { name: "taiwan", value: "台湾" },
55 | { name: "heilongjiang", value: "黑龙江" },
56 | { name: "neimenggu", value: "内蒙古" }
57 | ]
58 |
59 | // 转化省份到汉字
60 | var convertProvince = function (data) {
61 | for (var i = 0; i < provinces.length; i++) {
62 | if (provinces[i].name == data) {
63 | return provinces[i].value;
64 | }
65 | }
66 | // console.log(data)
67 | return "other";
68 | }
69 |
70 | var getdateformat = function (timestamp){
71 | var date = new Date(timestamp);
72 | var Y = date.getFullYear() + '-';
73 | var M = (date.getMonth()+1 < 10 ? '0'+(date.getMonth()+1) : date.getMonth()+1) + '-';
74 | var D = (date.getDate() < 10 ? '0'+(date.getDate()) : date.getDate()) + ' ';
75 | var h = (date.getHours() < 10 ? '0'+(date.getHours()) : date.getHours()) + ':';
76 | var m = (date.getMinutes() < 10 ? '0'+(date.getMinutes()) : date.getMinutes());
77 | return Y+M+D+h+m;
78 | }
79 |
80 |
81 | var all={};
82 | var avgArr=[];
83 | var tableGroups;
84 | $scope.$watch('esResponse', function(resp) {
85 | if (!resp) {
86 | return;
87 | }
88 | tableGroups = tabifyAggResponse($scope.vis, resp);
89 | tableGroups.tables.forEach(function (table,index) {
90 | var cols = table.columns;
91 | var prov_len=0;
92 | var j=0;
93 | all.dates=[];
94 | all.options=[];
95 | avgArr = [];
96 | prov_len=cols[2].aggConfig.params.size;
97 | table.rows.forEach(function (row,i) {
98 | var datestr = row[0];
99 | var region_name = "";
100 | region_name = row[2].toString();
101 | var avg_speed = 0;
102 | avg_speed = row[3];
103 | avg_speed=avg_speed.toFixed(2);
104 |
105 | if(all.dates.indexOf(getdateformat(datestr))===-1){
106 | all.dates.push(getdateformat(datestr));
107 | all.options.push(
108 | {
109 | "series":[{
110 | "data":[]
111 | }]
112 | }
113 | );
114 | j=j+1;
115 | }
116 |
117 | avgArr.push(avg_speed);
118 | if(escape(region_name).indexOf("%u")<0) {
119 | region_name = convertProvince(region_name);
120 | }
121 | all.options[j-1].series[0].data.push(
122 | {
123 | name:region_name,
124 | value:avg_speed
125 | }
126 | )
127 | });
128 | });
129 |
130 | var option={};
131 | option = {
132 | baseOption: {
133 | timeline: {
134 | axisType: 'category',
135 | orient: 'vertical',
136 | autoPlay: true,
137 | inverse: true,
138 | playInterval: 5000,
139 | left: 10,
140 | right: null,
141 | top: 20,
142 | bottom: 20,
143 | width: 120,
144 | height: null,
145 | label: {
146 | emphasis: {
147 | textStyle: {
148 | color: '#fff'
149 | },
150 | "show":true
151 | },
152 | normal: {
153 | "show": true
154 | }
155 | },
156 | symbol: 'none',
157 | lineStyle: {
158 | color: '#555'
159 | },
160 | checkpointStyle: {
161 | color: '#bbb',
162 | borderColor: '#777',
163 | borderWidth: 2
164 | },
165 | controlStyle: {
166 | showNextBtn: true,
167 | showPrevBtn: true,
168 | normal: {
169 | color: '#666',
170 | borderColor: '#666'
171 | },
172 | emphasis: {
173 | color: '#aaa',
174 | borderColor: '#aaa'
175 | }
176 | },
177 | data: all.dates
178 | },
179 | tooltip: {
180 | },
181 | series: [{
182 | type: 'map',
183 | name: '数据统计',
184 | map: 'china',
185 | roam: false,
186 | label: {
187 | "emphasis": {
188 | "show": true
189 | },
190 | "normal": {
191 | "show": true
192 | }
193 | }
194 | }],
195 | animationDurationUpdate: 1000,
196 | animationEasingUpdate: 'quinticInOut',
197 | visualMap: {
198 | min:0,
199 | max: 500,
200 | left: 'right',
201 | top: 'bottom',
202 | text: ['高','低'],
203 | calculable: true,
204 | inRange: {
205 | color: ['#0ba800','#eac736','#d94e5d']
206 | }
207 | }
208 | },
209 | options: all.options
210 | };
211 |
212 | mychart.clear();
213 | option.baseOption.visualMap.max=Math.max.apply(Math, avgArr);
214 | mychart.setOption(option,true);
215 | width = $(rootElement).width() - margin.left - margin.right;
216 | height = $(rootElement).height() - margin.top - margin.bottom;
217 | mychart.resize({
218 | option,
219 | width,
220 | height
221 | });
222 | return notify.timed('Echarts Map Controller', resp);
223 | });
224 |
225 | // Automatic resizing of graphics
226 | $scope.$watch(
227 | function () {
228 | width = $(rootElement).width() - margin.left - margin.right;
229 | height = $(rootElement).height() - margin.top - margin.bottom;
230 | mychart.resize({
231 | width,
232 | height
233 | });
234 | },
235 | true
236 | );
237 | });
238 |
239 |
--------------------------------------------------------------------------------