1+ define ( 'echarts/chart/eventRiver' , [
2+ 'require' ,
3+ '../component/base' ,
4+ './base' ,
5+ '../layout/eventRiver' ,
6+ 'zrender/shape/Polygon' ,
7+ '../component/axis' ,
8+ '../component/grid' ,
9+ '../component/dataZoom' ,
10+ '../config' ,
11+ '../util/ecData' ,
12+ '../util/date' ,
13+ 'zrender/tool/util' ,
14+ 'zrender/tool/color' ,
15+ '../chart'
16+ ] , function ( require ) {
17+ var ComponentBase = require ( '../component/base' ) ;
18+ var ChartBase = require ( './base' ) ;
19+ var eventRiverLayout = require ( '../layout/eventRiver' ) ;
20+ var PolygonShape = require ( 'zrender/shape/Polygon' ) ;
21+ require ( '../component/axis' ) ;
22+ require ( '../component/grid' ) ;
23+ require ( '../component/dataZoom' ) ;
24+ var ecConfig = require ( '../config' ) ;
25+ var ecData = require ( '../util/ecData' ) ;
26+ var ecDate = require ( '../util/date' ) ;
27+ var zrUtil = require ( 'zrender/tool/util' ) ;
28+ var zrColor = require ( 'zrender/tool/color' ) ;
29+ function EventRiver ( ecTheme , messageCenter , zr , option , myChart ) {
30+ ComponentBase . call ( this , ecTheme , messageCenter , zr , option , myChart ) ;
31+ ChartBase . call ( this ) ;
32+ var self = this ;
33+ self . _ondragend = function ( ) {
34+ self . isDragend = true ;
35+ } ;
36+ this . refresh ( option ) ;
37+ }
38+ EventRiver . prototype = {
39+ type : ecConfig . CHART_TYPE_EVENTRIVER ,
40+ _buildShape : function ( ) {
41+ var series = this . series ;
42+ this . selectedMap = { } ;
43+ this . _dataPreprocessing ( ) ;
44+ var legend = this . component . legend ;
45+ var eventRiverSeries = [ ] ;
46+ for ( var i = 0 ; i < series . length ; i ++ ) {
47+ if ( series [ i ] . type === this . type ) {
48+ series [ i ] = this . reformOption ( series [ i ] ) ;
49+ this . legendHoverLink = series [ i ] . legendHoverLink || this . legendHoverLink ;
50+ var serieName = series [ i ] . name || '' ;
51+ this . selectedMap [ serieName ] = legend ? legend . isSelected ( serieName ) : true ;
52+ if ( ! this . selectedMap [ serieName ] ) {
53+ continue ;
54+ }
55+ this . buildMark ( i ) ;
56+ eventRiverSeries . push ( this . series [ i ] ) ;
57+ }
58+ }
59+ eventRiverLayout ( eventRiverSeries , this . _intervalX , this . component . grid . getArea ( ) ) ;
60+ this . _drawEventRiver ( ) ;
61+ this . addShapeList ( ) ;
62+ } ,
63+ _dataPreprocessing : function ( ) {
64+ var series = this . series ;
65+ var xAxis ;
66+ var evolutionList ;
67+ for ( var i = 0 , iLen = series . length ; i < iLen ; i ++ ) {
68+ if ( series [ i ] . type === this . type ) {
69+ xAxis = this . component . xAxis . getAxis ( series [ i ] . xAxisIndex || 0 ) ;
70+ for ( var j = 0 , jLen = series [ i ] . eventList . length ; j < jLen ; j ++ ) {
71+ evolutionList = series [ i ] . eventList [ j ] . evolution ;
72+ for ( var k = 0 , kLen = evolutionList . length ; k < kLen ; k ++ ) {
73+ evolutionList [ k ] . timeScale = xAxis . getCoord ( ecDate . getNewDate ( evolutionList [ k ] . time ) - 0 ) ;
74+ evolutionList [ k ] . valueScale = Math . pow ( evolutionList [ k ] . value , 0.8 ) ;
75+ }
76+ }
77+ }
78+ }
79+ this . _intervalX = Math . round ( this . component . grid . getWidth ( ) / 40 ) ;
80+ } ,
81+ _drawEventRiver : function ( ) {
82+ var series = this . series ;
83+ for ( var i = 0 ; i < series . length ; i ++ ) {
84+ var serieName = series [ i ] . name || '' ;
85+ if ( series [ i ] . type === this . type && this . selectedMap [ serieName ] ) {
86+ for ( var j = 0 ; j < series [ i ] . eventList . length ; j ++ ) {
87+ this . _drawEventBubble ( series [ i ] . eventList [ j ] , i , j ) ;
88+ }
89+ }
90+ }
91+ } ,
92+ _drawEventBubble : function ( oneEvent , seriesIndex , dataIndex ) {
93+ var series = this . series ;
94+ var serie = series [ seriesIndex ] ;
95+ var serieName = serie . name || '' ;
96+ var data = serie . eventList [ dataIndex ] ;
97+ var queryTarget = [
98+ data ,
99+ serie
100+ ] ;
101+ var legend = this . component . legend ;
102+ var defaultColor = legend ? legend . getColor ( serieName ) : this . zr . getColor ( seriesIndex ) ;
103+ var normal = this . deepMerge ( queryTarget , 'itemStyle.normal' ) || { } ;
104+ var emphasis = this . deepMerge ( queryTarget , 'itemStyle.emphasis' ) || { } ;
105+ var normalColor = this . getItemStyleColor ( normal . color , seriesIndex , dataIndex , data ) || defaultColor ;
106+ var emphasisColor = this . getItemStyleColor ( emphasis . color , seriesIndex , dataIndex , data ) || ( typeof normalColor === 'string' ? zrColor . lift ( normalColor , - 0.2 ) : normalColor ) ;
107+ var pts = this . _calculateControlPoints ( oneEvent ) ;
108+ var eventBubbleShape = {
109+ zlevel : this . _zlevelBase ,
110+ clickable : this . deepQuery ( queryTarget , 'clickable' ) ,
111+ style : {
112+ pointList : pts ,
113+ smooth : 'spline' ,
114+ brushType : 'both' ,
115+ lineJoin : 'round' ,
116+ color : normalColor ,
117+ lineWidth : normal . borderWidth ,
118+ strokeColor : normal . borderColor
119+ } ,
120+ highlightStyle : {
121+ color : emphasisColor ,
122+ lineWidth : emphasis . borderWidth ,
123+ strokeColor : emphasis . borderColor
124+ } ,
125+ draggable : 'vertical' ,
126+ ondragend : this . _ondragend
127+ } ;
128+ eventBubbleShape = new PolygonShape ( eventBubbleShape ) ;
129+ this . addLabel ( eventBubbleShape , serie , data , oneEvent . name ) ;
130+ ecData . pack ( eventBubbleShape , series [ seriesIndex ] , seriesIndex , series [ seriesIndex ] . eventList [ dataIndex ] , dataIndex , series [ seriesIndex ] . eventList [ dataIndex ] . name ) ;
131+ this . shapeList . push ( eventBubbleShape ) ;
132+ } ,
133+ _calculateControlPoints : function ( oneEvent ) {
134+ var intervalX = this . _intervalX ;
135+ var posY = oneEvent . y ;
136+ var evolution = oneEvent . evolution ;
137+ var n = evolution . length ;
138+ if ( n < 1 ) {
139+ return ;
140+ }
141+ var time = [ ] ;
142+ var value = [ ] ;
143+ for ( var i = 0 ; i < n ; i ++ ) {
144+ time . push ( evolution [ i ] . timeScale ) ;
145+ value . push ( evolution [ i ] . valueScale ) ;
146+ }
147+ var pts = [ ] ;
148+ pts . push ( [
149+ time [ 0 ] ,
150+ posY
151+ ] ) ;
152+ var i = 0 ;
153+ for ( i = 0 ; i < n - 1 ; i ++ ) {
154+ pts . push ( [
155+ ( time [ i ] + time [ i + 1 ] ) / 2 ,
156+ value [ i ] / - 2 + posY
157+ ] ) ;
158+ }
159+ pts . push ( [
160+ ( time [ i ] + ( time [ i ] + intervalX ) ) / 2 ,
161+ value [ i ] / - 2 + posY
162+ ] ) ;
163+ pts . push ( [
164+ time [ i ] + intervalX ,
165+ posY
166+ ] ) ;
167+ pts . push ( [
168+ ( time [ i ] + ( time [ i ] + intervalX ) ) / 2 ,
169+ value [ i ] / 2 + posY
170+ ] ) ;
171+ for ( i = n - 1 ; i > 0 ; i -- ) {
172+ pts . push ( [
173+ ( time [ i ] + time [ i - 1 ] ) / 2 ,
174+ value [ i - 1 ] / 2 + posY
175+ ] ) ;
176+ }
177+ return pts ;
178+ } ,
179+ ondragend : function ( param , status ) {
180+ if ( ! this . isDragend || ! param . target ) {
181+ return ;
182+ }
183+ status . dragOut = true ;
184+ status . dragIn = true ;
185+ status . needRefresh = false ;
186+ this . isDragend = false ;
187+ } ,
188+ refresh : function ( newOption ) {
189+ if ( newOption ) {
190+ this . option = newOption ;
191+ this . series = newOption . series ;
192+ }
193+ this . backupShapeList ( ) ;
194+ this . _buildShape ( ) ;
195+ }
196+ } ;
197+ zrUtil . inherits ( EventRiver , ChartBase ) ;
198+ zrUtil . inherits ( EventRiver , ComponentBase ) ;
199+ require ( '../chart' ) . define ( 'eventRiver' , EventRiver ) ;
200+ return EventRiver ;
201+ } ) ; define ( 'echarts/layout/eventRiver' , [ 'require' ] , function ( require ) {
202+ function eventRiverLayout ( series , intervalX , area ) {
203+ var space = 5 ;
204+ var scale = intervalX ;
205+ function importanceSort ( a , b ) {
206+ var x = a . importance ;
207+ var y = b . importance ;
208+ return x > y ? - 1 : x < y ? 1 : 0 ;
209+ }
210+ function indexOf ( array , value ) {
211+ if ( array . indexOf ) {
212+ return array . indexOf ( value ) ;
213+ }
214+ for ( var i = 0 , len = array . length ; i < len ; i ++ ) {
215+ if ( array [ i ] === value ) {
216+ return i ;
217+ }
218+ }
219+ return - 1 ;
220+ }
221+ for ( var i = 0 ; i < series . length ; i ++ ) {
222+ for ( var j = 0 ; j < series [ i ] . eventList . length ; j ++ ) {
223+ if ( series [ i ] . eventList [ j ] . weight == null ) {
224+ series [ i ] . eventList [ j ] . weight = 1 ;
225+ }
226+ var importance = 0 ;
227+ for ( var k = 0 ; k < series [ i ] . eventList [ j ] . evolution . length ; k ++ ) {
228+ importance += series [ i ] . eventList [ j ] . evolution [ k ] . valueScale ;
229+ }
230+ series [ i ] . eventList [ j ] . importance = importance * series [ i ] . eventList [ j ] . weight ;
231+ }
232+ series [ i ] . eventList . sort ( importanceSort ) ;
233+ }
234+ for ( var i = 0 ; i < series . length ; i ++ ) {
235+ if ( series [ i ] . weight == null ) {
236+ series [ i ] . weight = 1 ;
237+ }
238+ var importance = 0 ;
239+ for ( var j = 0 ; j < series [ i ] . eventList . length ; j ++ ) {
240+ importance += series [ i ] . eventList [ j ] . weight ;
241+ }
242+ series [ i ] . importance = importance * series [ i ] . weight ;
243+ }
244+ series . sort ( importanceSort ) ;
245+ var minTime = Number . MAX_VALUE ;
246+ var maxTime = 0 ;
247+ for ( var i = 0 ; i < series . length ; i ++ ) {
248+ for ( var j = 0 ; j < series [ i ] . eventList . length ; j ++ ) {
249+ for ( var k = 0 ; k < series [ i ] . eventList [ j ] . evolution . length ; k ++ ) {
250+ var time = series [ i ] . eventList [ j ] . evolution [ k ] . timeScale ;
251+ minTime = Math . min ( minTime , time ) ;
252+ maxTime = Math . max ( maxTime , time ) ;
253+ }
254+ }
255+ }
256+ var root = segmentTreeBuild ( Math . floor ( minTime ) , Math . ceil ( maxTime ) ) ;
257+ var totalMaxY = 0 ;
258+ for ( var i = 0 ; i < series . length ; i ++ ) {
259+ for ( var j = 0 ; j < series [ i ] . eventList . length ; j ++ ) {
260+ var e = series [ i ] . eventList [ j ] ;
261+ e . time = [ ] ;
262+ e . value = [ ] ;
263+ for ( var k = 0 ; k < series [ i ] . eventList [ j ] . evolution . length ; k ++ ) {
264+ e . time . push ( series [ i ] . eventList [ j ] . evolution [ k ] . timeScale ) ;
265+ e . value . push ( series [ i ] . eventList [ j ] . evolution [ k ] . valueScale ) ;
266+ }
267+ var mxIndex = indexOf ( e . value , Math . max . apply ( Math , e . value ) ) ;
268+ var maxY = segmentTreeQuery ( root , e . time [ mxIndex ] , e . time [ mxIndex + 1 ] ) ;
269+ var k = 0 ;
270+ e . y = maxY + e . value [ mxIndex ] / 2 + space ;
271+ for ( k = 0 ; k < e . time . length - 1 ; k ++ ) {
272+ var curMaxY = segmentTreeQuery ( root , e . time [ k ] , e . time [ k + 1 ] ) ;
273+ if ( e . y - e . value [ k ] / 2 - space < curMaxY ) {
274+ e . y = curMaxY + e . value [ k ] / 2 + space ;
275+ }
276+ }
277+ var curMaxY = segmentTreeQuery ( root , e . time [ k ] , e . time [ k ] + scale ) ;
278+ if ( e . y - e . value [ k ] / 2 - space < curMaxY ) {
279+ e . y = curMaxY + e . value [ k ] / 2 + space ;
280+ }
281+ series [ i ] . y = e . y ;
282+ totalMaxY = Math . max ( totalMaxY , e . y + e . value [ mxIndex ] / 2 ) ;
283+ for ( k = 0 ; k < e . time . length - 1 ; k ++ ) {
284+ segmentTreeInsert ( root , e . time [ k ] , e . time [ k + 1 ] , e . y + e . value [ k ] / 2 ) ;
285+ }
286+ segmentTreeInsert ( root , e . time [ k ] , e . time [ k ] + scale , e . y + e . value [ k ] / 2 ) ;
287+ }
288+ }
289+ scaleY ( series , area , totalMaxY , space ) ;
290+ }
291+ function scaleY ( series , area , maxY , space ) {
292+ var yBase = area . y ;
293+ var yScale = ( area . height - space ) / maxY ;
294+ for ( var i = 0 ; i < series . length ; i ++ ) {
295+ series [ i ] . y = series [ i ] . y * yScale + yBase ;
296+ var eventList = series [ i ] . eventList ;
297+ for ( var j = 0 ; j < eventList . length ; j ++ ) {
298+ eventList [ j ] . y = eventList [ j ] . y * yScale + yBase ;
299+ var evolutionList = eventList [ j ] . evolution ;
300+ for ( var k = 0 ; k < evolutionList . length ; k ++ ) {
301+ evolutionList [ k ] . valueScale *= yScale * 1 ;
302+ }
303+ }
304+ }
305+ }
306+ function segmentTreeBuild ( left , right ) {
307+ var root = {
308+ 'left' : left ,
309+ 'right' : right ,
310+ 'leftChild' : null ,
311+ 'rightChild' : null ,
312+ 'maxValue' : 0
313+ } ;
314+ if ( left + 1 < right ) {
315+ var mid = Math . round ( ( left + right ) / 2 ) ;
316+ root . leftChild = segmentTreeBuild ( left , mid ) ;
317+ root . rightChild = segmentTreeBuild ( mid , right ) ;
318+ }
319+ return root ;
320+ }
321+ function segmentTreeQuery ( root , left , right ) {
322+ if ( right - left < 1 ) {
323+ return 0 ;
324+ }
325+ var mid = Math . round ( ( root . left + root . right ) / 2 ) ;
326+ var result = 0 ;
327+ if ( left == root . left && right == root . right ) {
328+ result = root . maxValue ;
329+ } else if ( right <= mid && root . leftChild != null ) {
330+ result = segmentTreeQuery ( root . leftChild , left , right ) ;
331+ } else if ( left >= mid && root . rightChild != null ) {
332+ result = segmentTreeQuery ( root . rightChild , left , right ) ;
333+ } else {
334+ var leftValue = 0 ;
335+ var rightValue = 0 ;
336+ if ( root . leftChild != null ) {
337+ leftValue = segmentTreeQuery ( root . leftChild , left , mid ) ;
338+ }
339+ if ( root . rightChild != null ) {
340+ rightValue = segmentTreeQuery ( root . rightChild , mid , right ) ;
341+ }
342+ result = leftValue > rightValue ? leftValue : rightValue ;
343+ }
344+ return result ;
345+ }
346+ function segmentTreeInsert ( root , left , right , value ) {
347+ if ( root == null ) {
348+ return ;
349+ }
350+ var mid = Math . round ( ( root . left + root . right ) / 2 ) ;
351+ root . maxValue = root . maxValue > value ? root . maxValue : value ;
352+ if ( Math . floor ( left * 10 ) == Math . floor ( root . left * 10 ) && Math . floor ( right * 10 ) == Math . floor ( root . right * 10 ) ) {
353+ return ;
354+ } else if ( right <= mid ) {
355+ segmentTreeInsert ( root . leftChild , left , right , value ) ;
356+ } else if ( left >= mid ) {
357+ segmentTreeInsert ( root . rightChild , left , right , value ) ;
358+ } else {
359+ segmentTreeInsert ( root . leftChild , left , mid , value ) ;
360+ segmentTreeInsert ( root . rightChild , mid , right , value ) ;
361+ }
362+ }
363+ return eventRiverLayout ;
364+ } ) ;
0 commit comments