123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- /**
- * echarts图表类:事件河流图
- *
- * @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
- * @author clmtulip (车丽美, clmtulip@gmail.com)
- *
- */
- define(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: {
- // color: 各异,
- borderColor: 'rgba(0,0,0,0)',
- borderWidth: 1,
- label: {
- show: true,
- position: 'inside', // 可选为'left'|'right'|'top'|'bottom'
- formatter: '{b}'
- // textStyle: null // 默认使用全局文本样式,详见TEXTSTYLE
- }
- },
- emphasis: {
- // color: 各异,
- 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');
- /**
- * 构造函数
- * @param {Object} messageCenter echart消息中心
- * @param {ZRender} zr zrender实例
- * @param {Object} option 数据
- * @param {Object} component 组件
- */
- 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;
- // 调用布局算法计算事件在Y轴上的位置
- 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 = evolutionList[k].value;
- // modified by limei.che, to normalize the value range
- 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.0, value[i] / -2.0 + posY]);
- }
- // 最后一个矩形上半部分的中点
- pts.push([(time[i] + (time[i] + intervalX)) / 2.0, value[i] / -2.0 + posY]);
- // 最后一个矩形的右端点
- pts.push([time[i] + intervalX, posY]);
- // 从右向左绘制气泡的下半部分控制点
- // 最后一个矩形下半部分的中点
- pts.push([(time[i] + (time[i] + intervalX)) / 2.0, value[i] / 2.0 + posY]);
- // 从倒数第二个矩形 到 一个矩形 下半部分的中点,由于polygon是闭合的,故不需要再加入左端点
- for (i = n - 1; i > 0; i--) {
- pts.push([(time[i] + time[i - 1]) / 2.0, value[i - 1] / 2.0 + posY]);
- }
-
- return pts;
- },
-
- /**
- * 数据项被拖拽出去
- */
- ondragend : function (param, status) {
- if (!this.isDragend || !param.target) {
- // 没有在当前实例上发生拖拽行为则直接返回
- return;
- }
- // 别status = {}赋值啊!!
- status.dragOut = true;
- status.dragIn = true;
- status.needRefresh = false; // 会有消息触发fresh,不用再刷一遍
- // 处理完拖拽事件后复位
- 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;
- });
|