mirror of
https://gitlab.com/JKANetwork/CheckServer.git
synced 2026-04-04 17:52:01 +02:00
Start again
This commit is contained in:
180
vendors/echarts/src/model/Component.js
vendored
Normal file
180
vendors/echarts/src/model/Component.js
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Component model
|
||||
*
|
||||
* @module echarts/model/Component
|
||||
*/
|
||||
define(function(require) {
|
||||
|
||||
var Model = require('./Model');
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var arrayPush = Array.prototype.push;
|
||||
var componentUtil = require('../util/component');
|
||||
var clazzUtil = require('../util/clazz');
|
||||
var layout = require('../util/layout');
|
||||
|
||||
/**
|
||||
* @alias module:echarts/model/Component
|
||||
* @constructor
|
||||
* @param {Object} option
|
||||
* @param {module:echarts/model/Model} parentModel
|
||||
* @param {module:echarts/model/Model} ecModel
|
||||
*/
|
||||
var ComponentModel = Model.extend({
|
||||
|
||||
type: 'component',
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
* @type {string}
|
||||
*/
|
||||
id: '',
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
*/
|
||||
name: '',
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
* @type {string}
|
||||
*/
|
||||
mainType: '',
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
* @type {string}
|
||||
*/
|
||||
subType: '',
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
* @type {number}
|
||||
*/
|
||||
componentIndex: 0,
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @protected
|
||||
*/
|
||||
defaultOption: null,
|
||||
|
||||
/**
|
||||
* @type {module:echarts/model/Global}
|
||||
* @readOnly
|
||||
*/
|
||||
ecModel: null,
|
||||
|
||||
/**
|
||||
* key: componentType
|
||||
* value: Component model list, can not be null.
|
||||
* @type {Object.<string, Array.<module:echarts/model/Model>>}
|
||||
* @readOnly
|
||||
*/
|
||||
dependentModels: [],
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @readOnly
|
||||
*/
|
||||
uid: null,
|
||||
|
||||
/**
|
||||
* Support merge layout params.
|
||||
* Only support 'box' now (left/right/top/bottom/width/height).
|
||||
* @type {string|Object} Object can be {ignoreSize: true}
|
||||
* @readOnly
|
||||
*/
|
||||
layoutMode: null,
|
||||
|
||||
|
||||
init: function (option, parentModel, ecModel, extraOpt) {
|
||||
this.mergeDefaultAndTheme(this.option, this.ecModel);
|
||||
},
|
||||
|
||||
mergeDefaultAndTheme: function (option, ecModel) {
|
||||
var layoutMode = this.layoutMode;
|
||||
var inputPositionParams = layoutMode
|
||||
? layout.getLayoutParams(option) : {};
|
||||
|
||||
var themeModel = ecModel.getTheme();
|
||||
zrUtil.merge(option, themeModel.get(this.mainType));
|
||||
zrUtil.merge(option, this.getDefaultOption());
|
||||
|
||||
if (layoutMode) {
|
||||
layout.mergeLayoutParam(option, inputPositionParams, layoutMode);
|
||||
}
|
||||
},
|
||||
|
||||
mergeOption: function (option) {
|
||||
zrUtil.merge(this.option, option, true);
|
||||
|
||||
var layoutMode = this.layoutMode;
|
||||
if (layoutMode) {
|
||||
layout.mergeLayoutParam(this.option, option, layoutMode);
|
||||
}
|
||||
},
|
||||
|
||||
// Hooker after init or mergeOption
|
||||
optionUpdated: function (ecModel) {},
|
||||
|
||||
getDefaultOption: function () {
|
||||
if (!this.hasOwnProperty('__defaultOption')) {
|
||||
var optList = [];
|
||||
var Class = this.constructor;
|
||||
while (Class) {
|
||||
var opt = Class.prototype.defaultOption;
|
||||
opt && optList.push(opt);
|
||||
Class = Class.superClass;
|
||||
}
|
||||
|
||||
var defaultOption = {};
|
||||
for (var i = optList.length - 1; i >= 0; i--) {
|
||||
defaultOption = zrUtil.merge(defaultOption, optList[i], true);
|
||||
}
|
||||
this.__defaultOption = defaultOption;
|
||||
}
|
||||
return this.__defaultOption;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Reset ComponentModel.extend, add preConstruct.
|
||||
clazzUtil.enableClassExtend(
|
||||
ComponentModel,
|
||||
function (option, parentModel, ecModel, extraOpt) {
|
||||
// Set dependentModels, componentIndex, name, id, mainType, subType.
|
||||
zrUtil.extend(this, extraOpt);
|
||||
|
||||
this.uid = componentUtil.getUID('componentModel');
|
||||
|
||||
// this.setReadOnly([
|
||||
// 'type', 'id', 'uid', 'name', 'mainType', 'subType',
|
||||
// 'dependentModels', 'componentIndex'
|
||||
// ]);
|
||||
}
|
||||
);
|
||||
|
||||
// Add capability of registerClass, getClass, hasClass, registerSubTypeDefaulter and so on.
|
||||
clazzUtil.enableClassManagement(
|
||||
ComponentModel, {registerWhenExtend: true}
|
||||
);
|
||||
componentUtil.enableSubTypeDefaulter(ComponentModel);
|
||||
|
||||
// Add capability of ComponentModel.topologicalTravel.
|
||||
componentUtil.enableTopologicalTravel(ComponentModel, getDependencies);
|
||||
|
||||
function getDependencies(componentType) {
|
||||
var deps = [];
|
||||
zrUtil.each(ComponentModel.getClassesByMainType(componentType), function (Clazz) {
|
||||
arrayPush.apply(deps, Clazz.prototype.dependencies || []);
|
||||
});
|
||||
// Ensure main type
|
||||
return zrUtil.map(deps, function (type) {
|
||||
return clazzUtil.parseClassType(type).main;
|
||||
});
|
||||
}
|
||||
|
||||
zrUtil.mixin(ComponentModel, require('./mixin/boxLayout'));
|
||||
|
||||
return ComponentModel;
|
||||
});
|
||||
752
vendors/echarts/src/model/Global.js
vendored
Normal file
752
vendors/echarts/src/model/Global.js
vendored
Normal file
@@ -0,0 +1,752 @@
|
||||
/**
|
||||
* ECharts global model
|
||||
*
|
||||
* @module {echarts/model/Global}
|
||||
*
|
||||
*/
|
||||
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var modelUtil = require('../util/model');
|
||||
var Model = require('./Model');
|
||||
var each = zrUtil.each;
|
||||
var filter = zrUtil.filter;
|
||||
var map = zrUtil.map;
|
||||
var isArray = zrUtil.isArray;
|
||||
var indexOf = zrUtil.indexOf;
|
||||
var isObject = zrUtil.isObject;
|
||||
|
||||
var ComponentModel = require('./Component');
|
||||
|
||||
var globalDefault = require('./globalDefault');
|
||||
|
||||
var OPTION_INNER_KEY = '\0_ec_inner';
|
||||
|
||||
/**
|
||||
* @alias module:echarts/model/Global
|
||||
*
|
||||
* @param {Object} option
|
||||
* @param {module:echarts/model/Model} parentModel
|
||||
* @param {Object} theme
|
||||
*/
|
||||
var GlobalModel = Model.extend({
|
||||
|
||||
constructor: GlobalModel,
|
||||
|
||||
init: function (option, parentModel, theme, optionManager) {
|
||||
theme = theme || {};
|
||||
|
||||
this.option = null; // Mark as not initialized.
|
||||
|
||||
/**
|
||||
* @type {module:echarts/model/Model}
|
||||
* @private
|
||||
*/
|
||||
this._theme = new Model(theme);
|
||||
|
||||
/**
|
||||
* @type {module:echarts/model/OptionManager}
|
||||
*/
|
||||
this._optionManager = optionManager;
|
||||
},
|
||||
|
||||
setOption: function (option, optionPreprocessorFuncs) {
|
||||
zrUtil.assert(
|
||||
!(OPTION_INNER_KEY in option),
|
||||
'please use chart.getOption()'
|
||||
);
|
||||
|
||||
this._optionManager.setOption(option, optionPreprocessorFuncs);
|
||||
|
||||
this.resetOption();
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} type null/undefined: reset all.
|
||||
* 'recreate': force recreate all.
|
||||
* 'timeline': only reset timeline option
|
||||
* 'media': only reset media query option
|
||||
* @return {boolean} Whether option changed.
|
||||
*/
|
||||
resetOption: function (type) {
|
||||
var optionChanged = false;
|
||||
var optionManager = this._optionManager;
|
||||
|
||||
if (!type || type === 'recreate') {
|
||||
var baseOption = optionManager.mountOption(type === 'recreate');
|
||||
|
||||
if (!this.option || type === 'recreate') {
|
||||
initBase.call(this, baseOption);
|
||||
}
|
||||
else {
|
||||
this.restoreData();
|
||||
this.mergeOption(baseOption);
|
||||
}
|
||||
optionChanged = true;
|
||||
}
|
||||
|
||||
if (type === 'timeline' || type === 'media') {
|
||||
this.restoreData();
|
||||
}
|
||||
|
||||
if (!type || type === 'recreate' || type === 'timeline') {
|
||||
var timelineOption = optionManager.getTimelineOption(this);
|
||||
timelineOption && (this.mergeOption(timelineOption), optionChanged = true);
|
||||
}
|
||||
|
||||
if (!type || type === 'recreate' || type === 'media') {
|
||||
var mediaOptions = optionManager.getMediaOption(this, this._api);
|
||||
if (mediaOptions.length) {
|
||||
each(mediaOptions, function (mediaOption) {
|
||||
this.mergeOption(mediaOption, optionChanged = true);
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
return optionChanged;
|
||||
},
|
||||
|
||||
/**
|
||||
* @protected
|
||||
*/
|
||||
mergeOption: function (newOption) {
|
||||
var option = this.option;
|
||||
var componentsMap = this._componentsMap;
|
||||
var newCptTypes = [];
|
||||
|
||||
// 如果不存在对应的 component model 则直接 merge
|
||||
each(newOption, function (componentOption, mainType) {
|
||||
if (componentOption == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ComponentModel.hasClass(mainType)) {
|
||||
option[mainType] = option[mainType] == null
|
||||
? zrUtil.clone(componentOption)
|
||||
: zrUtil.merge(option[mainType], componentOption, true);
|
||||
}
|
||||
else {
|
||||
newCptTypes.push(mainType);
|
||||
}
|
||||
});
|
||||
|
||||
// FIXME OPTION 同步是否要改回原来的
|
||||
ComponentModel.topologicalTravel(
|
||||
newCptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this
|
||||
);
|
||||
|
||||
function visitComponent(mainType, dependencies) {
|
||||
var newCptOptionList = modelUtil.normalizeToArray(newOption[mainType]);
|
||||
|
||||
var mapResult = modelUtil.mappingToExists(
|
||||
componentsMap[mainType], newCptOptionList
|
||||
);
|
||||
|
||||
makeKeyInfo(mainType, mapResult);
|
||||
|
||||
var dependentModels = getComponentsByTypes(
|
||||
componentsMap, dependencies
|
||||
);
|
||||
|
||||
option[mainType] = [];
|
||||
componentsMap[mainType] = [];
|
||||
|
||||
each(mapResult, function (resultItem, index) {
|
||||
var componentModel = resultItem.exist;
|
||||
var newCptOption = resultItem.option;
|
||||
|
||||
zrUtil.assert(
|
||||
isObject(newCptOption) || componentModel,
|
||||
'Empty component definition'
|
||||
);
|
||||
|
||||
// Consider where is no new option and should be merged using {},
|
||||
// see removeEdgeAndAdd in topologicalTravel and
|
||||
// ComponentModel.getAllClassMainTypes.
|
||||
if (!newCptOption) {
|
||||
componentModel.mergeOption({}, this);
|
||||
componentModel.optionUpdated(this);
|
||||
}
|
||||
else {
|
||||
var ComponentModelClass = ComponentModel.getClass(
|
||||
mainType, resultItem.keyInfo.subType, true
|
||||
);
|
||||
|
||||
if (componentModel && componentModel instanceof ComponentModelClass) {
|
||||
componentModel.mergeOption(newCptOption, this);
|
||||
componentModel.optionUpdated(this);
|
||||
}
|
||||
else {
|
||||
// PENDING Global as parent ?
|
||||
componentModel = new ComponentModelClass(
|
||||
newCptOption, this, this,
|
||||
zrUtil.extend(
|
||||
{
|
||||
dependentModels: dependentModels,
|
||||
componentIndex: index
|
||||
},
|
||||
resultItem.keyInfo
|
||||
)
|
||||
);
|
||||
// Call optionUpdated after init
|
||||
componentModel.optionUpdated(this);
|
||||
}
|
||||
}
|
||||
|
||||
componentsMap[mainType][index] = componentModel;
|
||||
option[mainType][index] = componentModel.option;
|
||||
}, this);
|
||||
|
||||
// Backup series for filtering.
|
||||
if (mainType === 'series') {
|
||||
this._seriesIndices = createSeriesIndices(componentsMap.series);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get option for output (cloned option and inner info removed)
|
||||
* @public
|
||||
* @return {Object}
|
||||
*/
|
||||
getOption: function () {
|
||||
var option = zrUtil.clone(this.option);
|
||||
|
||||
each(option, function (opts, mainType) {
|
||||
if (ComponentModel.hasClass(mainType)) {
|
||||
var opts = modelUtil.normalizeToArray(opts);
|
||||
for (var i = opts.length - 1; i >= 0; i--) {
|
||||
// Remove options with inner id.
|
||||
if (modelUtil.isIdInner(opts[i])) {
|
||||
opts.splice(i, 1);
|
||||
}
|
||||
}
|
||||
option[mainType] = opts;
|
||||
}
|
||||
});
|
||||
|
||||
delete option[OPTION_INNER_KEY];
|
||||
|
||||
return option;
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {module:echarts/model/Model}
|
||||
*/
|
||||
getTheme: function () {
|
||||
return this._theme;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} mainType
|
||||
* @param {number} [idx=0]
|
||||
* @return {module:echarts/model/Component}
|
||||
*/
|
||||
getComponent: function (mainType, idx) {
|
||||
var list = this._componentsMap[mainType];
|
||||
if (list) {
|
||||
return list[idx || 0];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Object} condition
|
||||
* @param {string} condition.mainType
|
||||
* @param {string} [condition.subType] If ignore, only query by mainType
|
||||
* @param {number} [condition.index] Either input index or id or name.
|
||||
* @param {string} [condition.id] Either input index or id or name.
|
||||
* @param {string} [condition.name] Either input index or id or name.
|
||||
* @return {Array.<module:echarts/model/Component>}
|
||||
*/
|
||||
queryComponents: function (condition) {
|
||||
var mainType = condition.mainType;
|
||||
if (!mainType) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var index = condition.index;
|
||||
var id = condition.id;
|
||||
var name = condition.name;
|
||||
|
||||
var cpts = this._componentsMap[mainType];
|
||||
|
||||
if (!cpts || !cpts.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var result;
|
||||
|
||||
if (index != null) {
|
||||
if (!isArray(index)) {
|
||||
index = [index];
|
||||
}
|
||||
result = filter(map(index, function (idx) {
|
||||
return cpts[idx];
|
||||
}), function (val) {
|
||||
return !!val;
|
||||
});
|
||||
}
|
||||
else if (id != null) {
|
||||
var isIdArray = isArray(id);
|
||||
result = filter(cpts, function (cpt) {
|
||||
return (isIdArray && indexOf(id, cpt.id) >= 0)
|
||||
|| (!isIdArray && cpt.id === id);
|
||||
});
|
||||
}
|
||||
else if (name != null) {
|
||||
var isNameArray = isArray(name);
|
||||
result = filter(cpts, function (cpt) {
|
||||
return (isNameArray && indexOf(name, cpt.name) >= 0)
|
||||
|| (!isNameArray && cpt.name === name);
|
||||
});
|
||||
}
|
||||
|
||||
return filterBySubType(result, condition);
|
||||
},
|
||||
|
||||
/**
|
||||
* The interface is different from queryComponents,
|
||||
* which is convenient for inner usage.
|
||||
*
|
||||
* @usage
|
||||
* var result = findComponents(
|
||||
* {mainType: 'dataZoom', query: {dataZoomId: 'abc'}}
|
||||
* );
|
||||
* var result = findComponents(
|
||||
* {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}}
|
||||
* );
|
||||
* var result = findComponents(
|
||||
* {mainType: 'series'},
|
||||
* function (model, index) {...}
|
||||
* );
|
||||
* // result like [component0, componnet1, ...]
|
||||
*
|
||||
* @param {Object} condition
|
||||
* @param {string} condition.mainType Mandatory.
|
||||
* @param {string} [condition.subType] Optional.
|
||||
* @param {Object} [condition.query] like {xxxIndex, xxxId, xxxName},
|
||||
* where xxx is mainType.
|
||||
* If query attribute is null/undefined or has no index/id/name,
|
||||
* do not filtering by query conditions, which is convenient for
|
||||
* no-payload situations or when target of action is global.
|
||||
* @param {Function} [condition.filter] parameter: component, return boolean.
|
||||
* @return {Array.<module:echarts/model/Component>}
|
||||
*/
|
||||
findComponents: function (condition) {
|
||||
var query = condition.query;
|
||||
var mainType = condition.mainType;
|
||||
|
||||
var queryCond = getQueryCond(query);
|
||||
var result = queryCond
|
||||
? this.queryComponents(queryCond)
|
||||
: this._componentsMap[mainType];
|
||||
|
||||
return doFilter(filterBySubType(result, condition));
|
||||
|
||||
function getQueryCond(q) {
|
||||
var indexAttr = mainType + 'Index';
|
||||
var idAttr = mainType + 'Id';
|
||||
var nameAttr = mainType + 'Name';
|
||||
return q && (
|
||||
q.hasOwnProperty(indexAttr)
|
||||
|| q.hasOwnProperty(idAttr)
|
||||
|| q.hasOwnProperty(nameAttr)
|
||||
)
|
||||
? {
|
||||
mainType: mainType,
|
||||
// subType will be filtered finally.
|
||||
index: q[indexAttr],
|
||||
id: q[idAttr],
|
||||
name: q[nameAttr]
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
function doFilter(res) {
|
||||
return condition.filter
|
||||
? filter(res, condition.filter)
|
||||
: res;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @usage
|
||||
* eachComponent('legend', function (legendModel, index) {
|
||||
* ...
|
||||
* });
|
||||
* eachComponent(function (componentType, model, index) {
|
||||
* // componentType does not include subType
|
||||
* // (componentType is 'xxx' but not 'xxx.aa')
|
||||
* });
|
||||
* eachComponent(
|
||||
* {mainType: 'dataZoom', query: {dataZoomId: 'abc'}},
|
||||
* function (model, index) {...}
|
||||
* );
|
||||
* eachComponent(
|
||||
* {mainType: 'series', subType: 'pie', query: {seriesName: 'uio'}},
|
||||
* function (model, index) {...}
|
||||
* );
|
||||
*
|
||||
* @param {string|Object=} mainType When mainType is object, the definition
|
||||
* is the same as the method 'findComponents'.
|
||||
* @param {Function} cb
|
||||
* @param {*} context
|
||||
*/
|
||||
eachComponent: function (mainType, cb, context) {
|
||||
var componentsMap = this._componentsMap;
|
||||
|
||||
if (typeof mainType === 'function') {
|
||||
context = cb;
|
||||
cb = mainType;
|
||||
each(componentsMap, function (components, componentType) {
|
||||
each(components, function (component, index) {
|
||||
cb.call(context, componentType, component, index);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (zrUtil.isString(mainType)) {
|
||||
each(componentsMap[mainType], cb, context);
|
||||
}
|
||||
else if (isObject(mainType)) {
|
||||
var queryResult = this.findComponents(mainType);
|
||||
each(queryResult, cb, context);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @return {Array.<module:echarts/model/Series>}
|
||||
*/
|
||||
getSeriesByName: function (name) {
|
||||
var series = this._componentsMap.series;
|
||||
return filter(series, function (oneSeries) {
|
||||
return oneSeries.name === name;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} seriesIndex
|
||||
* @return {module:echarts/model/Series}
|
||||
*/
|
||||
getSeriesByIndex: function (seriesIndex) {
|
||||
return this._componentsMap.series[seriesIndex];
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} subType
|
||||
* @return {Array.<module:echarts/model/Series>}
|
||||
*/
|
||||
getSeriesByType: function (subType) {
|
||||
var series = this._componentsMap.series;
|
||||
return filter(series, function (oneSeries) {
|
||||
return oneSeries.subType === subType;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {Array.<module:echarts/model/Series>}
|
||||
*/
|
||||
getSeries: function () {
|
||||
return this._componentsMap.series.slice();
|
||||
},
|
||||
|
||||
/**
|
||||
* After filtering, series may be different
|
||||
* frome raw series.
|
||||
*
|
||||
* @param {Function} cb
|
||||
* @param {*} context
|
||||
*/
|
||||
eachSeries: function (cb, context) {
|
||||
assertSeriesInitialized(this);
|
||||
each(this._seriesIndices, function (rawSeriesIndex) {
|
||||
var series = this._componentsMap.series[rawSeriesIndex];
|
||||
cb.call(context, series, rawSeriesIndex);
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterate raw series before filtered.
|
||||
*
|
||||
* @param {Function} cb
|
||||
* @param {*} context
|
||||
*/
|
||||
eachRawSeries: function (cb, context) {
|
||||
each(this._componentsMap.series, cb, context);
|
||||
},
|
||||
|
||||
/**
|
||||
* After filtering, series may be different.
|
||||
* frome raw series.
|
||||
*
|
||||
* @parma {string} subType
|
||||
* @param {Function} cb
|
||||
* @param {*} context
|
||||
*/
|
||||
eachSeriesByType: function (subType, cb, context) {
|
||||
assertSeriesInitialized(this);
|
||||
each(this._seriesIndices, function (rawSeriesIndex) {
|
||||
var series = this._componentsMap.series[rawSeriesIndex];
|
||||
if (series.subType === subType) {
|
||||
cb.call(context, series, rawSeriesIndex);
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterate raw series before filtered of given type.
|
||||
*
|
||||
* @parma {string} subType
|
||||
* @param {Function} cb
|
||||
* @param {*} context
|
||||
*/
|
||||
eachRawSeriesByType: function (subType, cb, context) {
|
||||
return each(this.getSeriesByType(subType), cb, context);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {module:echarts/model/Series} seriesModel
|
||||
*/
|
||||
isSeriesFiltered: function (seriesModel) {
|
||||
assertSeriesInitialized(this);
|
||||
return zrUtil.indexOf(this._seriesIndices, seriesModel.componentIndex) < 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {Function} cb
|
||||
* @param {*} context
|
||||
*/
|
||||
filterSeries: function (cb, context) {
|
||||
assertSeriesInitialized(this);
|
||||
var filteredSeries = filter(
|
||||
this._componentsMap.series, cb, context
|
||||
);
|
||||
this._seriesIndices = createSeriesIndices(filteredSeries);
|
||||
},
|
||||
|
||||
restoreData: function () {
|
||||
var componentsMap = this._componentsMap;
|
||||
|
||||
this._seriesIndices = createSeriesIndices(componentsMap.series);
|
||||
|
||||
var componentTypes = [];
|
||||
each(componentsMap, function (components, componentType) {
|
||||
componentTypes.push(componentType);
|
||||
});
|
||||
|
||||
ComponentModel.topologicalTravel(
|
||||
componentTypes,
|
||||
ComponentModel.getAllClassMainTypes(),
|
||||
function (componentType, dependencies) {
|
||||
each(componentsMap[componentType], function (component) {
|
||||
component.restoreData();
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function mergeTheme(option, theme) {
|
||||
for (var name in theme) {
|
||||
// 如果有 component model 则把具体的 merge 逻辑交给该 model 处理
|
||||
if (!ComponentModel.hasClass(name)) {
|
||||
if (typeof theme[name] === 'object') {
|
||||
option[name] = !option[name]
|
||||
? zrUtil.clone(theme[name])
|
||||
: zrUtil.merge(option[name], theme[name], false);
|
||||
}
|
||||
else {
|
||||
if (option[name] == null) {
|
||||
option[name] = theme[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initBase(baseOption) {
|
||||
baseOption = baseOption;
|
||||
|
||||
// Using OPTION_INNER_KEY to mark that this option can not be used outside,
|
||||
// i.e. `chart.setOption(chart.getModel().option);` is forbiden.
|
||||
this.option = {};
|
||||
this.option[OPTION_INNER_KEY] = 1;
|
||||
|
||||
/**
|
||||
* @type {Object.<string, Array.<module:echarts/model/Model>>}
|
||||
* @private
|
||||
*/
|
||||
this._componentsMap = {};
|
||||
|
||||
/**
|
||||
* Mapping between filtered series list and raw series list.
|
||||
* key: filtered series indices, value: raw series indices.
|
||||
* @type {Array.<nubmer>}
|
||||
* @private
|
||||
*/
|
||||
this._seriesIndices = null;
|
||||
|
||||
mergeTheme(baseOption, this._theme.option);
|
||||
|
||||
// TODO Needs clone when merging to the unexisted property
|
||||
zrUtil.merge(baseOption, globalDefault, false);
|
||||
|
||||
this.mergeOption(baseOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inner
|
||||
* @param {Array.<string>|string} types model types
|
||||
* @return {Object} key: {string} type, value: {Array.<Object>} models
|
||||
*/
|
||||
function getComponentsByTypes(componentsMap, types) {
|
||||
if (!zrUtil.isArray(types)) {
|
||||
types = types ? [types] : [];
|
||||
}
|
||||
|
||||
var ret = {};
|
||||
each(types, function (type) {
|
||||
ret[type] = (componentsMap[type] || []).slice();
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function makeKeyInfo(mainType, mapResult) {
|
||||
// We use this id to hash component models and view instances
|
||||
// in echarts. id can be specified by user, or auto generated.
|
||||
|
||||
// The id generation rule ensures new view instance are able
|
||||
// to mapped to old instance when setOption are called in
|
||||
// no-merge mode. So we generate model id by name and plus
|
||||
// type in view id.
|
||||
|
||||
// name can be duplicated among components, which is convenient
|
||||
// to specify multi components (like series) by one name.
|
||||
|
||||
// Ensure that each id is distinct.
|
||||
var idMap = {};
|
||||
|
||||
each(mapResult, function (item, index) {
|
||||
var existCpt = item.exist;
|
||||
existCpt && (idMap[existCpt.id] = item);
|
||||
});
|
||||
|
||||
each(mapResult, function (item, index) {
|
||||
var opt = item.option;
|
||||
|
||||
zrUtil.assert(
|
||||
!opt || opt.id == null || !idMap[opt.id] || idMap[opt.id] === item,
|
||||
'id duplicates: ' + (opt && opt.id)
|
||||
);
|
||||
|
||||
opt && opt.id != null && (idMap[opt.id] = item);
|
||||
|
||||
// Complete subType
|
||||
if (isObject(opt)) {
|
||||
var subType = determineSubType(mainType, opt, item.exist);
|
||||
item.keyInfo = {mainType: mainType, subType: subType};
|
||||
}
|
||||
});
|
||||
|
||||
// Make name and id.
|
||||
each(mapResult, function (item, index) {
|
||||
var existCpt = item.exist;
|
||||
var opt = item.option;
|
||||
var keyInfo = item.keyInfo;
|
||||
|
||||
if (!isObject(opt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// name can be overwitten. Consider case: axis.name = '20km'.
|
||||
// But id generated by name will not be changed, which affect
|
||||
// only in that case: setOption with 'not merge mode' and view
|
||||
// instance will be recreated, which can be accepted.
|
||||
keyInfo.name = opt.name != null
|
||||
? opt.name + ''
|
||||
: existCpt
|
||||
? existCpt.name
|
||||
: '\0-';
|
||||
|
||||
if (existCpt) {
|
||||
keyInfo.id = existCpt.id;
|
||||
}
|
||||
else if (opt.id != null) {
|
||||
keyInfo.id = opt.id + '';
|
||||
}
|
||||
else {
|
||||
// Consider this situatoin:
|
||||
// optionA: [{name: 'a'}, {name: 'a'}, {..}]
|
||||
// optionB [{..}, {name: 'a'}, {name: 'a'}]
|
||||
// Series with the same name between optionA and optionB
|
||||
// should be mapped.
|
||||
var idNum = 0;
|
||||
do {
|
||||
keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++;
|
||||
}
|
||||
while (idMap[keyInfo.id]);
|
||||
}
|
||||
|
||||
idMap[keyInfo.id] = item;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function determineSubType(mainType, newCptOption, existComponent) {
|
||||
var subType = newCptOption.type
|
||||
? newCptOption.type
|
||||
: existComponent
|
||||
? existComponent.subType
|
||||
// Use determineSubType only when there is no existComponent.
|
||||
: ComponentModel.determineSubType(mainType, newCptOption);
|
||||
|
||||
// tooltip, markline, markpoint may always has no subType
|
||||
return subType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function createSeriesIndices(seriesModels) {
|
||||
return map(seriesModels, function (series) {
|
||||
return series.componentIndex;
|
||||
}) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function filterBySubType(components, condition) {
|
||||
// Using hasOwnProperty for restrict. Consider
|
||||
// subType is undefined in user payload.
|
||||
return condition.hasOwnProperty('subType')
|
||||
? filter(components, function (cpt) {
|
||||
return cpt.subType === condition.subType;
|
||||
})
|
||||
: components;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inner
|
||||
*/
|
||||
function assertSeriesInitialized(ecModel) {
|
||||
// Components that use _seriesIndices should depends on series component,
|
||||
// which make sure that their initialization is after series.
|
||||
if (!ecModel._seriesIndices) {
|
||||
throw new Error('Series has not been initialized yet.');
|
||||
}
|
||||
}
|
||||
|
||||
return GlobalModel;
|
||||
});
|
||||
157
vendors/echarts/src/model/Model.js
vendored
Normal file
157
vendors/echarts/src/model/Model.js
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @module echarts/model/Model
|
||||
*/
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var clazzUtil = require('../util/clazz');
|
||||
|
||||
/**
|
||||
* @alias module:echarts/model/Model
|
||||
* @constructor
|
||||
* @param {Object} option
|
||||
* @param {module:echarts/model/Model} [parentModel]
|
||||
* @param {module:echarts/model/Global} [ecModel]
|
||||
* @param {Object} extraOpt
|
||||
*/
|
||||
function Model(option, parentModel, ecModel, extraOpt) {
|
||||
/**
|
||||
* @type {module:echarts/model/Model}
|
||||
* @readOnly
|
||||
*/
|
||||
this.parentModel = parentModel;
|
||||
|
||||
/**
|
||||
* @type {module:echarts/model/Global}
|
||||
* @readOnly
|
||||
*/
|
||||
this.ecModel = ecModel;
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @protected
|
||||
*/
|
||||
this.option = option;
|
||||
|
||||
// Simple optimization
|
||||
if (this.init) {
|
||||
if (arguments.length <= 4) {
|
||||
this.init(option, parentModel, ecModel, extraOpt);
|
||||
}
|
||||
else {
|
||||
this.init.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Model.prototype = {
|
||||
|
||||
constructor: Model,
|
||||
|
||||
/**
|
||||
* Model 的初始化函数
|
||||
* @param {Object} option
|
||||
*/
|
||||
init: null,
|
||||
|
||||
/**
|
||||
* 从新的 Option merge
|
||||
*/
|
||||
mergeOption: function (option) {
|
||||
zrUtil.merge(this.option, option, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {boolean} [ignoreParent=false]
|
||||
* @return {*}
|
||||
*/
|
||||
get: function (path, ignoreParent) {
|
||||
if (!path) {
|
||||
return this.option;
|
||||
}
|
||||
|
||||
if (typeof path === 'string') {
|
||||
path = path.split('.');
|
||||
}
|
||||
|
||||
var obj = this.option;
|
||||
var parentModel = this.parentModel;
|
||||
for (var i = 0; i < path.length; i++) {
|
||||
// Ignore empty
|
||||
if (!path[i]) {
|
||||
continue;
|
||||
}
|
||||
// obj could be number/string/... (like 0)
|
||||
obj = (obj && typeof obj === 'object') ? obj[path[i]] : null;
|
||||
if (obj == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (obj == null && parentModel && !ignoreParent) {
|
||||
obj = parentModel.get(path);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {boolean} [ignoreParent=false]
|
||||
* @return {*}
|
||||
*/
|
||||
getShallow: function (key, ignoreParent) {
|
||||
var option = this.option;
|
||||
var val = option && option[key];
|
||||
var parentModel = this.parentModel;
|
||||
if (val == null && parentModel && !ignoreParent) {
|
||||
val = parentModel.getShallow(key);
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {module:echarts/model/Model} [parentModel]
|
||||
* @return {module:echarts/model/Model}
|
||||
*/
|
||||
getModel: function (path, parentModel) {
|
||||
var obj = this.get(path, true);
|
||||
var thisParentModel = this.parentModel;
|
||||
var model = new Model(
|
||||
obj, parentModel || (thisParentModel && thisParentModel.getModel(path)),
|
||||
this.ecModel
|
||||
);
|
||||
return model;
|
||||
},
|
||||
|
||||
/**
|
||||
* If model has option
|
||||
*/
|
||||
isEmpty: function () {
|
||||
return this.option == null;
|
||||
},
|
||||
|
||||
restoreData: function () {},
|
||||
|
||||
// Pending
|
||||
clone: function () {
|
||||
var Ctor = this.constructor;
|
||||
return new Ctor(zrUtil.clone(this.option));
|
||||
},
|
||||
|
||||
setReadOnly: function (properties) {
|
||||
clazzUtil.setReadOnly(this, properties);
|
||||
}
|
||||
};
|
||||
|
||||
// Enable Model.extend.
|
||||
clazzUtil.enableClassExtend(Model);
|
||||
|
||||
var mixin = zrUtil.mixin;
|
||||
mixin(Model, require('./mixin/lineStyle'));
|
||||
mixin(Model, require('./mixin/areaStyle'));
|
||||
mixin(Model, require('./mixin/textStyle'));
|
||||
mixin(Model, require('./mixin/itemStyle'));
|
||||
|
||||
return Model;
|
||||
});
|
||||
435
vendors/echarts/src/model/OptionManager.js
vendored
Normal file
435
vendors/echarts/src/model/OptionManager.js
vendored
Normal file
@@ -0,0 +1,435 @@
|
||||
/**
|
||||
* ECharts option manager
|
||||
*
|
||||
* @module {echarts/model/OptionManager}
|
||||
*/
|
||||
|
||||
define(function (require) {
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var modelUtil = require('../util/model');
|
||||
var ComponentModel = require('./Component');
|
||||
var each = zrUtil.each;
|
||||
var clone = zrUtil.clone;
|
||||
var map = zrUtil.map;
|
||||
var merge = zrUtil.merge;
|
||||
|
||||
var QUERY_REG = /^(min|max)?(.+)$/;
|
||||
|
||||
/**
|
||||
* TERM EXPLANATIONS:
|
||||
*
|
||||
* [option]:
|
||||
*
|
||||
* An object that contains definitions of components. For example:
|
||||
* var option = {
|
||||
* title: {...},
|
||||
* legend: {...},
|
||||
* visualMap: {...},
|
||||
* series: [
|
||||
* {data: [...]},
|
||||
* {data: [...]},
|
||||
* ...
|
||||
* ]
|
||||
* };
|
||||
*
|
||||
* [rawOption]:
|
||||
*
|
||||
* An object input to echarts.setOption. 'rawOption' may be an
|
||||
* 'option', or may be an object contains multi-options. For example:
|
||||
* var option = {
|
||||
* baseOption: {
|
||||
* title: {...},
|
||||
* legend: {...},
|
||||
* series: [
|
||||
* {data: [...]},
|
||||
* {data: [...]},
|
||||
* ...
|
||||
* ]
|
||||
* },
|
||||
* timeline: {...},
|
||||
* options: [
|
||||
* {title: {...}, series: {data: [...]}},
|
||||
* {title: {...}, series: {data: [...]}},
|
||||
* ...
|
||||
* ],
|
||||
* media: [
|
||||
* {
|
||||
* query: {maxWidth: 320},
|
||||
* option: {series: {x: 20}, visualMap: {show: false}}
|
||||
* },
|
||||
* {
|
||||
* query: {minWidth: 320, maxWidth: 720},
|
||||
* option: {series: {x: 500}, visualMap: {show: true}}
|
||||
* },
|
||||
* {
|
||||
* option: {series: {x: 1200}, visualMap: {show: true}}
|
||||
* }
|
||||
* ]
|
||||
* };
|
||||
*
|
||||
* @alias module:echarts/model/OptionManager
|
||||
* @param {module:echarts/ExtensionAPI} api
|
||||
*/
|
||||
function OptionManager(api) {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {module:echarts/ExtensionAPI}
|
||||
*/
|
||||
this._api = api;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this._timelineOptions = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array.<Object>}
|
||||
*/
|
||||
this._mediaList = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._mediaDefault;
|
||||
|
||||
/**
|
||||
* -1, means default.
|
||||
* empty means no media.
|
||||
* @private
|
||||
* @type {Array.<number>}
|
||||
*/
|
||||
this._currentMediaIndices = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._optionBackup;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Object}
|
||||
*/
|
||||
this._newBaseOption;
|
||||
}
|
||||
|
||||
// timeline.notMerge is not supported in ec3. Firstly there is rearly
|
||||
// case that notMerge is needed. Secondly supporting 'notMerge' requires
|
||||
// rawOption cloned and backuped when timeline changed, which does no
|
||||
// good to performance. What's more, that both timeline and setOption
|
||||
// method supply 'notMerge' brings complex and some problems.
|
||||
// Consider this case:
|
||||
// (step1) chart.setOption({timeline: {notMerge: false}, ...}, false);
|
||||
// (step2) chart.setOption({timeline: {notMerge: true}, ...}, false);
|
||||
|
||||
OptionManager.prototype = {
|
||||
|
||||
constructor: OptionManager,
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @param {Object} rawOption Raw option.
|
||||
* @param {module:echarts/model/Global} ecModel
|
||||
* @param {Array.<Function>} optionPreprocessorFuncs
|
||||
* @return {Object} Init option
|
||||
*/
|
||||
setOption: function (rawOption, optionPreprocessorFuncs) {
|
||||
rawOption = clone(rawOption, true);
|
||||
|
||||
// FIXME
|
||||
// 如果 timeline options 或者 media 中设置了某个属性,而baseOption中没有设置,则进行警告。
|
||||
|
||||
var oldOptionBackup = this._optionBackup;
|
||||
var newParsedOption = parseRawOption.call(
|
||||
this, rawOption, optionPreprocessorFuncs
|
||||
);
|
||||
this._newBaseOption = newParsedOption.baseOption;
|
||||
|
||||
// For setOption at second time (using merge mode);
|
||||
if (oldOptionBackup) {
|
||||
// Only baseOption can be merged.
|
||||
mergeOption(oldOptionBackup.baseOption, newParsedOption.baseOption);
|
||||
|
||||
// For simplicity, timeline options and media options do not support merge,
|
||||
// that is, if you `setOption` twice and both has timeline options, the latter
|
||||
// timeline opitons will not be merged to the formers, but just substitude them.
|
||||
if (newParsedOption.timelineOptions.length) {
|
||||
oldOptionBackup.timelineOptions = newParsedOption.timelineOptions;
|
||||
}
|
||||
if (newParsedOption.mediaList.length) {
|
||||
oldOptionBackup.mediaList = newParsedOption.mediaList;
|
||||
}
|
||||
if (newParsedOption.mediaDefault) {
|
||||
oldOptionBackup.mediaDefault = newParsedOption.mediaDefault;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._optionBackup = newParsedOption;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {boolean} isRecreate
|
||||
* @return {Object}
|
||||
*/
|
||||
mountOption: function (isRecreate) {
|
||||
var optionBackup = this._optionBackup;
|
||||
|
||||
// TODO
|
||||
// 如果没有reset功能则不clone。
|
||||
|
||||
this._timelineOptions = map(optionBackup.timelineOptions, clone);
|
||||
this._mediaList = map(optionBackup.mediaList, clone);
|
||||
this._mediaDefault = clone(optionBackup.mediaDefault);
|
||||
this._currentMediaIndices = [];
|
||||
|
||||
return clone(isRecreate
|
||||
// this._optionBackup.baseOption, which is created at the first `setOption`
|
||||
// called, and is merged into every new option by inner method `mergeOption`
|
||||
// each time `setOption` called, can be only used in `isRecreate`, because
|
||||
// its reliability is under suspicion. In other cases option merge is
|
||||
// proformed by `model.mergeOption`.
|
||||
? optionBackup.baseOption : this._newBaseOption
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {module:echarts/model/Global} ecModel
|
||||
* @return {Object}
|
||||
*/
|
||||
getTimelineOption: function (ecModel) {
|
||||
var option;
|
||||
var timelineOptions = this._timelineOptions;
|
||||
|
||||
if (timelineOptions.length) {
|
||||
// getTimelineOption can only be called after ecModel inited,
|
||||
// so we can get currentIndex from timelineModel.
|
||||
var timelineModel = ecModel.getComponent('timeline');
|
||||
if (timelineModel) {
|
||||
option = clone(
|
||||
timelineOptions[timelineModel.getCurrentIndex()],
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return option;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {module:echarts/model/Global} ecModel
|
||||
* @return {Array.<Object>}
|
||||
*/
|
||||
getMediaOption: function (ecModel) {
|
||||
var ecWidth = this._api.getWidth();
|
||||
var ecHeight = this._api.getHeight();
|
||||
var mediaList = this._mediaList;
|
||||
var mediaDefault = this._mediaDefault;
|
||||
var indices = [];
|
||||
var result = [];
|
||||
|
||||
// No media defined.
|
||||
if (!mediaList.length && !mediaDefault) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Multi media may be applied, the latter defined media has higher priority.
|
||||
for (var i = 0, len = mediaList.length; i < len; i++) {
|
||||
if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) {
|
||||
indices.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME
|
||||
// 是否mediaDefault应该强制用户设置,否则可能修改不能回归。
|
||||
if (!indices.length && mediaDefault) {
|
||||
indices = [-1];
|
||||
}
|
||||
|
||||
if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) {
|
||||
result = map(indices, function (index) {
|
||||
return clone(
|
||||
index === -1 ? mediaDefault.option : mediaList[index].option
|
||||
);
|
||||
});
|
||||
}
|
||||
// Otherwise return nothing.
|
||||
|
||||
this._currentMediaIndices = indices;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
function parseRawOption(rawOption, optionPreprocessorFuncs) {
|
||||
var timelineOptions = [];
|
||||
var mediaList = [];
|
||||
var mediaDefault;
|
||||
var baseOption;
|
||||
|
||||
// Compatible with ec2.
|
||||
var timelineOpt = rawOption.timeline;
|
||||
|
||||
if (rawOption.baseOption) {
|
||||
baseOption = rawOption.baseOption;
|
||||
}
|
||||
|
||||
// For timeline
|
||||
if (timelineOpt || rawOption.options) {
|
||||
baseOption = baseOption || {};
|
||||
timelineOptions = (rawOption.options || []).slice();
|
||||
}
|
||||
|
||||
// For media query
|
||||
if (rawOption.media) {
|
||||
baseOption = baseOption || {};
|
||||
var media = rawOption.media;
|
||||
each(media, function (singleMedia) {
|
||||
if (singleMedia && singleMedia.option) {
|
||||
if (singleMedia.query) {
|
||||
mediaList.push(singleMedia);
|
||||
}
|
||||
else if (!mediaDefault) {
|
||||
// Use the first media default.
|
||||
mediaDefault = singleMedia;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// For normal option
|
||||
if (!baseOption) {
|
||||
baseOption = rawOption;
|
||||
}
|
||||
|
||||
// Set timelineOpt to baseOption in ec3,
|
||||
// which is convenient for merge option.
|
||||
if (!baseOption.timeline) {
|
||||
baseOption.timeline = timelineOpt;
|
||||
}
|
||||
|
||||
// Preprocess.
|
||||
each([baseOption].concat(timelineOptions)
|
||||
.concat(zrUtil.map(mediaList, function (media) {
|
||||
return media.option;
|
||||
})),
|
||||
function (option) {
|
||||
each(optionPreprocessorFuncs, function (preProcess) {
|
||||
preProcess(option);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
baseOption: baseOption,
|
||||
timelineOptions: timelineOptions,
|
||||
mediaDefault: mediaDefault,
|
||||
mediaList: mediaList
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @see <http://www.w3.org/TR/css3-mediaqueries/#media1>
|
||||
* Support: width, height, aspectRatio
|
||||
* Can use max or min as prefix.
|
||||
*/
|
||||
function applyMediaQuery(query, ecWidth, ecHeight) {
|
||||
var realMap = {
|
||||
width: ecWidth,
|
||||
height: ecHeight,
|
||||
aspectratio: ecWidth / ecHeight // lowser case for convenientce.
|
||||
};
|
||||
|
||||
var applicatable = true;
|
||||
|
||||
zrUtil.each(query, function (value, attr) {
|
||||
var matched = attr.match(QUERY_REG);
|
||||
|
||||
if (!matched || !matched[1] || !matched[2]) {
|
||||
return;
|
||||
}
|
||||
|
||||
var operator = matched[1];
|
||||
var realAttr = matched[2].toLowerCase();
|
||||
|
||||
if (!compare(realMap[realAttr], value, operator)) {
|
||||
applicatable = false;
|
||||
}
|
||||
});
|
||||
|
||||
return applicatable;
|
||||
}
|
||||
|
||||
function compare(real, expect, operator) {
|
||||
if (operator === 'min') {
|
||||
return real >= expect;
|
||||
}
|
||||
else if (operator === 'max') {
|
||||
return real <= expect;
|
||||
}
|
||||
else { // Equals
|
||||
return real === expect;
|
||||
}
|
||||
}
|
||||
|
||||
function indicesEquals(indices1, indices2) {
|
||||
// indices is always order by asc and has only finite number.
|
||||
return indices1.join(',') === indices2.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* Consider case:
|
||||
* `chart.setOption(opt1);`
|
||||
* Then user do some interaction like dataZoom, dataView changing.
|
||||
* `chart.setOption(opt2);`
|
||||
* Then user press 'reset button' in toolbox.
|
||||
*
|
||||
* After doing that all of the interaction effects should be reset, the
|
||||
* chart should be the same as the result of invoke
|
||||
* `chart.setOption(opt1); chart.setOption(opt2);`.
|
||||
*
|
||||
* Although it is not able ensure that
|
||||
* `chart.setOption(opt1); chart.setOption(opt2);` is equivalents to
|
||||
* `chart.setOption(merge(opt1, opt2));` exactly,
|
||||
* this might be the only simple way to implement that feature.
|
||||
*
|
||||
* MEMO: We've considered some other approaches:
|
||||
* 1. Each model handle its self restoration but not uniform treatment.
|
||||
* (Too complex in logic and error-prone)
|
||||
* 2. Use a shadow ecModel. (Performace expensive)
|
||||
*/
|
||||
function mergeOption(oldOption, newOption) {
|
||||
newOption = newOption || {};
|
||||
|
||||
each(newOption, function (newCptOpt, mainType) {
|
||||
if (newCptOpt == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var oldCptOpt = oldOption[mainType];
|
||||
|
||||
if (!ComponentModel.hasClass(mainType)) {
|
||||
oldOption[mainType] = merge(oldCptOpt, newCptOpt, true);
|
||||
}
|
||||
else {
|
||||
newCptOpt = modelUtil.normalizeToArray(newCptOpt);
|
||||
oldCptOpt = modelUtil.normalizeToArray(oldCptOpt);
|
||||
|
||||
var mapResult = modelUtil.mappingToExists(oldCptOpt, newCptOpt);
|
||||
|
||||
oldOption[mainType] = map(mapResult, function (item) {
|
||||
return (item.option && item.exist)
|
||||
? merge(item.exist, item.option, true)
|
||||
: (item.exist || item.option);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return OptionManager;
|
||||
});
|
||||
215
vendors/echarts/src/model/Series.js
vendored
Normal file
215
vendors/echarts/src/model/Series.js
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
define(function(require) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var zrUtil = require('zrender/core/util');
|
||||
var formatUtil = require('../util/format');
|
||||
var modelUtil = require('../util/model');
|
||||
var ComponentModel = require('./Component');
|
||||
|
||||
var encodeHTML = formatUtil.encodeHTML;
|
||||
var addCommas = formatUtil.addCommas;
|
||||
|
||||
var SeriesModel = ComponentModel.extend({
|
||||
|
||||
type: 'series.__base__',
|
||||
|
||||
/**
|
||||
* @readOnly
|
||||
*/
|
||||
seriesIndex: 0,
|
||||
|
||||
// coodinateSystem will be injected in the echarts/CoordinateSystem
|
||||
coordinateSystem: null,
|
||||
|
||||
/**
|
||||
* @type {Object}
|
||||
* @protected
|
||||
*/
|
||||
defaultOption: null,
|
||||
|
||||
/**
|
||||
* Data provided for legend
|
||||
* @type {Function}
|
||||
*/
|
||||
// PENDING
|
||||
legendDataProvider: null,
|
||||
|
||||
init: function (option, parentModel, ecModel, extraOpt) {
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @readOnly
|
||||
*/
|
||||
this.seriesIndex = this.componentIndex;
|
||||
|
||||
this.mergeDefaultAndTheme(option, ecModel);
|
||||
|
||||
/**
|
||||
* @type {module:echarts/data/List|module:echarts/data/Tree|module:echarts/data/Graph}
|
||||
* @private
|
||||
*/
|
||||
this._dataBeforeProcessed = this.getInitialData(option, ecModel);
|
||||
|
||||
// If we reverse the order (make this._data firstly, and then make
|
||||
// this._dataBeforeProcessed by cloneShallow), cloneShallow will
|
||||
// cause this._data.graph.data !== this._data when using
|
||||
// module:echarts/data/Graph or module:echarts/data/Tree.
|
||||
// See module:echarts/data/helper/linkList
|
||||
this._data = this._dataBeforeProcessed.cloneShallow();
|
||||
},
|
||||
|
||||
/**
|
||||
* Util for merge default and theme to option
|
||||
* @param {Object} option
|
||||
* @param {module:echarts/model/Global} ecModel
|
||||
*/
|
||||
mergeDefaultAndTheme: function (option, ecModel) {
|
||||
zrUtil.merge(
|
||||
option,
|
||||
ecModel.getTheme().get(this.subType)
|
||||
);
|
||||
zrUtil.merge(option, this.getDefaultOption());
|
||||
|
||||
// Default label emphasis `position` and `show`
|
||||
// FIXME Set label in mergeOption
|
||||
modelUtil.defaultEmphasis(option.label, modelUtil.LABEL_OPTIONS);
|
||||
|
||||
this.fillDataTextStyle(option.data);
|
||||
},
|
||||
|
||||
mergeOption: function (newSeriesOption, ecModel) {
|
||||
newSeriesOption = zrUtil.merge(this.option, newSeriesOption, true);
|
||||
this.fillDataTextStyle(newSeriesOption.data);
|
||||
|
||||
var data = this.getInitialData(newSeriesOption, ecModel);
|
||||
// TODO Merge data?
|
||||
if (data) {
|
||||
this._data = data;
|
||||
this._dataBeforeProcessed = data.cloneShallow();
|
||||
}
|
||||
},
|
||||
|
||||
fillDataTextStyle: function (data) {
|
||||
// Default data label emphasis `position` and `show`
|
||||
// FIXME Tree structure data ?
|
||||
// FIXME Performance ?
|
||||
if (data) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
if (data[i] && data[i].label) {
|
||||
modelUtil.defaultEmphasis(data[i].label, modelUtil.LABEL_OPTIONS);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Init a data structure from data related option in series
|
||||
* Must be overwritten
|
||||
*/
|
||||
getInitialData: function () {},
|
||||
|
||||
/**
|
||||
* @param {string} [dataType]
|
||||
* @return {module:echarts/data/List}
|
||||
*/
|
||||
getData: function (dataType) {
|
||||
return dataType == null ? this._data : this._data.getLinkedData(dataType);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {module:echarts/data/List} data
|
||||
*/
|
||||
setData: function (data) {
|
||||
this._data = data;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get data before processed
|
||||
* @return {module:echarts/data/List}
|
||||
*/
|
||||
getRawData: function () {
|
||||
return this._dataBeforeProcessed;
|
||||
},
|
||||
|
||||
/**
|
||||
* Coord dimension to data dimension.
|
||||
*
|
||||
* By default the result is the same as dimensions of series data.
|
||||
* But in some series data dimensions are different from coord dimensions (i.e.
|
||||
* candlestick and boxplot). Override this method to handle those cases.
|
||||
*
|
||||
* Coord dimension to data dimension can be one-to-many
|
||||
*
|
||||
* @param {string} coordDim
|
||||
* @return {Array.<string>} dimensions on the axis.
|
||||
*/
|
||||
coordDimToDataDim: function (coordDim) {
|
||||
return [coordDim];
|
||||
},
|
||||
|
||||
/**
|
||||
* Convert data dimension to coord dimension.
|
||||
*
|
||||
* @param {string|number} dataDim
|
||||
* @return {string}
|
||||
*/
|
||||
dataDimToCoordDim: function (dataDim) {
|
||||
return dataDim;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get base axis if has coordinate system and has axis.
|
||||
* By default use coordSys.getBaseAxis();
|
||||
* Can be overrided for some chart.
|
||||
* @return {type} description
|
||||
*/
|
||||
getBaseAxis: function () {
|
||||
var coordSys = this.coordinateSystem;
|
||||
return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis();
|
||||
},
|
||||
|
||||
// FIXME
|
||||
/**
|
||||
* Default tooltip formatter
|
||||
*
|
||||
* @param {number} dataIndex
|
||||
* @param {boolean} [multipleSeries=false]
|
||||
* @param {number} [dataType]
|
||||
*/
|
||||
formatTooltip: function (dataIndex, multipleSeries, dataType) {
|
||||
var data = this._data;
|
||||
var value = this.getRawValue(dataIndex);
|
||||
var formattedValue = zrUtil.isArray(value)
|
||||
? zrUtil.map(value, addCommas).join(', ') : addCommas(value);
|
||||
var name = data.getName(dataIndex);
|
||||
var color = data.getItemVisual(dataIndex, 'color');
|
||||
var colorEl = '<span style="display:inline-block;margin-right:5px;'
|
||||
+ 'border-radius:10px;width:9px;height:9px;background-color:' + color + '"></span>';
|
||||
|
||||
var seriesName = this.name;
|
||||
// FIXME
|
||||
if (seriesName === '\0-') {
|
||||
// Not show '-'
|
||||
seriesName = '';
|
||||
}
|
||||
return !multipleSeries
|
||||
? ((seriesName && encodeHTML(seriesName) + '<br />') + colorEl
|
||||
+ (name
|
||||
? encodeHTML(name) + ' : ' + formattedValue
|
||||
: formattedValue)
|
||||
)
|
||||
: (colorEl + encodeHTML(this.name) + ' : ' + formattedValue);
|
||||
},
|
||||
|
||||
restoreData: function () {
|
||||
this._data = this._dataBeforeProcessed.cloneShallow();
|
||||
},
|
||||
|
||||
getAxisTooltipDataIndex: null
|
||||
});
|
||||
|
||||
zrUtil.mixin(SeriesModel, modelUtil.dataFormatMixin);
|
||||
|
||||
return SeriesModel;
|
||||
});
|
||||
44
vendors/echarts/src/model/globalDefault.js
vendored
Normal file
44
vendors/echarts/src/model/globalDefault.js
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
define(function () {
|
||||
var platform = '';
|
||||
// Navigator not exists in node
|
||||
if (typeof navigator !== 'undefined') {
|
||||
platform = navigator.platform || '';
|
||||
}
|
||||
return {
|
||||
// 全图默认背景
|
||||
// backgroundColor: 'rgba(0,0,0,0)',
|
||||
|
||||
// https://dribbble.com/shots/1065960-Infographic-Pie-chart-visualization
|
||||
// color: ['#5793f3', '#d14a61', '#fd9c35', '#675bba', '#fec42c', '#dd4444', '#d4df5a', '#cd4870'],
|
||||
// 浅色
|
||||
// color: ['#bcd3bb', '#e88f70', '#edc1a5', '#9dc5c8', '#e1e8c8', '#7b7c68', '#e5b5b5', '#f0b489', '#928ea8', '#bda29a'],
|
||||
// color: ['#cc5664', '#9bd6ec', '#ea946e', '#8acaaa', '#f1ec64', '#ee8686', '#a48dc1', '#5da6bc', '#b9dcae'],
|
||||
// 深色
|
||||
color: ['#c23531','#2f4554', '#61a0a8', '#d48265', '#91c7ae','#749f83', '#ca8622', '#bda29a','#6e7074', '#546570', '#c4ccd3'],
|
||||
|
||||
// 默认需要 Grid 配置项
|
||||
grid: {},
|
||||
// 主题,主题
|
||||
textStyle: {
|
||||
// color: '#000',
|
||||
// decoration: 'none',
|
||||
// PENDING
|
||||
fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif',
|
||||
// fontFamily: 'Arial, Verdana, sans-serif',
|
||||
fontSize: 12,
|
||||
fontStyle: 'normal',
|
||||
fontWeight: 'normal'
|
||||
},
|
||||
// 主题,默认标志图形类型列表
|
||||
// symbolList: [
|
||||
// 'circle', 'rectangle', 'triangle', 'diamond',
|
||||
// 'emptyCircle', 'emptyRectangle', 'emptyTriangle', 'emptyDiamond'
|
||||
// ],
|
||||
animation: true, // 过渡动画是否开启
|
||||
animationThreshold: 2000, // 动画元素阀值,产生的图形原素超过2000不出动画
|
||||
animationDuration: 1000, // 过渡动画参数:进入
|
||||
animationDurationUpdate: 300, // 过渡动画参数:更新
|
||||
animationEasing: 'exponentialOut', //BounceOut
|
||||
animationEasingUpdate: 'cubicOut'
|
||||
};
|
||||
});
|
||||
14
vendors/echarts/src/model/mixin/areaStyle.js
vendored
Normal file
14
vendors/echarts/src/model/mixin/areaStyle.js
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
define(function (require) {
|
||||
return {
|
||||
getAreaStyle: require('./makeStyleMapper')(
|
||||
[
|
||||
['fill', 'color'],
|
||||
['shadowBlur'],
|
||||
['shadowOffsetX'],
|
||||
['shadowOffsetY'],
|
||||
['opacity'],
|
||||
['shadowColor']
|
||||
]
|
||||
)
|
||||
};
|
||||
});
|
||||
15
vendors/echarts/src/model/mixin/boxLayout.js
vendored
Normal file
15
vendors/echarts/src/model/mixin/boxLayout.js
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
define(function (require) {
|
||||
|
||||
return {
|
||||
getBoxLayoutParams: function () {
|
||||
return {
|
||||
left: this.get('left'),
|
||||
top: this.get('top'),
|
||||
right: this.get('right'),
|
||||
bottom: this.get('bottom'),
|
||||
width: this.get('width'),
|
||||
height: this.get('height')
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
16
vendors/echarts/src/model/mixin/itemStyle.js
vendored
Normal file
16
vendors/echarts/src/model/mixin/itemStyle.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
define(function (require) {
|
||||
return {
|
||||
getItemStyle: require('./makeStyleMapper')(
|
||||
[
|
||||
['fill', 'color'],
|
||||
['stroke', 'borderColor'],
|
||||
['lineWidth', 'borderWidth'],
|
||||
['opacity'],
|
||||
['shadowBlur'],
|
||||
['shadowOffsetX'],
|
||||
['shadowOffsetY'],
|
||||
['shadowColor']
|
||||
]
|
||||
)
|
||||
};
|
||||
});
|
||||
27
vendors/echarts/src/model/mixin/lineStyle.js
vendored
Normal file
27
vendors/echarts/src/model/mixin/lineStyle.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
define(function (require) {
|
||||
var getLineStyle = require('./makeStyleMapper')(
|
||||
[
|
||||
['lineWidth', 'width'],
|
||||
['stroke', 'color'],
|
||||
['opacity'],
|
||||
['shadowBlur'],
|
||||
['shadowOffsetX'],
|
||||
['shadowOffsetY'],
|
||||
['shadowColor']
|
||||
]
|
||||
);
|
||||
return {
|
||||
getLineStyle: function (excludes) {
|
||||
var style = getLineStyle.call(this, excludes);
|
||||
var lineDash = this.getLineDash();
|
||||
lineDash && (style.lineDash = lineDash);
|
||||
return style;
|
||||
},
|
||||
|
||||
getLineDash: function () {
|
||||
var lineType = this.get('type');
|
||||
return (lineType === 'solid' || lineType == null) ? null
|
||||
: (lineType === 'dashed' ? [5, 5] : [1, 1]);
|
||||
}
|
||||
};
|
||||
});
|
||||
28
vendors/echarts/src/model/mixin/makeStyleMapper.js
vendored
Normal file
28
vendors/echarts/src/model/mixin/makeStyleMapper.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// TODO Parse shadow style
|
||||
// TODO Only shallow path support
|
||||
define(function (require) {
|
||||
var zrUtil = require('zrender/core/util');
|
||||
|
||||
return function (properties) {
|
||||
// Normalize
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
if (!properties[i][1]) {
|
||||
properties[i][1] = properties[i][0];
|
||||
}
|
||||
}
|
||||
return function (excludes) {
|
||||
var style = {};
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
var propName = properties[i][1];
|
||||
if (excludes && zrUtil.indexOf(excludes, propName) >= 0) {
|
||||
continue;
|
||||
}
|
||||
var val = this.getShallow(propName);
|
||||
if (val != null) {
|
||||
style[properties[i][0]] = val;
|
||||
}
|
||||
}
|
||||
return style;
|
||||
};
|
||||
};
|
||||
});
|
||||
52
vendors/echarts/src/model/mixin/textStyle.js
vendored
Normal file
52
vendors/echarts/src/model/mixin/textStyle.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
define(function (require) {
|
||||
|
||||
var textContain = require('zrender/contain/text');
|
||||
|
||||
function getShallow(model, path) {
|
||||
return model && model.getShallow(path);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Get color property or get color from option.textStyle.color
|
||||
* @return {string}
|
||||
*/
|
||||
getTextColor: function () {
|
||||
var ecModel = this.ecModel;
|
||||
return this.getShallow('color')
|
||||
|| (ecModel && ecModel.get('textStyle.color'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Create font string from fontStyle, fontWeight, fontSize, fontFamily
|
||||
* @return {string}
|
||||
*/
|
||||
getFont: function () {
|
||||
var ecModel = this.ecModel;
|
||||
var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
|
||||
return [
|
||||
// FIXME in node-canvas fontWeight is before fontStyle
|
||||
this.getShallow('fontStyle') || getShallow(gTextStyleModel, 'fontStyle'),
|
||||
this.getShallow('fontWeight') || getShallow(gTextStyleModel, 'fontWeight'),
|
||||
(this.getShallow('fontSize') || getShallow(gTextStyleModel, 'fontSize') || 12) + 'px',
|
||||
this.getShallow('fontFamily') || getShallow(gTextStyleModel, 'fontFamily') || 'sans-serif'
|
||||
].join(' ');
|
||||
},
|
||||
|
||||
getTextRect: function (text) {
|
||||
var textStyle = this.get('textStyle') || {};
|
||||
return textContain.getBoundingRect(
|
||||
text,
|
||||
this.getFont(),
|
||||
textStyle.align,
|
||||
textStyle.baseline
|
||||
);
|
||||
},
|
||||
|
||||
ellipsis: function (text, containerWidth, options) {
|
||||
return textContain.ellipsis(
|
||||
text, this.getFont(), containerWidth, options
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user