blob: 2eaec6617fe22f7b7d260c14aa61a6a82b34bec3 [file] [log] [blame]
/**
* echarts
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @desc echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表。
* @author Kener (@Kener-林峰, linzhifeng@baidu.com)
*
*/
define(function(require) {
var self = {};
self.init = function(dom, libOption) {
libOption = libOption || {type : 'canvas'};
if (libOption.type == 'canvas') {
return new Echarts(dom);
}
else if (libOption.type == 'flash') {
alert('未配置');
}
};
/**
* 基于zrender实现Echarts接口层
* @param {HtmlElement} dom 必要
* @param {Object} option 可选参数,同setOption
*/
function Echarts(dom, option) {
var ecConfig = require('./config');
var self = this;
var _zr;
var _option;
var _optionBackup;
var _chartList; // 图表实例
var _messageCenter; // Echarts层的消息中心,做zrender原始事件转换
var _status = { // 用于图表间通信
dragIn : false,
dragOut : false,
needRefresh : false
};
var _selectedMap;
var _island;
var _toolbox;
// 初始化::构造函数
_init();
function _init() {
var zrender = require('zrender');
_zr = zrender.init(dom);
var zrUtil = require('zrender/tool/util');
_option = zrUtil.clone(option || {});
_chartList = []; // 图表实例
_messageCenter = {}; // Echarts层的消息中心,做zrender原始事件转换
// 添加消息中心的事件分发器特性
var zrEvent = require('zrender/tool/event');
zrEvent.Dispatcher.call(_messageCenter);
_messageCenter.bind(
ecConfig.EVENT.LEGEND_SELECTED, _onlegendSelected
);
_messageCenter.bind(
ecConfig.EVENT.DATA_ZOOM, _ondataZoom
);
_messageCenter.bind(
ecConfig.EVENT.MAGIC_TYPE_CHANGED, _onmagicTypeChanged
);
_messageCenter.bind(
ecConfig.EVENT.DATA_VIEW_CHANGED, _ondataViewChanged
);
_messageCenter.bind(
ecConfig.EVENT.REFRESH, _onrefresh
);
var zrConfig = require('zrender/config');
_zr.on(zrConfig.EVENT.CLICK, _onclick);
_zr.on(zrConfig.EVENT.MOUSEOVER, _onhover);
_zr.on(zrConfig.EVENT.MOUSEWHEEL, _onmousewheel);
_zr.on(zrConfig.EVENT.DRAGSTART, _ondragstart);
_zr.on(zrConfig.EVENT.DRAGEND, _ondragend);
_zr.on(zrConfig.EVENT.DRAGENTER, _ondragenter);
_zr.on(zrConfig.EVENT.DRAGOVER, _ondragover);
_zr.on(zrConfig.EVENT.DRAGLEAVE, _ondragleave);
_zr.on(zrConfig.EVENT.DROP, _ondrop);
var shape = require('zrender/shape');
var Icon = require('./util/icon');
shape.define('icon', new Icon());
// 孤岛
var chartLibrary = require('./chart');
var Island = chartLibrary.get('island');
_island = new Island(_messageCenter, _zr);
// 工具箱
var componentLibrary = require('./component');
var Toolbox = componentLibrary.get('toolbox');
_toolbox = new Toolbox(_messageCenter, _zr, dom);
}
/**
* 点击事件,响应zrender事件,包装后分发到Echarts层
*/
function _onclick(param) {
var len = _chartList.length;
while (len--) {
if (_chartList[len].onclick) {
_chartList[len].onclick(param);
}
}
if (param.target) {
var ecData = _eventPackage(param.target);
if (ecData && typeof ecData.seriesIndex != 'undefined') {
_messageCenter.dispatch(
ecConfig.EVENT.CLICK,
param.event,
ecData
);
}
}
}
/**
* 悬浮事件,响应zrender事件,包装后分发到Echarts层
*/
function _onhover(param) {
if (param.target) {
var ecData = _eventPackage(param.target);
if (ecData && typeof ecData.seriesIndex != 'undefined') {
_messageCenter.dispatch(
ecConfig.EVENT.HOVER,
param.event,
ecData
);
}
}
}
/**
* 滚轮回调,孤岛可计算特性
*/
function _onmousewheel(param) {
_messageCenter.dispatch(
ecConfig.EVENT.MOUSEWHEEL,
param.event,
_eventPackage(param.target)
);
}
/**
* dragstart回调,可计算特性实现
*/
function _ondragstart(param) {
// 复位用于图表间通信拖拽标识
_status = {
dragIn : false,
dragOut : false,
needRefresh : false
};
var len = _chartList.length;
while (len--) {
if (_chartList[len].ondragstart) {
_chartList[len].ondragstart(param);
}
}
}
/**
* dragging回调,可计算特性实现
*/
function _ondragenter(param) {
var len = _chartList.length;
while (len--) {
if (_chartList[len].ondragenter) {
_chartList[len].ondragenter(param);
}
}
}
/**
* dragstart回调,可计算特性实现
*/
function _ondragover(param) {
var len = _chartList.length;
while (len--) {
if (_chartList[len].ondragover) {
_chartList[len].ondragover(param);
}
}
}
/**
* dragstart回调,可计算特性实现
*/
function _ondragleave(param) {
var len = _chartList.length;
while (len--) {
if (_chartList[len].ondragleave) {
_chartList[len].ondragleave(param);
}
}
}
/**
* dragstart回调,可计算特性实现
*/
function _ondrop(param) {
var len = _chartList.length;
while (len--) {
if (_chartList[len].ondrop) {
_chartList[len].ondrop(param, _status);
}
}
_island.ondrop(param, _status);
}
/**
* dragdone回调 ,可计算特性实现
*/
function _ondragend(param) {
var len = _chartList.length;
while (len--) {
if (_chartList[len].ondragend) {
_chartList[len].ondragend(param, _status);
}
}
_island.ondragend(param, _status);
// 发生过重计算
if (_status.needRefresh) {
_messageCenter.dispatch(
ecConfig.EVENT.DATA_CHANGED,
param.event,
_eventPackage(param.target)
);
// 先来后到,不能仅刷新自己,也不能在上一个循环中刷新,如坐标系数据改变会影响其他图表的大小
// 所以安顺序刷新各种图表,图表内部refresh优化无需更新则不更新~
for (var i = 0, l = _chartList.length; i < l; i++) {
_chartList[i].refresh && _chartList[i].refresh();
}
_zr.refresh();
}
}
function _onlegendSelected(param) {
// 用于图表间通信
_status.needRefresh = false;
for (var l = _chartList.length - 1; l >= 0; l--) {
if (_chartList[l].onlegendSelected) {
_chartList[l].onlegendSelected(param, _status);
}
}
_selectedMap = param.selected;
if (_status.needRefresh) {
for (var i = 0, l = _chartList.length; i < l; i++) {
_chartList[i].refresh && _chartList[i].refresh();
}
_zr.refresh();
}
}
function _ondataZoom(param) {
// 用于图表间通信
_status.needRefresh = false;
for (var l = _chartList.length - 1; l >= 0; l--) {
if (_chartList[l].ondataZoom) {
_chartList[l].ondataZoom(param, _status);
}
}
if (_status.needRefresh) {
for (var i = 0, l = _chartList.length; i < l; i++) {
_chartList[i].refresh && _chartList[i].refresh();
}
_zr.refresh();
}
}
function _onmagicTypeChanged() {
var magicOption = _toolbox.getMagicOption();
var len;
if (_optionBackup.xAxis) {
if (_optionBackup.xAxis instanceof Array) {
len = _optionBackup.xAxis.length;
while (len--) {
magicOption.xAxis[len].data =
_optionBackup.xAxis[len].data;
}
}
else {
magicOption.xAxis.data = _optionBackup.xAxis.data;
}
}
if (_optionBackup.yAxis) {
if (_optionBackup.yAxis instanceof Array) {
len = _optionBackup.yAxis.length;
while (len--) {
magicOption.yAxis[len].data =
_optionBackup.yAxis[len].data;
}
}
else {
magicOption.yAxis.data = _optionBackup.yAxis.data;
}
}
len = magicOption.series.length;
while (len--) {
magicOption.series[len].data = _optionBackup.series[len].data;
}
_render(magicOption);
}
function _ondataViewChanged() {
_messageCenter.dispatch(
ecConfig.EVENT.DATA_CHANGED
);
for (var i = 0, l = _chartList.length; i < l; i++) {
_chartList[i].refresh && _chartList[i].refresh();
}
_zr.refresh();
}
function _onrefresh() {
_refresh();
}
/**
* 打包Echarts层的事件附件
*/
function _eventPackage(target) {
if (target) {
var ecData = require('./util/ecData');
return {
seriesIndex : ecData.get(target, 'seriesIndex'),
dataIndex : ecData.get(target, 'dataIndex')
};
}
return;
}
function _render(magicOption) {
_disposeChartList();
_zr.clear();
var chartLibrary = require('./chart');
var componentLibrary = require('./component');
// 提示
var tooltip;
if (magicOption.tooltip) {
var Tooltip = componentLibrary.get('tooltip');
tooltip = new Tooltip(_messageCenter, _zr, magicOption, dom);
_chartList.push(tooltip);
}
// 图例
var legend;
if (magicOption.legend) {
var Legend = new componentLibrary.get('legend');
legend = new Legend(
_messageCenter, _zr, magicOption, _selectedMap
);
_chartList.push(legend);
}
var grid;
var xAxis;
var yAxis;
if (magicOption.grid || magicOption.xAxis || magicOption.yAxis) {
var Grid = componentLibrary.get('grid');
grid = new Grid(_messageCenter, _zr, magicOption);
_chartList.push(grid);
var DataZoom = componentLibrary.get('dataZoom');
_chartList.push(new DataZoom(
_messageCenter,
_zr,
magicOption,
{
'grid' : grid
}
));
var Axis = componentLibrary.get('axis');
xAxis = new Axis(
_messageCenter,
_zr,
magicOption,
{
'legend' : legend,
'grid' : grid
},
'xAxis'
);
_chartList.push(xAxis);
yAxis = new Axis(
_messageCenter,
_zr,
magicOption,
{
'legend' : legend,
'grid' : grid
},
'yAxis'
);
_chartList.push(yAxis);
tooltip && tooltip.setComponent({
'grid' : grid,
'xAxis' : xAxis,
'yAxis' : yAxis
});
}
var ChartClass;
var chartType;
var chart;
var chartMap = {}; // 记录已经初始化的图表
for (var i = 0, l = magicOption.series.length; i < l; i++) {
chartType = magicOption.series[i].type;
if (!chartType) {
continue;
}
if (!chartMap[chartType]) {
chartMap[chartType] = true;
ChartClass = chartLibrary.get(chartType);
if (ChartClass) {
chart = new ChartClass(
_messageCenter,
_zr,
magicOption,
{
'tooltip' : tooltip,
'legend' : legend,
'grid' : grid,
'xAxis' : xAxis,
'yAxis' : yAxis
}
);
_chartList.push(chart);
}
}
}
_island.render(magicOption);
_toolbox.render(magicOption);
if (magicOption.animation) {
var len = _chartList.length;
while (len--) {
_chartList[len].animation && _chartList[len].animation();
}
}
_zr.render();
}
function _refresh() {
var zrUtil = require('zrender/tool/util');
_selectedMap = {};
_option = zrUtil.clone(_optionBackup);
_island.clear();
_toolbox.resetMagicType(_option);
_render(_option);
}
/**
* 释放图表实例
*/
function _disposeChartList() {
var len = _chartList.length;
while (len--) {
_chartList[len].dispose && _chartList[len].dispose();
}
_chartList = [];
}
/**
* 万能接口,配置图表实例任何可配置选项,多次调用时option选项做merge处理
* @param {Object} option
* @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,
* 如果不需求,可以通过notMerger参数为true阻止与上次option的合并
*/
function setOption(option, notMerge) {
var zrUtil = require('zrender/tool/util');
if (!notMerge) {
zrUtil.merge(
_option,
zrUtil.clone(option),
{
'overwrite': true,
'recursive': true
}
);
}
else {
_option = zrUtil.clone(option);
}
if (!option.series || option.series.length === 0) {
return;
}
// 非图表全局属性merge~~
if (typeof _option.calculable == 'undefined') {
_option.calculable = ecConfig.calculable;
}
if (typeof _option.nameConnector == 'undefined') {
_option.nameConnector = ecConfig.nameConnector;
}
if (typeof _option.valueConnector == 'undefined') {
_option.valueConnector = ecConfig.valueConnector;
}
if (typeof _option.animation == 'undefined') {
_option.animation = ecConfig.animation;
}
if (typeof _option.animationDuration == 'undefined') {
_option.animationDuration = ecConfig.animationDuration;
}
if (typeof _option.animationEasing == 'undefined') {
_option.animationEasing = ecConfig.animationEasing;
}
var zrColor = require('zrender/tool/color');
// 数值系列的颜色列表,不传则采用内置颜色,可配数组
if (_option.color && _option.color.length > 0) {
_zr.getColor = function(idx) {
return zrColor.getColor(idx, _option.color);
};
}
else {
_zr.getColor = function(idx) {
return zrColor.getColor(idx, ecConfig.color);
};
}
// calculable可计算颜色提示
_zr.getCalculableColor = function () {
return _option.calculableColor || ecConfig.calculableColor;
};
_optionBackup = zrUtil.clone(_option);
_selectedMap = {};
_island.clear();
_toolbox.resetMagicType(_option);
_render(_option);
return self;
}
/**
* 数据设置快捷接口
* @param {Array} series
* @param {boolean=} notMerge 多次调用时option选项是默认是合并(merge)的,
* 如果不需求,可以通过notMerger参数为true阻止与上次option的合并。
*/
function setSeries(series, notMerge) {
if (!notMerge) {
self.setOption({series: series});
}
else {
_option.series = series;
self.setOption(_option, notMerge);
}
return self;
}
function getZrender() {
return _zr;
}
function on(eventName, eventListener) {
_messageCenter.bind(eventName, eventListener);
return self;
}
function un(eventName, eventListener) {
_messageCenter.unbind(eventName, eventListener);
return self;
}
function showLoading(loadingOption) {
_toolbox.hideDataView();
var zrUtil = require('zrender/tool/util');
loadingOption = loadingOption || {};
loadingOption.textStyle = loadingOption.textStyle || {};
var finalTextStyle = zrUtil.merge(
zrUtil.clone(loadingOption.textStyle),
ecConfig.textStyle,
{ 'overwrite': false}
);
loadingOption.textStyle.textFont = finalTextStyle.fontStyle + ' '
+ finalTextStyle.fontWeight + ' '
+ finalTextStyle.fontSize + 'px '
+ finalTextStyle.fontFamily;
loadingOption.textStyle.text = loadingOption.text || 'Loading...';
if (typeof loadingOption.x != 'undefined') {
loadingOption.textStyle.x = loadingOption.x;
}
if (typeof loadingOption.y != 'undefined') {
loadingOption.textStyle.y = loadingOption.y;
}
_zr.showLoading(loadingOption);
return self;
}
function hideLoading() {
_zr.hideLoading();
return self;
}
function resize() {
_zr.resize();
// 先来后到,不能仅刷新自己,也不能在上一个循环中刷新,如坐标系数据改变会影响其他图表的大小
// 所以安顺序刷新各种图表,图表内部refresh优化无需更新则不更新~
for (var i = 0, l = _chartList.length; i < l; i++) {
_chartList[i].refresh && _chartList[i].refresh();
}
_zr.refresh();
}
function clear() {
_zr.clear();
return self;
}
function dispose() {
_island.dispose();
_toolbox.dispose();
_disposeChartList();
_messageCenter.unbind();
_zr.dispose();
self = null;
return;
}
self.setOption = setOption;
self.setSeries = setSeries;
self.getZrender = getZrender;
self.on = on;
self.un = un;
self.showLoading = showLoading;
self.hideLoading = hideLoading;
self.resize = resize;
self.clear = clear;
self.dispose = dispose;
}
return self;
});