Spaces:
Running
Running
/* | |
* 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 PointerPath from './PointerPath'; | |
import * as graphic from '../../util/graphic'; | |
import { setStatesStylesFromModel, toggleHoverEmphasis } from '../../util/states'; | |
import {createTextStyle, setLabelValueAnimation, animateLabelValue} from '../../label/labelStyle'; | |
import ChartView from '../../view/Chart'; | |
import {parsePercent, round, linearMap} from '../../util/number'; | |
import GaugeSeriesModel, { GaugeDataItemOption } from './GaugeSeries'; | |
import GlobalModel from '../../model/Global'; | |
import ExtensionAPI from '../../core/ExtensionAPI'; | |
import { ColorString, ECElement } from '../../util/types'; | |
import SeriesData from '../../data/SeriesData'; | |
import Sausage from '../../util/shape/sausage'; | |
import {createSymbol} from '../../util/symbol'; | |
import ZRImage from 'zrender/src/graphic/Image'; | |
import { extend, isFunction, isString, isNumber, each } from 'zrender/src/core/util'; | |
import {setCommonECData} from '../../util/innerStore'; | |
import { normalizeArcAngles } from 'zrender/src/core/PathProxy'; | |
type ECSymbol = ReturnType<typeof createSymbol>; | |
interface PosInfo { | |
cx: number | |
cy: number | |
r: number | |
} | |
function parsePosition(seriesModel: GaugeSeriesModel, api: ExtensionAPI): PosInfo { | |
const center = seriesModel.get('center'); | |
const width = api.getWidth(); | |
const height = api.getHeight(); | |
const size = Math.min(width, height); | |
const cx = parsePercent(center[0], api.getWidth()); | |
const cy = parsePercent(center[1], api.getHeight()); | |
const r = parsePercent(seriesModel.get('radius'), size / 2); | |
return { | |
cx: cx, | |
cy: cy, | |
r: r | |
}; | |
} | |
function formatLabel(value: number, labelFormatter: string | ((value: number) => string)): string { | |
let label = value == null ? '' : (value + ''); | |
if (labelFormatter) { | |
if (isString(labelFormatter)) { | |
label = labelFormatter.replace('{value}', label); | |
} | |
else if (isFunction(labelFormatter)) { | |
label = labelFormatter(value); | |
} | |
} | |
return label; | |
} | |
class GaugeView extends ChartView { | |
static type = 'gauge' as const; | |
type = GaugeView.type; | |
private _data: SeriesData; | |
private _progressEls: graphic.Path[]; | |
private _titleEls: graphic.Text[]; | |
private _detailEls: graphic.Text[]; | |
render(seriesModel: GaugeSeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { | |
this.group.removeAll(); | |
const colorList = seriesModel.get(['axisLine', 'lineStyle', 'color']); | |
const posInfo = parsePosition(seriesModel, api); | |
this._renderMain( | |
seriesModel, ecModel, api, colorList, posInfo | |
); | |
this._data = seriesModel.getData(); | |
} | |
dispose() {} | |
_renderMain( | |
seriesModel: GaugeSeriesModel, | |
ecModel: GlobalModel, | |
api: ExtensionAPI, | |
colorList: [number, ColorString][], | |
posInfo: PosInfo | |
) { | |
const group = this.group; | |
const clockwise = seriesModel.get('clockwise'); | |
let startAngle = -seriesModel.get('startAngle') / 180 * Math.PI; | |
let endAngle = -seriesModel.get('endAngle') / 180 * Math.PI; | |
const axisLineModel = seriesModel.getModel('axisLine'); | |
const roundCap = axisLineModel.get('roundCap'); | |
const MainPath = roundCap ? Sausage : graphic.Sector; | |
const showAxis = axisLineModel.get('show'); | |
const lineStyleModel = axisLineModel.getModel('lineStyle'); | |
const axisLineWidth = lineStyleModel.get('width'); | |
const angles = [startAngle, endAngle]; | |
normalizeArcAngles(angles, !clockwise); | |
startAngle = angles[0]; | |
endAngle = angles[1]; | |
const angleRangeSpan = endAngle - startAngle; | |
let prevEndAngle = startAngle; | |
const sectors: (Sausage | graphic.Sector)[] = []; | |
for (let i = 0; showAxis && i < colorList.length; i++) { | |
// Clamp | |
const percent = Math.min(Math.max(colorList[i][0], 0), 1); | |
endAngle = startAngle + angleRangeSpan * percent; | |
const sector = new MainPath({ | |
shape: { | |
startAngle: prevEndAngle, | |
endAngle: endAngle, | |
cx: posInfo.cx, | |
cy: posInfo.cy, | |
clockwise: clockwise, | |
r0: posInfo.r - axisLineWidth, | |
r: posInfo.r | |
}, | |
silent: true | |
}); | |
sector.setStyle({ | |
fill: colorList[i][1] | |
}); | |
sector.setStyle(lineStyleModel.getLineStyle( | |
// Because we use sector to simulate arc | |
// so the properties for stroking are useless | |
['color', 'width'] | |
)); | |
sectors.push(sector); | |
prevEndAngle = endAngle; | |
} | |
sectors.reverse(); | |
each(sectors, sector => group.add(sector)); | |
const getColor = function (percent: number) { | |
// Less than 0 | |
if (percent <= 0) { | |
return colorList[0][1]; | |
} | |
let i; | |
for (i = 0; i < colorList.length; i++) { | |
if (colorList[i][0] >= percent | |
&& (i === 0 ? 0 : colorList[i - 1][0]) < percent | |
) { | |
return colorList[i][1]; | |
} | |
} | |
// More than 1 | |
return colorList[i - 1][1]; | |
}; | |
this._renderTicks( | |
seriesModel, ecModel, api, getColor, posInfo, | |
startAngle, endAngle, clockwise, axisLineWidth | |
); | |
this._renderTitleAndDetail( | |
seriesModel, ecModel, api, getColor, posInfo | |
); | |
this._renderAnchor(seriesModel, posInfo); | |
this._renderPointer( | |
seriesModel, ecModel, api, getColor, posInfo, | |
startAngle, endAngle, clockwise, axisLineWidth | |
); | |
} | |
_renderTicks( | |
seriesModel: GaugeSeriesModel, | |
ecModel: GlobalModel, | |
api: ExtensionAPI, | |
getColor: (percent: number) => ColorString, | |
posInfo: PosInfo, | |
startAngle: number, | |
endAngle: number, | |
clockwise: boolean, | |
axisLineWidth: number | |
) { | |
const group = this.group; | |
const cx = posInfo.cx; | |
const cy = posInfo.cy; | |
const r = posInfo.r; | |
const minVal = +seriesModel.get('min'); | |
const maxVal = +seriesModel.get('max'); | |
const splitLineModel = seriesModel.getModel('splitLine'); | |
const tickModel = seriesModel.getModel('axisTick'); | |
const labelModel = seriesModel.getModel('axisLabel'); | |
const splitNumber = seriesModel.get('splitNumber'); | |
const subSplitNumber = tickModel.get('splitNumber'); | |
const splitLineLen = parsePercent( | |
splitLineModel.get('length'), r | |
); | |
const tickLen = parsePercent( | |
tickModel.get('length'), r | |
); | |
let angle = startAngle; | |
const step = (endAngle - startAngle) / splitNumber; | |
const subStep = step / subSplitNumber; | |
const splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle(); | |
const tickLineStyle = tickModel.getModel('lineStyle').getLineStyle(); | |
const splitLineDistance = splitLineModel.get('distance'); | |
let unitX; | |
let unitY; | |
for (let i = 0; i <= splitNumber; i++) { | |
unitX = Math.cos(angle); | |
unitY = Math.sin(angle); | |
// Split line | |
if (splitLineModel.get('show')) { | |
const distance = splitLineDistance ? splitLineDistance + axisLineWidth : axisLineWidth; | |
const splitLine = new graphic.Line({ | |
shape: { | |
x1: unitX * (r - distance) + cx, | |
y1: unitY * (r - distance) + cy, | |
x2: unitX * (r - splitLineLen - distance) + cx, | |
y2: unitY * (r - splitLineLen - distance) + cy | |
}, | |
style: splitLineStyle, | |
silent: true | |
}); | |
if (splitLineStyle.stroke === 'auto') { | |
splitLine.setStyle({ | |
stroke: getColor(i / splitNumber) | |
}); | |
} | |
group.add(splitLine); | |
} | |
// Label | |
if (labelModel.get('show')) { | |
const distance = labelModel.get('distance') + splitLineDistance; | |
const label = formatLabel( | |
round(i / splitNumber * (maxVal - minVal) + minVal), | |
labelModel.get('formatter') | |
); | |
const autoColor = getColor(i / splitNumber); | |
const textStyleX = unitX * (r - splitLineLen - distance) + cx; | |
const textStyleY = unitY * (r - splitLineLen - distance) + cy; | |
const rotateType = labelModel.get('rotate'); | |
let rotate = 0; | |
if (rotateType === 'radial') { | |
rotate = -angle + 2 * Math.PI; | |
if (rotate > Math.PI / 2) { | |
rotate += Math.PI; | |
} | |
} | |
else if (rotateType === 'tangential') { | |
rotate = -angle - Math.PI / 2; | |
} | |
else if (isNumber(rotateType)) { | |
rotate = rotateType * Math.PI / 180; | |
} | |
if (rotate === 0) { | |
group.add(new graphic.Text({ | |
style: createTextStyle(labelModel, { | |
text: label, | |
x: textStyleX, | |
y: textStyleY, | |
verticalAlign: unitY < -0.8 ? 'top' : (unitY > 0.8 ? 'bottom' : 'middle'), | |
align: unitX < -0.4 ? 'left' : (unitX > 0.4 ? 'right' : 'center') | |
}, { | |
inheritColor: autoColor | |
}), | |
silent: true | |
})); | |
} | |
else { | |
group.add(new graphic.Text({ | |
style: createTextStyle(labelModel, { | |
text: label, | |
x: textStyleX, | |
y: textStyleY, | |
verticalAlign: 'middle', | |
align: 'center' | |
}, { | |
inheritColor: autoColor | |
}), | |
silent: true, | |
originX: textStyleX, | |
originY: textStyleY, | |
rotation: rotate | |
})); | |
} | |
} | |
// Axis tick | |
if (tickModel.get('show') && i !== splitNumber) { | |
let distance = tickModel.get('distance'); | |
distance = distance ? distance + axisLineWidth : axisLineWidth; | |
for (let j = 0; j <= subSplitNumber; j++) { | |
unitX = Math.cos(angle); | |
unitY = Math.sin(angle); | |
const tickLine = new graphic.Line({ | |
shape: { | |
x1: unitX * (r - distance) + cx, | |
y1: unitY * (r - distance) + cy, | |
x2: unitX * (r - tickLen - distance) + cx, | |
y2: unitY * (r - tickLen - distance) + cy | |
}, | |
silent: true, | |
style: tickLineStyle | |
}); | |
if (tickLineStyle.stroke === 'auto') { | |
tickLine.setStyle({ | |
stroke: getColor((i + j / subSplitNumber) / splitNumber) | |
}); | |
} | |
group.add(tickLine); | |
angle += subStep; | |
} | |
angle -= subStep; | |
} | |
else { | |
angle += step; | |
} | |
} | |
} | |
_renderPointer( | |
seriesModel: GaugeSeriesModel, | |
ecModel: GlobalModel, | |
api: ExtensionAPI, | |
getColor: (percent: number) => ColorString, | |
posInfo: PosInfo, | |
startAngle: number, | |
endAngle: number, | |
clockwise: boolean, | |
axisLineWidth: number | |
) { | |
const group = this.group; | |
const oldData = this._data; | |
const oldProgressData = this._progressEls; | |
const progressList = [] as graphic.Path[]; | |
const showPointer = seriesModel.get(['pointer', 'show']); | |
const progressModel = seriesModel.getModel('progress'); | |
const showProgress = progressModel.get('show'); | |
const data = seriesModel.getData(); | |
const valueDim = data.mapDimension('value'); | |
const minVal = +seriesModel.get('min'); | |
const maxVal = +seriesModel.get('max'); | |
const valueExtent = [minVal, maxVal]; | |
const angleExtent = [startAngle, endAngle]; | |
function createPointer(idx: number, angle: number) { | |
const itemModel = data.getItemModel<GaugeDataItemOption>(idx); | |
const pointerModel = itemModel.getModel('pointer'); | |
const pointerWidth = parsePercent(pointerModel.get('width'), posInfo.r); | |
const pointerLength = parsePercent(pointerModel.get('length'), posInfo.r); | |
const pointerStr = seriesModel.get(['pointer', 'icon']); | |
const pointerOffset = pointerModel.get('offsetCenter'); | |
const pointerOffsetX = parsePercent(pointerOffset[0], posInfo.r); | |
const pointerOffsetY = parsePercent(pointerOffset[1], posInfo.r); | |
const pointerKeepAspect = pointerModel.get('keepAspect'); | |
let pointer; | |
// not exist icon type will be set 'rect' | |
if (pointerStr) { | |
pointer = createSymbol( | |
pointerStr, | |
pointerOffsetX - pointerWidth / 2, | |
pointerOffsetY - pointerLength, | |
pointerWidth, | |
pointerLength, | |
null, | |
pointerKeepAspect | |
) as graphic.Path; | |
} | |
else { | |
pointer = new PointerPath({ | |
shape: { | |
angle: -Math.PI / 2, | |
width: pointerWidth, | |
r: pointerLength, | |
x: pointerOffsetX, | |
y: pointerOffsetY | |
} | |
}); | |
} | |
pointer.rotation = -(angle + Math.PI / 2); | |
pointer.x = posInfo.cx; | |
pointer.y = posInfo.cy; | |
return pointer; | |
} | |
function createProgress(idx: number, endAngle: number) { | |
const roundCap = progressModel.get('roundCap'); | |
const ProgressPath = roundCap ? Sausage : graphic.Sector; | |
const isOverlap = progressModel.get('overlap'); | |
const progressWidth = isOverlap ? progressModel.get('width') : axisLineWidth / data.count(); | |
const r0 = isOverlap ? posInfo.r - progressWidth : posInfo.r - (idx + 1) * progressWidth; | |
const r = isOverlap ? posInfo.r : posInfo.r - idx * progressWidth; | |
const progress = new ProgressPath({ | |
shape: { | |
startAngle: startAngle, | |
endAngle: endAngle, | |
cx: posInfo.cx, | |
cy: posInfo.cy, | |
clockwise: clockwise, | |
r0: r0, | |
r: r | |
} | |
}); | |
isOverlap && (progress.z2 = maxVal - (data.get(valueDim, idx) as number) % maxVal); | |
return progress; | |
} | |
if (showProgress || showPointer) { | |
data.diff(oldData) | |
.add(function (idx) { | |
const val = data.get(valueDim, idx) as number; | |
if (showPointer) { | |
const pointer = createPointer(idx, startAngle); | |
// TODO hide pointer on NaN value? | |
graphic.initProps(pointer, { | |
rotation: -( | |
(isNaN(+val) ? angleExtent[0] : linearMap(val, valueExtent, angleExtent, true)) | |
+ Math.PI / 2 | |
) | |
}, seriesModel); | |
group.add(pointer); | |
data.setItemGraphicEl(idx, pointer); | |
} | |
if (showProgress) { | |
const progress = createProgress(idx, startAngle) as graphic.Sector; | |
const isClip = progressModel.get('clip'); | |
graphic.initProps(progress, { | |
shape: { | |
endAngle: linearMap(val, valueExtent, angleExtent, isClip) | |
} | |
}, seriesModel); | |
group.add(progress); | |
// Add data index and series index for indexing the data by element | |
// Useful in tooltip | |
setCommonECData(seriesModel.seriesIndex, data.dataType, idx, progress); | |
progressList[idx] = progress; | |
} | |
}) | |
.update(function (newIdx, oldIdx) { | |
const val = data.get(valueDim, newIdx) as number; | |
if (showPointer) { | |
const previousPointer = oldData.getItemGraphicEl(oldIdx) as PointerPath; | |
const previousRotate = previousPointer ? previousPointer.rotation : startAngle; | |
const pointer = createPointer(newIdx, previousRotate); | |
pointer.rotation = previousRotate; | |
graphic.updateProps(pointer, { | |
rotation: -( | |
(isNaN(+val) ? angleExtent[0] : linearMap(val, valueExtent, angleExtent, true)) | |
+ Math.PI / 2 | |
) | |
}, seriesModel); | |
group.add(pointer); | |
data.setItemGraphicEl(newIdx, pointer); | |
} | |
if (showProgress) { | |
const previousProgress = oldProgressData[oldIdx]; | |
const previousEndAngle = previousProgress ? previousProgress.shape.endAngle : startAngle; | |
const progress = createProgress(newIdx, previousEndAngle) as graphic.Sector; | |
const isClip = progressModel.get('clip'); | |
graphic.updateProps(progress, { | |
shape: { | |
endAngle: linearMap(val, valueExtent, angleExtent, isClip) | |
} | |
}, seriesModel); | |
group.add(progress); | |
// Add data index and series index for indexing the data by element | |
// Useful in tooltip | |
setCommonECData(seriesModel.seriesIndex, data.dataType, newIdx, progress); | |
progressList[newIdx] = progress; | |
} | |
}) | |
.execute(); | |
data.each(function (idx) { | |
const itemModel = data.getItemModel<GaugeDataItemOption>(idx); | |
const emphasisModel = itemModel.getModel('emphasis'); | |
const focus = emphasisModel.get('focus'); | |
const blurScope = emphasisModel.get('blurScope'); | |
const emphasisDisabled = emphasisModel.get('disabled'); | |
if (showPointer) { | |
const pointer = data.getItemGraphicEl(idx) as ECSymbol; | |
const symbolStyle = data.getItemVisual(idx, 'style'); | |
const visualColor = symbolStyle.fill; | |
if (pointer instanceof ZRImage) { | |
const pathStyle = pointer.style; | |
pointer.useStyle(extend({ | |
image: pathStyle.image, | |
x: pathStyle.x, y: pathStyle.y, | |
width: pathStyle.width, height: pathStyle.height | |
}, symbolStyle)); | |
} | |
else { | |
pointer.useStyle(symbolStyle); | |
pointer.type !== 'pointer' && pointer.setColor(visualColor); | |
} | |
pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle()); | |
if (pointer.style.fill === 'auto') { | |
pointer.setStyle('fill', getColor( | |
linearMap(data.get(valueDim, idx) as number, valueExtent, [0, 1], true) | |
)); | |
} | |
(pointer as ECElement).z2EmphasisLift = 0; | |
setStatesStylesFromModel(pointer, itemModel); | |
toggleHoverEmphasis(pointer, focus, blurScope, emphasisDisabled); | |
} | |
if (showProgress) { | |
const progress = progressList[idx]; | |
progress.useStyle(data.getItemVisual(idx, 'style')); | |
progress.setStyle(itemModel.getModel(['progress', 'itemStyle']).getItemStyle()); | |
(progress as ECElement).z2EmphasisLift = 0; | |
setStatesStylesFromModel(progress, itemModel); | |
toggleHoverEmphasis(progress, focus, blurScope, emphasisDisabled); | |
} | |
}); | |
this._progressEls = progressList; | |
} | |
} | |
_renderAnchor( | |
seriesModel: GaugeSeriesModel, | |
posInfo: PosInfo | |
) { | |
const anchorModel = seriesModel.getModel('anchor'); | |
const showAnchor = anchorModel.get('show'); | |
if (showAnchor) { | |
const anchorSize = anchorModel.get('size'); | |
const anchorType = anchorModel.get('icon'); | |
const offsetCenter = anchorModel.get('offsetCenter'); | |
const anchorKeepAspect = anchorModel.get('keepAspect'); | |
const anchor = createSymbol( | |
anchorType, | |
posInfo.cx - anchorSize / 2 + parsePercent(offsetCenter[0], posInfo.r), | |
posInfo.cy - anchorSize / 2 + parsePercent(offsetCenter[1], posInfo.r), | |
anchorSize, | |
anchorSize, | |
null, | |
anchorKeepAspect | |
) as graphic.Path; | |
anchor.z2 = anchorModel.get('showAbove') ? 1 : 0; | |
anchor.setStyle(anchorModel.getModel('itemStyle').getItemStyle()); | |
this.group.add(anchor); | |
} | |
} | |
_renderTitleAndDetail( | |
seriesModel: GaugeSeriesModel, | |
ecModel: GlobalModel, | |
api: ExtensionAPI, | |
getColor: (percent: number) => ColorString, | |
posInfo: PosInfo | |
) { | |
const data = seriesModel.getData(); | |
const valueDim = data.mapDimension('value'); | |
const minVal = +seriesModel.get('min'); | |
const maxVal = +seriesModel.get('max'); | |
const contentGroup = new graphic.Group(); | |
const newTitleEls: graphic.Text[] = []; | |
const newDetailEls: graphic.Text[] = []; | |
const hasAnimation = seriesModel.isAnimationEnabled(); | |
const showPointerAbove = seriesModel.get(['pointer', 'showAbove']); | |
data.diff(this._data) | |
.add((idx) => { | |
newTitleEls[idx] = new graphic.Text({ | |
silent: true | |
}); | |
newDetailEls[idx] = new graphic.Text({ | |
silent: true | |
}); | |
}) | |
.update((idx, oldIdx) => { | |
newTitleEls[idx] = this._titleEls[oldIdx]; | |
newDetailEls[idx] = this._detailEls[oldIdx]; | |
}) | |
.execute(); | |
data.each(function (idx) { | |
const itemModel = data.getItemModel<GaugeDataItemOption>(idx); | |
const value = data.get(valueDim, idx) as number; | |
const itemGroup = new graphic.Group(); | |
const autoColor = getColor( | |
linearMap(value, [minVal, maxVal], [0, 1], true) | |
); | |
const itemTitleModel = itemModel.getModel('title'); | |
if (itemTitleModel.get('show')) { | |
const titleOffsetCenter = itemTitleModel.get('offsetCenter'); | |
const titleX = posInfo.cx + parsePercent(titleOffsetCenter[0], posInfo.r); | |
const titleY = posInfo.cy + parsePercent(titleOffsetCenter[1], posInfo.r); | |
const labelEl = newTitleEls[idx]; | |
labelEl.attr({ | |
z2: showPointerAbove ? 0 : 2, | |
style: createTextStyle(itemTitleModel, { | |
x: titleX, | |
y: titleY, | |
text: data.getName(idx), | |
align: 'center', | |
verticalAlign: 'middle' | |
}, {inheritColor: autoColor}) | |
}); | |
itemGroup.add(labelEl); | |
} | |
const itemDetailModel = itemModel.getModel('detail'); | |
if (itemDetailModel.get('show')) { | |
const detailOffsetCenter = itemDetailModel.get('offsetCenter'); | |
const detailX = posInfo.cx + parsePercent(detailOffsetCenter[0], posInfo.r); | |
const detailY = posInfo.cy + parsePercent(detailOffsetCenter[1], posInfo.r); | |
const width = parsePercent(itemDetailModel.get('width'), posInfo.r); | |
const height = parsePercent(itemDetailModel.get('height'), posInfo.r); | |
const detailColor = ( | |
seriesModel.get(['progress', 'show']) ? data.getItemVisual(idx, 'style').fill : autoColor | |
) as string; | |
const labelEl = newDetailEls[idx]; | |
const formatter = itemDetailModel.get('formatter'); | |
labelEl.attr({ | |
z2: showPointerAbove ? 0 : 2, | |
style: createTextStyle(itemDetailModel, { | |
x: detailX, | |
y: detailY, | |
text: formatLabel(value, formatter), | |
width: isNaN(width) ? null : width, | |
height: isNaN(height) ? null : height, | |
align: 'center', | |
verticalAlign: 'middle' | |
}, {inheritColor: detailColor}) | |
}); | |
setLabelValueAnimation( | |
labelEl, | |
{normal: itemDetailModel}, | |
value, | |
(value: number) => formatLabel(value, formatter) | |
); | |
hasAnimation && animateLabelValue(labelEl, idx, data, seriesModel, { | |
getFormattedLabel( | |
labelDataIndex, status, dataType, labelDimIndex, fmt, extendParams | |
) { | |
return formatLabel( | |
extendParams | |
? extendParams.interpolatedValue as typeof value | |
: value, | |
formatter | |
); | |
} | |
}); | |
itemGroup.add(labelEl); | |
} | |
contentGroup.add(itemGroup); | |
}); | |
this.group.add(contentGroup); | |
this._titleEls = newTitleEls; | |
this._detailEls = newDetailEls; | |
} | |
} | |
export default GaugeView; | |