blob: 4827e015ecbe1a6f16d3aa23dd15d077ada866be [file] [log] [blame]
/**
* @file Visual solution, for consistent option specification.
*/
import * as zrUtil from 'zrender/src/core/util';
import VisualMapping from './VisualMapping';
var each = zrUtil.each;
function hasKeys(obj) {
if (obj) {
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
return true;
}
}
}
}
/**
* @param {Object} option
* @param {Array.<string>} stateList
* @param {Function} [supplementVisualOption]
* @return {Object} visualMappings <state, <visualType, module:echarts/visual/VisualMapping>>
*/
export function createVisualMappings(option, stateList, supplementVisualOption) {
var visualMappings = {};
each(stateList, function (state) {
var mappings = visualMappings[state] = createMappings();
each(option[state], function (visualData, visualType) {
if (!VisualMapping.isValidType(visualType)) {
return;
}
var mappingOption = {
type: visualType,
visual: visualData
};
supplementVisualOption && supplementVisualOption(mappingOption, state);
mappings[visualType] = new VisualMapping(mappingOption); // Prepare a alpha for opacity, for some case that opacity
// is not supported, such as rendering using gradient color.
if (visualType === 'opacity') {
mappingOption = zrUtil.clone(mappingOption);
mappingOption.type = 'colorAlpha';
mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption);
}
});
});
return visualMappings;
function createMappings() {
var Creater = function () {}; // Make sure hidden fields will not be visited by
// object iteration (with hasOwnProperty checking).
Creater.prototype.__hidden = Creater.prototype;
var obj = new Creater();
return obj;
}
}
/**
* @param {Object} thisOption
* @param {Object} newOption
* @param {Array.<string>} keys
*/
export function replaceVisualOption(thisOption, newOption, keys) {
// Visual attributes merge is not supported, otherwise it
// brings overcomplicated merge logic. See #2853. So if
// newOption has anyone of these keys, all of these keys
// will be reset. Otherwise, all keys remain.
var has;
zrUtil.each(keys, function (key) {
if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
has = true;
}
});
has && zrUtil.each(keys, function (key) {
if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) {
thisOption[key] = zrUtil.clone(newOption[key]);
} else {
delete thisOption[key];
}
});
}
/**
* @param {Array.<string>} stateList
* @param {Object} visualMappings <state, Object.<visualType, module:echarts/visual/VisualMapping>>
* @param {module:echarts/data/List} list
* @param {Function} getValueState param: valueOrIndex, return: state.
* @param {object} [scope] Scope for getValueState
* @param {string} [dimension] Concrete dimension, if used.
*/
export function applyVisual(stateList, visualMappings, data, getValueState, scope, dimension) {
var visualTypesMap = {};
zrUtil.each(stateList, function (state) {
var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]);
visualTypesMap[state] = visualTypes;
});
var dataIndex;
function getVisual(key) {
return data.getItemVisual(dataIndex, key);
}
function setVisual(key, value) {
data.setItemVisual(dataIndex, key, value);
}
if (dimension == null) {
data.each(eachItem, true);
} else {
data.each([dimension], eachItem, true);
}
function eachItem(valueOrIndex, index) {
dataIndex = dimension == null ? valueOrIndex : index;
var rawDataItem = data.getRawDataItem(dataIndex); // Consider performance
if (rawDataItem && rawDataItem.visualMap === false) {
return;
}
var valueState = getValueState.call(scope, valueOrIndex);
var mappings = visualMappings[valueState];
var visualTypes = visualTypesMap[valueState];
for (var i = 0, len = visualTypes.length; i < len; i++) {
var type = visualTypes[i];
mappings[type] && mappings[type].applyVisual(valueOrIndex, getVisual, setVisual);
}
}
}