|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
|
|
* or more contributor license agreements. See the NOTICE file
|
|
|
|
|
* distributed with this work for additional information
|
|
|
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
|
|
|
* to you under the Apache License, Version 2.0 (the
|
|
|
|
|
* "License"); you may not use this file except in compliance
|
|
|
|
|
* with the License. You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing,
|
|
|
|
|
* software distributed under the License is distributed on an
|
|
|
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
|
* KIND, either express or implied. See the License for the
|
|
|
|
|
* specific language governing permissions and limitations
|
|
|
|
|
* under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AUTO-GENERATED FILE. DO NOT MODIFY.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
|
|
* or more contributor license agreements. See the NOTICE file
|
|
|
|
|
* distributed with this work for additional information
|
|
|
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
|
|
|
* to you under the Apache License, Version 2.0 (the
|
|
|
|
|
* "License"); you may not use this file except in compliance
|
|
|
|
|
* with the License. You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing,
|
|
|
|
|
* software distributed under the License is distributed on an
|
|
|
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
|
* KIND, either express or implied. See the License for the
|
|
|
|
|
* specific language governing permissions and limitations
|
|
|
|
|
* under the License.
|
|
|
|
|
*/
|
|
|
|
|
import { __extends } from "tslib";
|
|
|
|
|
import * as zrUtil from 'zrender/lib/core/util.js';
|
|
|
|
|
import visualDefault from '../../visual/visualDefault.js';
|
|
|
|
|
import VisualMapping from '../../visual/VisualMapping.js';
|
|
|
|
|
import * as visualSolution from '../../visual/visualSolution.js';
|
|
|
|
|
import * as modelUtil from '../../util/model.js';
|
|
|
|
|
import * as numberUtil from '../../util/number.js';
|
|
|
|
|
import ComponentModel from '../../model/Component.js';
|
|
|
|
|
var mapVisual = VisualMapping.mapVisual;
|
|
|
|
|
var eachVisual = VisualMapping.eachVisual;
|
|
|
|
|
var isArray = zrUtil.isArray;
|
|
|
|
|
var each = zrUtil.each;
|
|
|
|
|
var asc = numberUtil.asc;
|
|
|
|
|
var linearMap = numberUtil.linearMap;
|
|
|
|
|
var VisualMapModel = /** @class */function (_super) {
|
|
|
|
|
__extends(VisualMapModel, _super);
|
|
|
|
|
function VisualMapModel() {
|
|
|
|
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
|
|
|
_this.type = VisualMapModel.type;
|
|
|
|
|
_this.stateList = ['inRange', 'outOfRange'];
|
|
|
|
|
_this.replacableOptionKeys = ['inRange', 'outOfRange', 'target', 'controller', 'color'];
|
|
|
|
|
_this.layoutMode = {
|
|
|
|
|
type: 'box',
|
|
|
|
|
ignoreSize: true
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* [lowerBound, upperBound]
|
|
|
|
|
*/
|
|
|
|
|
_this.dataBound = [-Infinity, Infinity];
|
|
|
|
|
_this.targetVisuals = {};
|
|
|
|
|
_this.controllerVisuals = {};
|
|
|
|
|
return _this;
|
|
|
|
|
}
|
|
|
|
|
VisualMapModel.prototype.init = function (option, parentModel, ecModel) {
|
|
|
|
|
this.mergeDefaultAndTheme(option, ecModel);
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @protected
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.optionUpdated = function (newOption, isInit) {
|
|
|
|
|
var thisOption = this.option;
|
|
|
|
|
!isInit && visualSolution.replaceVisualOption(thisOption, newOption, this.replacableOptionKeys);
|
|
|
|
|
this.textStyleModel = this.getModel('textStyle');
|
|
|
|
|
this.resetItemSize();
|
|
|
|
|
this.completeVisualOption();
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @protected
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.resetVisual = function (supplementVisualOption) {
|
|
|
|
|
var stateList = this.stateList;
|
|
|
|
|
supplementVisualOption = zrUtil.bind(supplementVisualOption, this);
|
|
|
|
|
this.controllerVisuals = visualSolution.createVisualMappings(this.option.controller, stateList, supplementVisualOption);
|
|
|
|
|
this.targetVisuals = visualSolution.createVisualMappings(this.option.target, stateList, supplementVisualOption);
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @public
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.getItemSymbol = function () {
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @protected
|
|
|
|
|
* @return {Array.<number>} An array of series indices.
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.getTargetSeriesIndices = function () {
|
|
|
|
|
var optionSeriesIndex = this.option.seriesIndex;
|
|
|
|
|
var seriesIndices = [];
|
|
|
|
|
if (optionSeriesIndex == null || optionSeriesIndex === 'all') {
|
|
|
|
|
this.ecModel.eachSeries(function (seriesModel, index) {
|
|
|
|
|
seriesIndices.push(index);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
seriesIndices = modelUtil.normalizeToArray(optionSeriesIndex);
|
|
|
|
|
}
|
|
|
|
|
return seriesIndices;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @public
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.eachTargetSeries = function (callback, context) {
|
|
|
|
|
zrUtil.each(this.getTargetSeriesIndices(), function (seriesIndex) {
|
|
|
|
|
var seriesModel = this.ecModel.getSeriesByIndex(seriesIndex);
|
|
|
|
|
if (seriesModel) {
|
|
|
|
|
callback.call(context, seriesModel);
|
|
|
|
|
}
|
|
|
|
|
}, this);
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @pubilc
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.isTargetSeries = function (seriesModel) {
|
|
|
|
|
var is = false;
|
|
|
|
|
this.eachTargetSeries(function (model) {
|
|
|
|
|
model === seriesModel && (is = true);
|
|
|
|
|
});
|
|
|
|
|
return is;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @example
|
|
|
|
|
* this.formatValueText(someVal); // format single numeric value to text.
|
|
|
|
|
* this.formatValueText(someVal, true); // format single category value to text.
|
|
|
|
|
* this.formatValueText([min, max]); // format numeric min-max to text.
|
|
|
|
|
* this.formatValueText([this.dataBound[0], max]); // using data lower bound.
|
|
|
|
|
* this.formatValueText([min, this.dataBound[1]]); // using data upper bound.
|
|
|
|
|
*
|
|
|
|
|
* @param value Real value, or this.dataBound[0 or 1].
|
|
|
|
|
* @param isCategory Only available when value is number.
|
|
|
|
|
* @param edgeSymbols Open-close symbol when value is interval.
|
|
|
|
|
* @protected
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.formatValueText = function (value, isCategory, edgeSymbols) {
|
|
|
|
|
var option = this.option;
|
|
|
|
|
var precision = option.precision;
|
|
|
|
|
var dataBound = this.dataBound;
|
|
|
|
|
var formatter = option.formatter;
|
|
|
|
|
var isMinMax;
|
|
|
|
|
edgeSymbols = edgeSymbols || ['<', '>'];
|
|
|
|
|
if (zrUtil.isArray(value)) {
|
|
|
|
|
value = value.slice();
|
|
|
|
|
isMinMax = true;
|
|
|
|
|
}
|
|
|
|
|
var textValue = isCategory ? value // Value is string when isCategory
|
|
|
|
|
: isMinMax ? [toFixed(value[0]), toFixed(value[1])] : toFixed(value);
|
|
|
|
|
if (zrUtil.isString(formatter)) {
|
|
|
|
|
return formatter.replace('{value}', isMinMax ? textValue[0] : textValue).replace('{value2}', isMinMax ? textValue[1] : textValue);
|
|
|
|
|
} else if (zrUtil.isFunction(formatter)) {
|
|
|
|
|
return isMinMax ? formatter(value[0], value[1]) : formatter(value);
|
|
|
|
|
}
|
|
|
|
|
if (isMinMax) {
|
|
|
|
|
if (value[0] === dataBound[0]) {
|
|
|
|
|
return edgeSymbols[0] + ' ' + textValue[1];
|
|
|
|
|
} else if (value[1] === dataBound[1]) {
|
|
|
|
|
return edgeSymbols[1] + ' ' + textValue[0];
|
|
|
|
|
} else {
|
|
|
|
|
return textValue[0] + ' - ' + textValue[1];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Format single value (includes category case).
|
|
|
|
|
return textValue;
|
|
|
|
|
}
|
|
|
|
|
function toFixed(val) {
|
|
|
|
|
return val === dataBound[0] ? 'min' : val === dataBound[1] ? 'max' : (+val).toFixed(Math.min(precision, 20));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @protected
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.resetExtent = function () {
|
|
|
|
|
var thisOption = this.option;
|
|
|
|
|
// Can not calculate data extent by data here.
|
|
|
|
|
// Because series and data may be modified in processing stage.
|
|
|
|
|
// So we do not support the feature "auto min/max".
|
|
|
|
|
var extent = asc([thisOption.min, thisOption.max]);
|
|
|
|
|
this._dataExtent = extent;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* PENDING:
|
|
|
|
|
* delete this method if no outer usage.
|
|
|
|
|
*
|
|
|
|
|
* Return Concrete dimension. If null/undefined is returned, no dimension is used.
|
|
|
|
|
*/
|
|
|
|
|
// getDataDimension(data: SeriesData) {
|
|
|
|
|
// const optDim = this.option.dimension;
|
|
|
|
|
// if (optDim != null) {
|
|
|
|
|
// return data.getDimension(optDim);
|
|
|
|
|
// }
|
|
|
|
|
// const dimNames = data.dimensions;
|
|
|
|
|
// for (let i = dimNames.length - 1; i >= 0; i--) {
|
|
|
|
|
// const dimName = dimNames[i];
|
|
|
|
|
// const dimInfo = data.getDimensionInfo(dimName);
|
|
|
|
|
// if (!dimInfo.isCalculationCoord) {
|
|
|
|
|
// return dimName;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
VisualMapModel.prototype.getDataDimensionIndex = function (data) {
|
|
|
|
|
var optDim = this.option.dimension;
|
|
|
|
|
if (optDim != null) {
|
|
|
|
|
return data.getDimensionIndex(optDim);
|
|
|
|
|
}
|
|
|
|
|
var dimNames = data.dimensions;
|
|
|
|
|
for (var i = dimNames.length - 1; i >= 0; i--) {
|
|
|
|
|
var dimName = dimNames[i];
|
|
|
|
|
var dimInfo = data.getDimensionInfo(dimName);
|
|
|
|
|
if (!dimInfo.isCalculationCoord) {
|
|
|
|
|
return dimInfo.storeDimIndex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
VisualMapModel.prototype.getExtent = function () {
|
|
|
|
|
return this._dataExtent.slice();
|
|
|
|
|
};
|
|
|
|
|
VisualMapModel.prototype.completeVisualOption = function () {
|
|
|
|
|
var ecModel = this.ecModel;
|
|
|
|
|
var thisOption = this.option;
|
|
|
|
|
var base = {
|
|
|
|
|
inRange: thisOption.inRange,
|
|
|
|
|
outOfRange: thisOption.outOfRange
|
|
|
|
|
};
|
|
|
|
|
var target = thisOption.target || (thisOption.target = {});
|
|
|
|
|
var controller = thisOption.controller || (thisOption.controller = {});
|
|
|
|
|
zrUtil.merge(target, base); // Do not override
|
|
|
|
|
zrUtil.merge(controller, base); // Do not override
|
|
|
|
|
var isCategory = this.isCategory();
|
|
|
|
|
completeSingle.call(this, target);
|
|
|
|
|
completeSingle.call(this, controller);
|
|
|
|
|
completeInactive.call(this, target, 'inRange', 'outOfRange');
|
|
|
|
|
// completeInactive.call(this, target, 'outOfRange', 'inRange');
|
|
|
|
|
completeController.call(this, controller);
|
|
|
|
|
function completeSingle(base) {
|
|
|
|
|
// Compatible with ec2 dataRange.color.
|
|
|
|
|
// The mapping order of dataRange.color is: [high value, ..., low value]
|
|
|
|
|
// whereas inRange.color and outOfRange.color is [low value, ..., high value]
|
|
|
|
|
// Notice: ec2 has no inverse.
|
|
|
|
|
if (isArray(thisOption.color)
|
|
|
|
|
// If there has been inRange: {symbol: ...}, adding color is a mistake.
|
|
|
|
|
// So adding color only when no inRange defined.
|
|
|
|
|
&& !base.inRange) {
|
|
|
|
|
base.inRange = {
|
|
|
|
|
color: thisOption.color.slice().reverse()
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// Compatible with previous logic, always give a default color, otherwise
|
|
|
|
|
// simple config with no inRange and outOfRange will not work.
|
|
|
|
|
// Originally we use visualMap.color as the default color, but setOption at
|
|
|
|
|
// the second time the default color will be erased. So we change to use
|
|
|
|
|
// constant DEFAULT_COLOR.
|
|
|
|
|
// If user do not want the default color, set inRange: {color: null}.
|
|
|
|
|
base.inRange = base.inRange || {
|
|
|
|
|
color: ecModel.get('gradientColor')
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
function completeInactive(base, stateExist, stateAbsent) {
|
|
|
|
|
var optExist = base[stateExist];
|
|
|
|
|
var optAbsent = base[stateAbsent];
|
|
|
|
|
if (optExist && !optAbsent) {
|
|
|
|
|
optAbsent = base[stateAbsent] = {};
|
|
|
|
|
each(optExist, function (visualData, visualType) {
|
|
|
|
|
if (!VisualMapping.isValidType(visualType)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var defa = visualDefault.get(visualType, 'inactive', isCategory);
|
|
|
|
|
if (defa != null) {
|
|
|
|
|
optAbsent[visualType] = defa;
|
|
|
|
|
// Compatibable with ec2:
|
|
|
|
|
// Only inactive color to rgba(0,0,0,0) can not
|
|
|
|
|
// make label transparent, so use opacity also.
|
|
|
|
|
if (visualType === 'color' && !optAbsent.hasOwnProperty('opacity') && !optAbsent.hasOwnProperty('colorAlpha')) {
|
|
|
|
|
optAbsent.opacity = [0, 0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function completeController(controller) {
|
|
|
|
|
var symbolExists = (controller.inRange || {}).symbol || (controller.outOfRange || {}).symbol;
|
|
|
|
|
var symbolSizeExists = (controller.inRange || {}).symbolSize || (controller.outOfRange || {}).symbolSize;
|
|
|
|
|
var inactiveColor = this.get('inactiveColor');
|
|
|
|
|
var itemSymbol = this.getItemSymbol();
|
|
|
|
|
var defaultSymbol = itemSymbol || 'roundRect';
|
|
|
|
|
each(this.stateList, function (state) {
|
|
|
|
|
var itemSize = this.itemSize;
|
|
|
|
|
var visuals = controller[state];
|
|
|
|
|
// Set inactive color for controller if no other color
|
|
|
|
|
// attr (like colorAlpha) specified.
|
|
|
|
|
if (!visuals) {
|
|
|
|
|
visuals = controller[state] = {
|
|
|
|
|
color: isCategory ? inactiveColor : [inactiveColor]
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
// Consistent symbol and symbolSize if not specified.
|
|
|
|
|
if (visuals.symbol == null) {
|
|
|
|
|
visuals.symbol = symbolExists && zrUtil.clone(symbolExists) || (isCategory ? defaultSymbol : [defaultSymbol]);
|
|
|
|
|
}
|
|
|
|
|
if (visuals.symbolSize == null) {
|
|
|
|
|
visuals.symbolSize = symbolSizeExists && zrUtil.clone(symbolSizeExists) || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]);
|
|
|
|
|
}
|
|
|
|
|
// Filter none
|
|
|
|
|
visuals.symbol = mapVisual(visuals.symbol, function (symbol) {
|
|
|
|
|
return symbol === 'none' ? defaultSymbol : symbol;
|
|
|
|
|
});
|
|
|
|
|
// Normalize symbolSize
|
|
|
|
|
var symbolSize = visuals.symbolSize;
|
|
|
|
|
if (symbolSize != null) {
|
|
|
|
|
var max_1 = -Infinity;
|
|
|
|
|
// symbolSize can be object when categories defined.
|
|
|
|
|
eachVisual(symbolSize, function (value) {
|
|
|
|
|
value > max_1 && (max_1 = value);
|
|
|
|
|
});
|
|
|
|
|
visuals.symbolSize = mapVisual(symbolSize, function (value) {
|
|
|
|
|
return linearMap(value, [0, max_1], [0, itemSize[0]], true);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}, this);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
VisualMapModel.prototype.resetItemSize = function () {
|
|
|
|
|
this.itemSize = [parseFloat(this.get('itemWidth')), parseFloat(this.get('itemHeight'))];
|
|
|
|
|
};
|
|
|
|
|
VisualMapModel.prototype.isCategory = function () {
|
|
|
|
|
return !!this.option.categories;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @public
|
|
|
|
|
* @abstract
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.setSelected = function (selected) {};
|
|
|
|
|
VisualMapModel.prototype.getSelected = function () {
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* @public
|
|
|
|
|
* @abstract
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.getValueState = function (value) {
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* FIXME
|
|
|
|
|
* Do not publish to thirt-part-dev temporarily
|
|
|
|
|
* util the interface is stable. (Should it return
|
|
|
|
|
* a function but not visual meta?)
|
|
|
|
|
*
|
|
|
|
|
* @pubilc
|
|
|
|
|
* @abstract
|
|
|
|
|
* @param getColorVisual
|
|
|
|
|
* params: value, valueState
|
|
|
|
|
* return: color
|
|
|
|
|
* @return {Object} visualMeta
|
|
|
|
|
* should includes {stops, outerColors}
|
|
|
|
|
* outerColor means [colorBeyondMinValue, colorBeyondMaxValue]
|
|
|
|
|
*/
|
|
|
|
|
VisualMapModel.prototype.getVisualMeta = function (getColorVisual) {
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
VisualMapModel.type = 'visualMap';
|
|
|
|
|
VisualMapModel.dependencies = ['series'];
|
|
|
|
|
VisualMapModel.defaultOption = {
|
|
|
|
|
show: true,
|
|
|
|
|
// zlevel: 0,
|
|
|
|
|
z: 4,
|
|
|
|
|
seriesIndex: 'all',
|
|
|
|
|
min: 0,
|
|
|
|
|
max: 200,
|
|
|
|
|
left: 0,
|
|
|
|
|
right: null,
|
|
|
|
|
top: null,
|
|
|
|
|
bottom: 0,
|
|
|
|
|
itemWidth: null,
|
|
|
|
|
itemHeight: null,
|
|
|
|
|
inverse: false,
|
|
|
|
|
orient: 'vertical',
|
|
|
|
|
backgroundColor: 'rgba(0,0,0,0)',
|
|
|
|
|
borderColor: '#ccc',
|
|
|
|
|
contentColor: '#5793f3',
|
|
|
|
|
inactiveColor: '#aaa',
|
|
|
|
|
borderWidth: 0,
|
|
|
|
|
padding: 5,
|
|
|
|
|
// 接受数组分别设定上右下左边距,同css
|
|
|
|
|
textGap: 10,
|
|
|
|
|
precision: 0,
|
|
|
|
|
textStyle: {
|
|
|
|
|
color: '#333' // 值域文字颜色
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return VisualMapModel;
|
|
|
|
|
}(ComponentModel);
|
|
|
|
|
export default VisualMapModel;
|