484 lines
19 KiB
JavaScript
484 lines
19 KiB
JavaScript
|
|
/*
|
|
* 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 ZRText from 'zrender/lib/graphic/Text.js';
|
|
import { isFunction, retrieve2, extend, keys, trim } from 'zrender/lib/core/util.js';
|
|
import { SPECIAL_STATES, DISPLAY_STATES } from '../util/states.js';
|
|
import { deprecateReplaceLog } from '../util/log.js';
|
|
import { makeInner, interpolateRawValues } from '../util/model.js';
|
|
import { initProps, updateProps } from '../util/graphic.js';
|
|
var EMPTY_OBJ = {};
|
|
export function setLabelText(label, labelTexts) {
|
|
for (var i = 0; i < SPECIAL_STATES.length; i++) {
|
|
var stateName = SPECIAL_STATES[i];
|
|
var text = labelTexts[stateName];
|
|
var state = label.ensureState(stateName);
|
|
state.style = state.style || {};
|
|
state.style.text = text;
|
|
}
|
|
var oldStates = label.currentStates.slice();
|
|
label.clearStates(true);
|
|
label.setStyle({
|
|
text: labelTexts.normal
|
|
});
|
|
label.useStates(oldStates, true);
|
|
}
|
|
function getLabelText(opt, stateModels, interpolatedValue) {
|
|
var labelFetcher = opt.labelFetcher;
|
|
var labelDataIndex = opt.labelDataIndex;
|
|
var labelDimIndex = opt.labelDimIndex;
|
|
var normalModel = stateModels.normal;
|
|
var baseText;
|
|
if (labelFetcher) {
|
|
baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, normalModel && normalModel.get('formatter'), interpolatedValue != null ? {
|
|
interpolatedValue: interpolatedValue
|
|
} : null);
|
|
}
|
|
if (baseText == null) {
|
|
baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt, interpolatedValue) : opt.defaultText;
|
|
}
|
|
var statesText = {
|
|
normal: baseText
|
|
};
|
|
for (var i = 0; i < SPECIAL_STATES.length; i++) {
|
|
var stateName = SPECIAL_STATES[i];
|
|
var stateModel = stateModels[stateName];
|
|
statesText[stateName] = retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, stateName, null, labelDimIndex, stateModel && stateModel.get('formatter')) : null, baseText);
|
|
}
|
|
return statesText;
|
|
}
|
|
function setLabelStyle(targetEl, labelStatesModels, opt, stateSpecified
|
|
// TODO specified position?
|
|
) {
|
|
opt = opt || EMPTY_OBJ;
|
|
var isSetOnText = targetEl instanceof ZRText;
|
|
var needsCreateText = false;
|
|
for (var i = 0; i < DISPLAY_STATES.length; i++) {
|
|
var stateModel = labelStatesModels[DISPLAY_STATES[i]];
|
|
if (stateModel && stateModel.getShallow('show')) {
|
|
needsCreateText = true;
|
|
break;
|
|
}
|
|
}
|
|
var textContent = isSetOnText ? targetEl : targetEl.getTextContent();
|
|
if (needsCreateText) {
|
|
if (!isSetOnText) {
|
|
// Reuse the previous
|
|
if (!textContent) {
|
|
textContent = new ZRText();
|
|
targetEl.setTextContent(textContent);
|
|
}
|
|
// Use same state proxy
|
|
if (targetEl.stateProxy) {
|
|
textContent.stateProxy = targetEl.stateProxy;
|
|
}
|
|
}
|
|
var labelStatesTexts = getLabelText(opt, labelStatesModels);
|
|
var normalModel = labelStatesModels.normal;
|
|
var showNormal = !!normalModel.getShallow('show');
|
|
var normalStyle = createTextStyle(normalModel, stateSpecified && stateSpecified.normal, opt, false, !isSetOnText);
|
|
normalStyle.text = labelStatesTexts.normal;
|
|
if (!isSetOnText) {
|
|
// Always create new
|
|
targetEl.setTextConfig(createTextConfig(normalModel, opt, false));
|
|
}
|
|
for (var i = 0; i < SPECIAL_STATES.length; i++) {
|
|
var stateName = SPECIAL_STATES[i];
|
|
var stateModel = labelStatesModels[stateName];
|
|
if (stateModel) {
|
|
var stateObj = textContent.ensureState(stateName);
|
|
var stateShow = !!retrieve2(stateModel.getShallow('show'), showNormal);
|
|
if (stateShow !== showNormal) {
|
|
stateObj.ignore = !stateShow;
|
|
}
|
|
stateObj.style = createTextStyle(stateModel, stateSpecified && stateSpecified[stateName], opt, true, !isSetOnText);
|
|
stateObj.style.text = labelStatesTexts[stateName];
|
|
if (!isSetOnText) {
|
|
var targetElEmphasisState = targetEl.ensureState(stateName);
|
|
targetElEmphasisState.textConfig = createTextConfig(stateModel, opt, true);
|
|
}
|
|
}
|
|
}
|
|
// PENDING: if there is many requirements that emphasis position
|
|
// need to be different from normal position, we might consider
|
|
// auto silent is those cases.
|
|
textContent.silent = !!normalModel.getShallow('silent');
|
|
// Keep x and y
|
|
if (textContent.style.x != null) {
|
|
normalStyle.x = textContent.style.x;
|
|
}
|
|
if (textContent.style.y != null) {
|
|
normalStyle.y = textContent.style.y;
|
|
}
|
|
textContent.ignore = !showNormal;
|
|
// Always create new style.
|
|
textContent.useStyle(normalStyle);
|
|
textContent.dirty();
|
|
if (opt.enableTextSetter) {
|
|
labelInner(textContent).setLabelText = function (interpolatedValue) {
|
|
var labelStatesTexts = getLabelText(opt, labelStatesModels, interpolatedValue);
|
|
setLabelText(textContent, labelStatesTexts);
|
|
};
|
|
}
|
|
} else if (textContent) {
|
|
// Not display rich text.
|
|
textContent.ignore = true;
|
|
}
|
|
targetEl.dirty();
|
|
}
|
|
export { setLabelStyle };
|
|
export function getLabelStatesModels(itemModel, labelName) {
|
|
labelName = labelName || 'label';
|
|
var statesModels = {
|
|
normal: itemModel.getModel(labelName)
|
|
};
|
|
for (var i = 0; i < SPECIAL_STATES.length; i++) {
|
|
var stateName = SPECIAL_STATES[i];
|
|
statesModels[stateName] = itemModel.getModel([stateName, labelName]);
|
|
}
|
|
return statesModels;
|
|
}
|
|
/**
|
|
* Set basic textStyle properties.
|
|
*/
|
|
export function createTextStyle(textStyleModel, specifiedTextStyle,
|
|
// Fixed style in the code. Can't be set by model.
|
|
opt, isNotNormal, isAttached // If text is attached on an element. If so, auto color will handling in zrender.
|
|
) {
|
|
var textStyle = {};
|
|
setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached);
|
|
specifiedTextStyle && extend(textStyle, specifiedTextStyle);
|
|
// textStyle.host && textStyle.host.dirty && textStyle.host.dirty(false);
|
|
return textStyle;
|
|
}
|
|
export function createTextConfig(textStyleModel, opt, isNotNormal) {
|
|
opt = opt || {};
|
|
var textConfig = {};
|
|
var labelPosition;
|
|
var labelRotate = textStyleModel.getShallow('rotate');
|
|
var labelDistance = retrieve2(textStyleModel.getShallow('distance'), isNotNormal ? null : 5);
|
|
var labelOffset = textStyleModel.getShallow('offset');
|
|
labelPosition = textStyleModel.getShallow('position') || (isNotNormal ? null : 'inside');
|
|
// 'outside' is not a valid zr textPostion value, but used
|
|
// in bar series, and magric type should be considered.
|
|
labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top');
|
|
if (labelPosition != null) {
|
|
textConfig.position = labelPosition;
|
|
}
|
|
if (labelOffset != null) {
|
|
textConfig.offset = labelOffset;
|
|
}
|
|
if (labelRotate != null) {
|
|
labelRotate *= Math.PI / 180;
|
|
textConfig.rotation = labelRotate;
|
|
}
|
|
if (labelDistance != null) {
|
|
textConfig.distance = labelDistance;
|
|
}
|
|
// fill and auto is determined by the color of path fill if it's not specified by developers.
|
|
textConfig.outsideFill = textStyleModel.get('color') === 'inherit' ? opt.inheritColor || null : 'auto';
|
|
return textConfig;
|
|
}
|
|
/**
|
|
* The uniform entry of set text style, that is, retrieve style definitions
|
|
* from `model` and set to `textStyle` object.
|
|
*
|
|
* Never in merge mode, but in overwrite mode, that is, all of the text style
|
|
* properties will be set. (Consider the states of normal and emphasis and
|
|
* default value can be adopted, merge would make the logic too complicated
|
|
* to manage.)
|
|
*/
|
|
function setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached) {
|
|
// Consider there will be abnormal when merge hover style to normal style if given default value.
|
|
opt = opt || EMPTY_OBJ;
|
|
var ecModel = textStyleModel.ecModel;
|
|
var globalTextStyle = ecModel && ecModel.option.textStyle;
|
|
// Consider case:
|
|
// {
|
|
// data: [{
|
|
// value: 12,
|
|
// label: {
|
|
// rich: {
|
|
// // no 'a' here but using parent 'a'.
|
|
// }
|
|
// }
|
|
// }],
|
|
// rich: {
|
|
// a: { ... }
|
|
// }
|
|
// }
|
|
var richItemNames = getRichItemNames(textStyleModel);
|
|
var richResult;
|
|
if (richItemNames) {
|
|
richResult = {};
|
|
for (var name_1 in richItemNames) {
|
|
if (richItemNames.hasOwnProperty(name_1)) {
|
|
// Cascade is supported in rich.
|
|
var richTextStyle = textStyleModel.getModel(['rich', name_1]);
|
|
// In rich, never `disableBox`.
|
|
// FIXME: consider `label: {formatter: '{a|xx}', color: 'blue', rich: {a: {}}}`,
|
|
// the default color `'blue'` will not be adopted if no color declared in `rich`.
|
|
// That might confuses users. So probably we should put `textStyleModel` as the
|
|
// root ancestor of the `richTextStyle`. But that would be a break change.
|
|
setTokenTextStyle(richResult[name_1] = {}, richTextStyle, globalTextStyle, opt, isNotNormal, isAttached, false, true);
|
|
}
|
|
}
|
|
}
|
|
if (richResult) {
|
|
textStyle.rich = richResult;
|
|
}
|
|
var overflow = textStyleModel.get('overflow');
|
|
if (overflow) {
|
|
textStyle.overflow = overflow;
|
|
}
|
|
var margin = textStyleModel.get('minMargin');
|
|
if (margin != null) {
|
|
textStyle.margin = margin;
|
|
}
|
|
setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, true, false);
|
|
}
|
|
// Consider case:
|
|
// {
|
|
// data: [{
|
|
// value: 12,
|
|
// label: {
|
|
// rich: {
|
|
// // no 'a' here but using parent 'a'.
|
|
// }
|
|
// }
|
|
// }],
|
|
// rich: {
|
|
// a: { ... }
|
|
// }
|
|
// }
|
|
// TODO TextStyleModel
|
|
function getRichItemNames(textStyleModel) {
|
|
// Use object to remove duplicated names.
|
|
var richItemNameMap;
|
|
while (textStyleModel && textStyleModel !== textStyleModel.ecModel) {
|
|
var rich = (textStyleModel.option || EMPTY_OBJ).rich;
|
|
if (rich) {
|
|
richItemNameMap = richItemNameMap || {};
|
|
var richKeys = keys(rich);
|
|
for (var i = 0; i < richKeys.length; i++) {
|
|
var richKey = richKeys[i];
|
|
richItemNameMap[richKey] = 1;
|
|
}
|
|
}
|
|
textStyleModel = textStyleModel.parentModel;
|
|
}
|
|
return richItemNameMap;
|
|
}
|
|
var TEXT_PROPS_WITH_GLOBAL = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY'];
|
|
var TEXT_PROPS_SELF = ['align', 'lineHeight', 'width', 'height', 'tag', 'verticalAlign', 'ellipsis'];
|
|
var TEXT_PROPS_BOX = ['padding', 'borderWidth', 'borderRadius', 'borderDashOffset', 'backgroundColor', 'borderColor', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'];
|
|
function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, isBlock, inRich) {
|
|
// In merge mode, default value should not be given.
|
|
globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ;
|
|
var inheritColor = opt && opt.inheritColor;
|
|
var fillColor = textStyleModel.getShallow('color');
|
|
var strokeColor = textStyleModel.getShallow('textBorderColor');
|
|
var opacity = retrieve2(textStyleModel.getShallow('opacity'), globalTextStyle.opacity);
|
|
if (fillColor === 'inherit' || fillColor === 'auto') {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
if (fillColor === 'auto') {
|
|
deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\'');
|
|
}
|
|
}
|
|
if (inheritColor) {
|
|
fillColor = inheritColor;
|
|
} else {
|
|
fillColor = null;
|
|
}
|
|
}
|
|
if (strokeColor === 'inherit' || strokeColor === 'auto') {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
if (strokeColor === 'auto') {
|
|
deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\'');
|
|
}
|
|
}
|
|
if (inheritColor) {
|
|
strokeColor = inheritColor;
|
|
} else {
|
|
strokeColor = null;
|
|
}
|
|
}
|
|
if (!isAttached) {
|
|
// Only use default global textStyle.color if text is individual.
|
|
// Otherwise it will use the strategy of attached text color because text may be on a path.
|
|
fillColor = fillColor || globalTextStyle.color;
|
|
strokeColor = strokeColor || globalTextStyle.textBorderColor;
|
|
}
|
|
if (fillColor != null) {
|
|
textStyle.fill = fillColor;
|
|
}
|
|
if (strokeColor != null) {
|
|
textStyle.stroke = strokeColor;
|
|
}
|
|
var textBorderWidth = retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth);
|
|
if (textBorderWidth != null) {
|
|
textStyle.lineWidth = textBorderWidth;
|
|
}
|
|
var textBorderType = retrieve2(textStyleModel.getShallow('textBorderType'), globalTextStyle.textBorderType);
|
|
if (textBorderType != null) {
|
|
textStyle.lineDash = textBorderType;
|
|
}
|
|
var textBorderDashOffset = retrieve2(textStyleModel.getShallow('textBorderDashOffset'), globalTextStyle.textBorderDashOffset);
|
|
if (textBorderDashOffset != null) {
|
|
textStyle.lineDashOffset = textBorderDashOffset;
|
|
}
|
|
if (!isNotNormal && opacity == null && !inRich) {
|
|
opacity = opt && opt.defaultOpacity;
|
|
}
|
|
if (opacity != null) {
|
|
textStyle.opacity = opacity;
|
|
}
|
|
// TODO
|
|
if (!isNotNormal && !isAttached) {
|
|
// Set default finally.
|
|
if (textStyle.fill == null && opt.inheritColor) {
|
|
textStyle.fill = opt.inheritColor;
|
|
}
|
|
}
|
|
// Do not use `getFont` here, because merge should be supported, where
|
|
// part of these properties may be changed in emphasis style, and the
|
|
// others should remain their original value got from normal style.
|
|
for (var i = 0; i < TEXT_PROPS_WITH_GLOBAL.length; i++) {
|
|
var key = TEXT_PROPS_WITH_GLOBAL[i];
|
|
var val = retrieve2(textStyleModel.getShallow(key), globalTextStyle[key]);
|
|
if (val != null) {
|
|
textStyle[key] = val;
|
|
}
|
|
}
|
|
for (var i = 0; i < TEXT_PROPS_SELF.length; i++) {
|
|
var key = TEXT_PROPS_SELF[i];
|
|
var val = textStyleModel.getShallow(key);
|
|
if (val != null) {
|
|
textStyle[key] = val;
|
|
}
|
|
}
|
|
if (textStyle.verticalAlign == null) {
|
|
var baseline = textStyleModel.getShallow('baseline');
|
|
if (baseline != null) {
|
|
textStyle.verticalAlign = baseline;
|
|
}
|
|
}
|
|
if (!isBlock || !opt.disableBox) {
|
|
for (var i = 0; i < TEXT_PROPS_BOX.length; i++) {
|
|
var key = TEXT_PROPS_BOX[i];
|
|
var val = textStyleModel.getShallow(key);
|
|
if (val != null) {
|
|
textStyle[key] = val;
|
|
}
|
|
}
|
|
var borderType = textStyleModel.getShallow('borderType');
|
|
if (borderType != null) {
|
|
textStyle.borderDash = borderType;
|
|
}
|
|
if ((textStyle.backgroundColor === 'auto' || textStyle.backgroundColor === 'inherit') && inheritColor) {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
if (textStyle.backgroundColor === 'auto') {
|
|
deprecateReplaceLog('backgroundColor: \'auto\'', 'backgroundColor: \'inherit\'');
|
|
}
|
|
}
|
|
textStyle.backgroundColor = inheritColor;
|
|
}
|
|
if ((textStyle.borderColor === 'auto' || textStyle.borderColor === 'inherit') && inheritColor) {
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
if (textStyle.borderColor === 'auto') {
|
|
deprecateReplaceLog('borderColor: \'auto\'', 'borderColor: \'inherit\'');
|
|
}
|
|
}
|
|
textStyle.borderColor = inheritColor;
|
|
}
|
|
}
|
|
}
|
|
export function getFont(opt, ecModel) {
|
|
var gTextStyleModel = ecModel && ecModel.getModel('textStyle');
|
|
return trim([
|
|
// FIXME in node-canvas fontWeight is before fontStyle
|
|
opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' '));
|
|
}
|
|
export var labelInner = makeInner();
|
|
export function setLabelValueAnimation(label, labelStatesModels, value, getDefaultText) {
|
|
if (!label) {
|
|
return;
|
|
}
|
|
var obj = labelInner(label);
|
|
obj.prevValue = obj.value;
|
|
obj.value = value;
|
|
var normalLabelModel = labelStatesModels.normal;
|
|
obj.valueAnimation = normalLabelModel.get('valueAnimation');
|
|
if (obj.valueAnimation) {
|
|
obj.precision = normalLabelModel.get('precision');
|
|
obj.defaultInterpolatedText = getDefaultText;
|
|
obj.statesModels = labelStatesModels;
|
|
}
|
|
}
|
|
export function animateLabelValue(textEl, dataIndex, data, animatableModel, labelFetcher) {
|
|
var labelInnerStore = labelInner(textEl);
|
|
if (!labelInnerStore.valueAnimation || labelInnerStore.prevValue === labelInnerStore.value) {
|
|
// Value not changed, no new label animation
|
|
return;
|
|
}
|
|
var defaultInterpolatedText = labelInnerStore.defaultInterpolatedText;
|
|
// Consider the case that being animating, do not use the `obj.value`,
|
|
// Otherwise it will jump to the `obj.value` when this new animation started.
|
|
var currValue = retrieve2(labelInnerStore.interpolatedValue, labelInnerStore.prevValue);
|
|
var targetValue = labelInnerStore.value;
|
|
function during(percent) {
|
|
var interpolated = interpolateRawValues(data, labelInnerStore.precision, currValue, targetValue, percent);
|
|
labelInnerStore.interpolatedValue = percent === 1 ? null : interpolated;
|
|
var labelText = getLabelText({
|
|
labelDataIndex: dataIndex,
|
|
labelFetcher: labelFetcher,
|
|
defaultText: defaultInterpolatedText ? defaultInterpolatedText(interpolated) : interpolated + ''
|
|
}, labelInnerStore.statesModels, interpolated);
|
|
setLabelText(textEl, labelText);
|
|
}
|
|
textEl.percent = 0;
|
|
(labelInnerStore.prevValue == null ? initProps : updateProps)(textEl, {
|
|
// percent is used to prevent animation from being aborted #15916
|
|
percent: 1
|
|
}, animatableModel, dataIndex, null, during);
|
|
} |