define('echarts/chart/eventRiver', [ 'require', './base', '../layout/eventRiver', 'zrender/shape/Polygon', '../component/axis', '../component/grid', '../component/dataZoom', '../config', '../util/ecData', '../util/date', 'zrender/tool/util', 'zrender/tool/color', '../chart' ], function (require) { var ChartBase = require('./base'); var eventRiverLayout = require('../layout/eventRiver'); var PolygonShape = require('zrender/shape/Polygon'); require('../component/axis'); require('../component/grid'); require('../component/dataZoom'); var ecConfig = require('../config'); ecConfig.eventRiver = { zlevel: 0, z: 2, clickable: true, legendHoverLink: true, itemStyle: { normal: { borderColor: 'rgba(0,0,0,0)', borderWidth: 1, label: { show: true, position: 'inside', formatter: '{b}' } }, emphasis: { borderColor: 'rgba(0,0,0,0)', borderWidth: 1, label: { show: true } } } }; var ecData = require('../util/ecData'); var ecDate = require('../util/date'); var zrUtil = require('zrender/tool/util'); var zrColor = require('zrender/tool/color'); function EventRiver(ecTheme, messageCenter, zr, option, myChart) { ChartBase.call(this, ecTheme, messageCenter, zr, option, myChart); var self = this; self._ondragend = function () { self.isDragend = true; }; this.refresh(option); } EventRiver.prototype = { type: ecConfig.CHART_TYPE_EVENTRIVER, _buildShape: function () { var series = this.series; this.selectedMap = {}; this._dataPreprocessing(); var legend = this.component.legend; var eventRiverSeries = []; for (var i = 0; i < series.length; i++) { if (series[i].type === this.type) { series[i] = this.reformOption(series[i]); this.legendHoverLink = series[i].legendHoverLink || this.legendHoverLink; var serieName = series[i].name || ''; this.selectedMap[serieName] = legend ? legend.isSelected(serieName) : true; if (!this.selectedMap[serieName]) { continue; } this.buildMark(i); eventRiverSeries.push(this.series[i]); } } eventRiverLayout(eventRiverSeries, this._intervalX, this.component.grid.getArea()); this._drawEventRiver(); this.addShapeList(); }, _dataPreprocessing: function () { var series = this.series; var xAxis; var evolutionList; for (var i = 0, iLen = series.length; i < iLen; i++) { if (series[i].type === this.type) { xAxis = this.component.xAxis.getAxis(series[i].xAxisIndex || 0); for (var j = 0, jLen = series[i].data.length; j < jLen; j++) { evolutionList = series[i].data[j].evolution; for (var k = 0, kLen = evolutionList.length; k < kLen; k++) { evolutionList[k].timeScale = xAxis.getCoord(ecDate.getNewDate(evolutionList[k].time) - 0); evolutionList[k].valueScale = Math.pow(evolutionList[k].value, 0.8); } } } } this._intervalX = Math.round(this.component.grid.getWidth() / 40); }, _drawEventRiver: function () { var series = this.series; for (var i = 0; i < series.length; i++) { var serieName = series[i].name || ''; if (series[i].type === this.type && this.selectedMap[serieName]) { for (var j = 0; j < series[i].data.length; j++) { this._drawEventBubble(series[i].data[j], i, j); } } } }, _drawEventBubble: function (oneEvent, seriesIndex, dataIndex) { var series = this.series; var serie = series[seriesIndex]; var serieName = serie.name || ''; var data = serie.data[dataIndex]; var queryTarget = [ data, serie ]; var legend = this.component.legend; var defaultColor = legend ? legend.getColor(serieName) : this.zr.getColor(seriesIndex); var normal = this.deepMerge(queryTarget, 'itemStyle.normal') || {}; var emphasis = this.deepMerge(queryTarget, 'itemStyle.emphasis') || {}; var normalColor = this.getItemStyleColor(normal.color, seriesIndex, dataIndex, data) || defaultColor; var emphasisColor = this.getItemStyleColor(emphasis.color, seriesIndex, dataIndex, data) || (typeof normalColor === 'string' ? zrColor.lift(normalColor, -0.2) : normalColor); var pts = this._calculateControlPoints(oneEvent); var eventBubbleShape = { zlevel: serie.zlevel, z: serie.z, clickable: this.deepQuery(queryTarget, 'clickable'), style: { pointList: pts, smooth: 'spline', brushType: 'both', lineJoin: 'round', color: normalColor, lineWidth: normal.borderWidth, strokeColor: normal.borderColor }, highlightStyle: { color: emphasisColor, lineWidth: emphasis.borderWidth, strokeColor: emphasis.borderColor }, draggable: 'vertical', ondragend: this._ondragend }; eventBubbleShape = new PolygonShape(eventBubbleShape); this.addLabel(eventBubbleShape, serie, data, oneEvent.name); ecData.pack(eventBubbleShape, series[seriesIndex], seriesIndex, series[seriesIndex].data[dataIndex], dataIndex, series[seriesIndex].data[dataIndex].name); this.shapeList.push(eventBubbleShape); }, _calculateControlPoints: function (oneEvent) { var intervalX = this._intervalX; var posY = oneEvent.y; var evolution = oneEvent.evolution; var n = evolution.length; if (n < 1) { return; } var time = []; var value = []; for (var i = 0; i < n; i++) { time.push(evolution[i].timeScale); value.push(evolution[i].valueScale); } var pts = []; pts.push([ time[0], posY ]); var i = 0; for (i = 0; i < n - 1; i++) { pts.push([ (time[i] + time[i + 1]) / 2, value[i] / -2 + posY ]); } pts.push([ (time[i] + (time[i] + intervalX)) / 2, value[i] / -2 + posY ]); pts.push([ time[i] + intervalX, posY ]); pts.push([ (time[i] + (time[i] + intervalX)) / 2, value[i] / 2 + posY ]); for (i = n - 1; i > 0; i--) { pts.push([ (time[i] + time[i - 1]) / 2, value[i - 1] / 2 + posY ]); } return pts; }, ondragend: function (param, status) { if (!this.isDragend || !param.target) { return; } status.dragOut = true; status.dragIn = true; status.needRefresh = false; this.isDragend = false; }, refresh: function (newOption) { if (newOption) { this.option = newOption; this.series = newOption.series; } this.backupShapeList(); this._buildShape(); } }; zrUtil.inherits(EventRiver, ChartBase); require('../chart').define('eventRiver', EventRiver); return EventRiver; });define('echarts/layout/eventRiver', ['require'], function (require) { function eventRiverLayout(series, intervalX, area) { var space = 4; var scale = intervalX; function importanceSort(a, b) { var x = a.importance; var y = b.importance; return x > y ? -1 : x < y ? 1 : 0; } function indexOf(array, value) { if (array.indexOf) { return array.indexOf(value); } for (var i = 0, len = array.length; i < len; i++) { if (array[i] === value) { return i; } } return -1; } for (var i = 0; i < series.length; i++) { for (var j = 0; j < series[i].data.length; j++) { if (series[i].data[j].weight == null) { series[i].data[j].weight = 1; } var importance = 0; for (var k = 0; k < series[i].data[j].evolution.length; k++) { importance += series[i].data[j].evolution[k].valueScale; } series[i].data[j].importance = importance * series[i].data[j].weight; } series[i].data.sort(importanceSort); } for (var i = 0; i < series.length; i++) { if (series[i].weight == null) { series[i].weight = 1; } var importance = 0; for (var j = 0; j < series[i].data.length; j++) { importance += series[i].data[j].weight; } series[i].importance = importance * series[i].weight; } series.sort(importanceSort); var minTime = Number.MAX_VALUE; var maxTime = 0; for (var i = 0; i < series.length; i++) { for (var j = 0; j < series[i].data.length; j++) { for (var k = 0; k < series[i].data[j].evolution.length; k++) { var time = series[i].data[j].evolution[k].timeScale; minTime = Math.min(minTime, time); maxTime = Math.max(maxTime, time); } } } minTime = ~~minTime; maxTime = ~~maxTime; var flagForOffset = function () { var length = maxTime - minTime + 1 + ~~intervalX; if (length <= 0) { return [0]; } var result = []; while (length--) { result.push(0); } return result; }(); var flagForPos = flagForOffset.slice(0); var bubbleData = []; var totalMaxy = 0; var totalOffset = 0; for (var i = 0; i < series.length; i++) { for (var j = 0; j < series[i].data.length; j++) { var e = series[i].data[j]; e.time = []; e.value = []; var tmp; var maxy = 0; for (var k = 0; k < series[i].data[j].evolution.length; k++) { tmp = series[i].data[j].evolution[k]; e.time.push(tmp.timeScale); e.value.push(tmp.valueScale); maxy = Math.max(maxy, tmp.valueScale); } bubbleBound(e, intervalX, minTime); e.y = findLocation(flagForPos, e, function (e, index) { return e.ypx[index]; }); e._offset = findLocation(flagForOffset, e, function () { return space; }); totalMaxy = Math.max(totalMaxy, e.y + maxy); totalOffset = Math.max(totalOffset, e._offset); bubbleData.push(e); } } scaleY(bubbleData, area, totalMaxy, totalOffset); } function scaleY(bubbleData, area, maxY, offset) { var height = area.height; var offsetScale = offset / height > 0.5 ? 0.5 : 1; var yBase = area.y; var yScale = (area.height - offset) / maxY; for (var i = 0, length = bubbleData.length; i < length; i++) { var e = bubbleData[i]; e.y = yBase + yScale * e.y + e._offset * offsetScale; delete e.time; delete e.value; delete e.xpx; delete e.ypx; delete e._offset; var evolutionList = e.evolution; for (var k = 0, klen = evolutionList.length; k < klen; k++) { evolutionList[k].valueScale *= yScale; } } } function line(x0, y0, x1, y1) { if (x0 === x1) { throw new Error('x0 is equal with x1!!!'); } if (y0 === y1) { return function () { return y0; }; } var k = (y0 - y1) / (x0 - x1); var b = (y1 * x0 - y0 * x1) / (x0 - x1); return function (x) { return k * x + b; }; } function bubbleBound(e, intervalX, minX) { var space = ~~intervalX; var length = e.time.length; e.xpx = []; e.ypx = []; var i = 0; var x0 = 0; var x1 = 0; var y0 = 0; var y1 = 0; var newline; for (; i < length; i++) { x0 = ~~e.time[i]; y0 = e.value[i] / 2; if (i === length - 1) { x1 = x0 + space; y1 = 0; } else { x1 = ~~e.time[i + 1]; y1 = e.value[i + 1] / 2; } newline = line(x0, y0, x1, y1); for (var x = x0; x < x1; x++) { e.xpx.push(x - minX); e.ypx.push(newline(x)); } } e.xpx.push(x1 - minX); e.ypx.push(y1); } function findLocation(flags, e, yvalue) { var pos = 0; var length = e.xpx.length; var i = 0; var y; for (; i < length; i++) { y = yvalue(e, i); pos = Math.max(pos, y + flags[e.xpx[i]]); } for (i = 0; i < length; i++) { y = yvalue(e, i); flags[e.xpx[i]] = pos + y; } return pos; } return eventRiverLayout; });