758 lines
18 KiB
TypeScript
758 lines
18 KiB
TypeScript
import CLASS from './class'
|
|
import { ChartInternal } from './core'
|
|
import {
|
|
isValue,
|
|
isFunction,
|
|
isNumber,
|
|
isArray,
|
|
notEmpty,
|
|
hasValue,
|
|
flattenArray,
|
|
getBBox
|
|
} from './util'
|
|
|
|
ChartInternal.prototype.isEpochs = function(key) {
|
|
var $$ = this,
|
|
config = $$.config
|
|
return config.data_epochs && key === config.data_epochs
|
|
}
|
|
ChartInternal.prototype.isX = function(key) {
|
|
var $$ = this,
|
|
config = $$.config
|
|
return (
|
|
(config.data_x && key === config.data_x) ||
|
|
(notEmpty(config.data_xs) && hasValue(config.data_xs, key))
|
|
)
|
|
}
|
|
ChartInternal.prototype.isNotX = function(key) {
|
|
return !this.isX(key)
|
|
}
|
|
ChartInternal.prototype.isNotXAndNotEpochs = function(key) {
|
|
return !this.isX(key) && !this.isEpochs(key)
|
|
}
|
|
|
|
/**
|
|
* Returns whether the normalized stack option is enabled or not.
|
|
*
|
|
* To be enabled it must also have data.groups defined.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
ChartInternal.prototype.isStackNormalized = function() {
|
|
return this.config.data_stack_normalize && this.config.data_groups.length > 0
|
|
}
|
|
|
|
/**
|
|
* Returns whether the axis is normalized or not.
|
|
*
|
|
* An axis is normalized as long as one of its associated target
|
|
* is normalized.
|
|
*
|
|
* @param axisId Axis ID (y or y2)
|
|
* @return {Boolean}
|
|
*/
|
|
ChartInternal.prototype.isAxisNormalized = function(axisId) {
|
|
const $$ = this
|
|
|
|
if (!$$.isStackNormalized()) {
|
|
// shortcut
|
|
return false
|
|
}
|
|
|
|
return $$.data.targets
|
|
.filter(target => $$.axis.getId(target.id) === axisId)
|
|
.some(target => $$.isTargetNormalized(target.id))
|
|
}
|
|
|
|
/**
|
|
* Returns whether the values for this target ID is normalized or not.
|
|
*
|
|
* To be normalized the option needs to be enabled and target needs
|
|
* to be defined in `data.groups`.
|
|
*
|
|
* @param targetId ID of the target
|
|
* @return {Boolean} True if the target is normalized, false otherwise.
|
|
*/
|
|
ChartInternal.prototype.isTargetNormalized = function(targetId) {
|
|
const $$ = this
|
|
|
|
return (
|
|
$$.isStackNormalized() &&
|
|
$$.config.data_groups.some(group => group.includes(targetId))
|
|
)
|
|
}
|
|
|
|
ChartInternal.prototype.getXKey = function(id) {
|
|
var $$ = this,
|
|
config = $$.config
|
|
return config.data_x
|
|
? config.data_x
|
|
: notEmpty(config.data_xs)
|
|
? config.data_xs[id]
|
|
: null
|
|
}
|
|
|
|
/**
|
|
* Get sum of visible data per index for given axis.
|
|
*
|
|
* Expect axisId to be either 'y' or 'y2'.
|
|
*
|
|
* @private
|
|
* @param axisId Compute sum for data associated to given axis.
|
|
* @return {Array}
|
|
*/
|
|
ChartInternal.prototype.getTotalPerIndex = function(axisId) {
|
|
const $$ = this
|
|
|
|
if (!$$.isStackNormalized()) {
|
|
return null
|
|
}
|
|
|
|
const cached = $$.getFromCache('getTotalPerIndex')
|
|
if (cached !== undefined) {
|
|
return cached[axisId]
|
|
}
|
|
|
|
const sum = { y: [], y2: [] }
|
|
|
|
$$.data.targets
|
|
// keep only target that are normalized
|
|
.filter(target => $$.isTargetNormalized(target.id))
|
|
|
|
// keep only target that are visible
|
|
.filter(target => $$.isTargetToShow(target.id))
|
|
|
|
// compute sum per axis
|
|
.forEach(target => {
|
|
const sumByAxis = sum[$$.axis.getId(target.id)]
|
|
|
|
target.values.forEach((v, i) => {
|
|
if (!sumByAxis[i]) {
|
|
sumByAxis[i] = 0
|
|
}
|
|
sumByAxis[i] += isNumber(v.value) ? v.value : 0
|
|
})
|
|
})
|
|
|
|
$$.addToCache('getTotalPerIndex', sum)
|
|
|
|
return sum[axisId]
|
|
}
|
|
|
|
/**
|
|
* Get sum of visible data.
|
|
*
|
|
* Should be used for normalised data only since all values
|
|
* are expected to be positive.
|
|
*
|
|
* @private
|
|
* @return {Number}
|
|
*/
|
|
ChartInternal.prototype.getTotalDataSum = function() {
|
|
const $$ = this
|
|
|
|
const cached = $$.getFromCache('getTotalDataSum')
|
|
if (cached !== undefined) {
|
|
return cached
|
|
}
|
|
|
|
const totalDataSum = flattenArray(
|
|
$$.data.targets
|
|
.filter(target => $$.isTargetToShow(target.id))
|
|
.map(target => target.values)
|
|
)
|
|
.map(d => d.value)
|
|
.reduce((p, c) => p + c, 0)
|
|
|
|
$$.addToCache('getTotalDataSum', totalDataSum)
|
|
|
|
return totalDataSum
|
|
}
|
|
|
|
ChartInternal.prototype.getXValuesOfXKey = function(key, targets) {
|
|
var $$ = this,
|
|
xValues,
|
|
ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : []
|
|
ids.forEach(function(id) {
|
|
if ($$.getXKey(id) === key) {
|
|
xValues = $$.data.xs[id]
|
|
}
|
|
})
|
|
return xValues
|
|
}
|
|
ChartInternal.prototype.getXValue = function(id, i) {
|
|
var $$ = this
|
|
return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i])
|
|
? $$.data.xs[id][i]
|
|
: i
|
|
}
|
|
ChartInternal.prototype.getOtherTargetXs = function() {
|
|
var $$ = this,
|
|
idsForX = Object.keys($$.data.xs)
|
|
return idsForX.length ? $$.data.xs[idsForX[0]] : null
|
|
}
|
|
ChartInternal.prototype.getOtherTargetX = function(index) {
|
|
var xs = this.getOtherTargetXs()
|
|
return xs && index < xs.length ? xs[index] : null
|
|
}
|
|
ChartInternal.prototype.addXs = function(xs) {
|
|
var $$ = this
|
|
Object.keys(xs).forEach(function(id) {
|
|
$$.config.data_xs[id] = xs[id]
|
|
})
|
|
}
|
|
ChartInternal.prototype.addName = function(data) {
|
|
var $$ = this,
|
|
name
|
|
if (data) {
|
|
name = $$.config.data_names[data.id]
|
|
data.name = name !== undefined ? name : data.id
|
|
}
|
|
return data
|
|
}
|
|
ChartInternal.prototype.getValueOnIndex = function(values, index) {
|
|
var valueOnIndex = values.filter(function(v) {
|
|
return v.index === index
|
|
})
|
|
return valueOnIndex.length ? valueOnIndex[0] : null
|
|
}
|
|
ChartInternal.prototype.updateTargetX = function(targets, x) {
|
|
var $$ = this
|
|
targets.forEach(function(t) {
|
|
t.values.forEach(function(v, i) {
|
|
v.x = $$.generateTargetX(x[i], t.id, i)
|
|
})
|
|
$$.data.xs[t.id] = x
|
|
})
|
|
}
|
|
ChartInternal.prototype.updateTargetXs = function(targets, xs) {
|
|
var $$ = this
|
|
targets.forEach(function(t) {
|
|
if (xs[t.id]) {
|
|
$$.updateTargetX([t], xs[t.id])
|
|
}
|
|
})
|
|
}
|
|
ChartInternal.prototype.generateTargetX = function(rawX, id, index) {
|
|
var $$ = this,
|
|
x
|
|
if ($$.isTimeSeries()) {
|
|
x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index))
|
|
} else if ($$.isCustomX() && !$$.isCategorized()) {
|
|
x = isValue(rawX) ? +rawX : $$.getXValue(id, index)
|
|
} else {
|
|
x = index
|
|
}
|
|
return x
|
|
}
|
|
ChartInternal.prototype.cloneTarget = function(target) {
|
|
return {
|
|
id: target.id,
|
|
id_org: target.id_org,
|
|
values: target.values.map(function(d) {
|
|
return {
|
|
x: d.x,
|
|
value: d.value,
|
|
id: d.id
|
|
}
|
|
})
|
|
}
|
|
}
|
|
ChartInternal.prototype.getMaxDataCount = function() {
|
|
var $$ = this
|
|
return $$.d3.max($$.data.targets, function(t) {
|
|
return t.values.length
|
|
})
|
|
}
|
|
ChartInternal.prototype.mapToIds = function(targets) {
|
|
return targets.map(function(d) {
|
|
return d.id
|
|
})
|
|
}
|
|
ChartInternal.prototype.mapToTargetIds = function(ids) {
|
|
var $$ = this
|
|
return ids ? [].concat(ids) : $$.mapToIds($$.data.targets)
|
|
}
|
|
ChartInternal.prototype.hasTarget = function(targets, id) {
|
|
var ids = this.mapToIds(targets),
|
|
i
|
|
for (i = 0; i < ids.length; i++) {
|
|
if (ids[i] === id) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
ChartInternal.prototype.isTargetToShow = function(targetId) {
|
|
return this.hiddenTargetIds.indexOf(targetId) < 0
|
|
}
|
|
ChartInternal.prototype.isLegendToShow = function(targetId) {
|
|
return this.hiddenLegendIds.indexOf(targetId) < 0
|
|
}
|
|
|
|
/**
|
|
* Returns only visible targets.
|
|
*
|
|
* This is the same as calling {@link filterTargetsToShow} on $$.data.targets.
|
|
*
|
|
* @return {Array}
|
|
*/
|
|
ChartInternal.prototype.getTargetsToShow = function() {
|
|
const $$ = this
|
|
return $$.filterTargetsToShow($$.data.targets)
|
|
}
|
|
|
|
ChartInternal.prototype.filterTargetsToShow = function(targets) {
|
|
var $$ = this
|
|
return targets.filter(function(t) {
|
|
return $$.isTargetToShow(t.id)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* @return {Array} Returns all the targets attached to the chart, visible or not
|
|
*/
|
|
ChartInternal.prototype.getTargets = function() {
|
|
const $$ = this
|
|
return $$.data.targets
|
|
}
|
|
|
|
ChartInternal.prototype.mapTargetsToUniqueXs = function(targets) {
|
|
var $$ = this
|
|
var xs = $$.d3
|
|
.set(
|
|
$$.d3.merge(
|
|
targets.map(function(t) {
|
|
return t.values.map(function(v) {
|
|
return +v.x
|
|
})
|
|
})
|
|
)
|
|
)
|
|
.values()
|
|
xs = $$.isTimeSeries()
|
|
? xs.map(function(x) {
|
|
return new Date(+x)
|
|
})
|
|
: xs.map(function(x) {
|
|
return +x
|
|
})
|
|
return xs.sort(function(a, b) {
|
|
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN
|
|
})
|
|
}
|
|
ChartInternal.prototype.addHiddenTargetIds = function(targetIds) {
|
|
targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds)
|
|
for (var i = 0; i < targetIds.length; i++) {
|
|
if (this.hiddenTargetIds.indexOf(targetIds[i]) < 0) {
|
|
this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds[i])
|
|
}
|
|
}
|
|
this.resetCache()
|
|
}
|
|
ChartInternal.prototype.removeHiddenTargetIds = function(targetIds) {
|
|
this.hiddenTargetIds = this.hiddenTargetIds.filter(function(id) {
|
|
return targetIds.indexOf(id) < 0
|
|
})
|
|
this.resetCache()
|
|
}
|
|
ChartInternal.prototype.addHiddenLegendIds = function(targetIds) {
|
|
targetIds = targetIds instanceof Array ? targetIds : new Array(targetIds)
|
|
for (var i = 0; i < targetIds.length; i++) {
|
|
if (this.hiddenLegendIds.indexOf(targetIds[i]) < 0) {
|
|
this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds[i])
|
|
}
|
|
}
|
|
}
|
|
ChartInternal.prototype.removeHiddenLegendIds = function(targetIds) {
|
|
this.hiddenLegendIds = this.hiddenLegendIds.filter(function(id) {
|
|
return targetIds.indexOf(id) < 0
|
|
})
|
|
}
|
|
ChartInternal.prototype.getValuesAsIdKeyed = function(targets) {
|
|
var ys = {}
|
|
targets.forEach(function(t) {
|
|
ys[t.id] = []
|
|
t.values.forEach(function(v) {
|
|
ys[t.id].push(v.value)
|
|
})
|
|
})
|
|
return ys
|
|
}
|
|
ChartInternal.prototype.checkValueInTargets = function(targets, checker) {
|
|
var ids = Object.keys(targets),
|
|
i,
|
|
j,
|
|
values
|
|
for (i = 0; i < ids.length; i++) {
|
|
values = targets[ids[i]].values
|
|
for (j = 0; j < values.length; j++) {
|
|
if (checker(values[j].value)) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
ChartInternal.prototype.hasNegativeValueInTargets = function(targets) {
|
|
return this.checkValueInTargets(targets, function(v) {
|
|
return v < 0
|
|
})
|
|
}
|
|
ChartInternal.prototype.hasPositiveValueInTargets = function(targets) {
|
|
return this.checkValueInTargets(targets, function(v) {
|
|
return v > 0
|
|
})
|
|
}
|
|
ChartInternal.prototype.isOrderDesc = function() {
|
|
var config = this.config
|
|
return (
|
|
typeof config.data_order === 'string' &&
|
|
config.data_order.toLowerCase() === 'desc'
|
|
)
|
|
}
|
|
ChartInternal.prototype.isOrderAsc = function() {
|
|
var config = this.config
|
|
return (
|
|
typeof config.data_order === 'string' &&
|
|
config.data_order.toLowerCase() === 'asc'
|
|
)
|
|
}
|
|
ChartInternal.prototype.getOrderFunction = function() {
|
|
var $$ = this,
|
|
config = $$.config,
|
|
orderAsc = $$.isOrderAsc(),
|
|
orderDesc = $$.isOrderDesc()
|
|
if (orderAsc || orderDesc) {
|
|
var reducer = function(p, c) {
|
|
return p + Math.abs(c.value)
|
|
}
|
|
return function(t1, t2) {
|
|
var t1Sum = t1.values.reduce(reducer, 0),
|
|
t2Sum = t2.values.reduce(reducer, 0)
|
|
return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum
|
|
}
|
|
} else if (isFunction(config.data_order)) {
|
|
return config.data_order
|
|
} else if (isArray(config.data_order)) {
|
|
var order = config.data_order
|
|
return function(t1, t2) {
|
|
return order.indexOf(t1.id) - order.indexOf(t2.id)
|
|
}
|
|
}
|
|
}
|
|
ChartInternal.prototype.orderTargets = function(targets) {
|
|
var fct = this.getOrderFunction()
|
|
if (fct) {
|
|
targets.sort(fct)
|
|
}
|
|
return targets
|
|
}
|
|
|
|
/**
|
|
* Returns all the values from the given targets at the given index.
|
|
*
|
|
* @param {Array} targets
|
|
* @param {Number} index
|
|
* @return {Array}
|
|
*/
|
|
ChartInternal.prototype.filterByIndex = function(targets, index) {
|
|
return this.d3.merge(
|
|
targets.map(t => t.values.filter(v => v.index === index))
|
|
)
|
|
}
|
|
|
|
ChartInternal.prototype.filterByX = function(targets, x) {
|
|
return this.d3
|
|
.merge(
|
|
targets.map(function(t) {
|
|
return t.values
|
|
})
|
|
)
|
|
.filter(function(v) {
|
|
return v.x - x === 0
|
|
})
|
|
}
|
|
ChartInternal.prototype.filterRemoveNull = function(data) {
|
|
return data.filter(function(d) {
|
|
return isValue(d.value)
|
|
})
|
|
}
|
|
ChartInternal.prototype.filterByXDomain = function(targets, xDomain) {
|
|
return targets.map(function(t) {
|
|
return {
|
|
id: t.id,
|
|
id_org: t.id_org,
|
|
values: t.values.filter(function(v) {
|
|
return xDomain[0] <= v.x && v.x <= xDomain[1]
|
|
})
|
|
}
|
|
})
|
|
}
|
|
ChartInternal.prototype.hasDataLabel = function() {
|
|
var config = this.config
|
|
if (typeof config.data_labels === 'boolean' && config.data_labels) {
|
|
return true
|
|
} else if (
|
|
typeof config.data_labels === 'object' &&
|
|
notEmpty(config.data_labels)
|
|
) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
ChartInternal.prototype.getDataLabelLength = function(min, max, key) {
|
|
var $$ = this,
|
|
lengths = [0, 0],
|
|
paddingCoef = 1.3
|
|
$$.selectChart
|
|
.select('svg')
|
|
.selectAll('.dummy')
|
|
.data([min, max])
|
|
.enter()
|
|
.append('text')
|
|
.text(function(d) {
|
|
return $$.dataLabelFormat(d.id)(d)
|
|
})
|
|
.each(function(d, i) {
|
|
lengths[i] = getBBox(this)[key] * paddingCoef
|
|
})
|
|
.remove()
|
|
return lengths
|
|
}
|
|
/**
|
|
* Returns true if the given data point is not arc type, otherwise false.
|
|
* @param {Object} d The data point
|
|
* @return {boolean}
|
|
*/
|
|
ChartInternal.prototype.isNoneArc = function(d) {
|
|
return this.hasTarget(this.data.targets, d.id)
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given data point is arc type, otherwise false.
|
|
* @param {Object} d The data point
|
|
* @return {boolean}
|
|
*/
|
|
ChartInternal.prototype.isArc = function(d) {
|
|
return 'data' in d && this.hasTarget(this.data.targets, d.data.id)
|
|
}
|
|
|
|
/**
|
|
* Find the closest point from the given pos among the given targets or
|
|
* undefined if none satisfies conditions.
|
|
*
|
|
* @param {Array} targets
|
|
* @param {Array} pos An [x,y] coordinate
|
|
* @return {Object|undefined}
|
|
*/
|
|
ChartInternal.prototype.findClosestFromTargets = function(targets, pos) {
|
|
const $$ = this
|
|
|
|
// for each target, find the closest point
|
|
const candidates = targets
|
|
.map(t =>
|
|
$$.findClosest(
|
|
t.values,
|
|
pos,
|
|
$$.config.tooltip_horizontal
|
|
? $$.horizontalDistance.bind($$)
|
|
: $$.dist.bind($$),
|
|
$$.config.point_sensitivity
|
|
)
|
|
)
|
|
.filter(v => v)
|
|
|
|
// returns the closest of candidates
|
|
if (candidates.length === 0) {
|
|
return undefined
|
|
} else if (candidates.length === 1) {
|
|
return candidates[0]
|
|
} else {
|
|
return $$.findClosest(candidates, pos, $$.dist.bind($$))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find the closest point from the x value or undefined if none satisfies conditions.
|
|
*
|
|
* @param {Array} targets
|
|
* @param {Array} x A value on X axis
|
|
* @return {Object|undefined}
|
|
*/
|
|
ChartInternal.prototype.findClosestFromTargetsByX = function(targets, x) {
|
|
let closest
|
|
let diff
|
|
|
|
targets.forEach(t => {
|
|
t.values.forEach(d => {
|
|
let newDiff = Math.abs(x - d.x)
|
|
|
|
if (diff === undefined || newDiff < diff) {
|
|
closest = d
|
|
diff = newDiff
|
|
}
|
|
})
|
|
})
|
|
|
|
return closest
|
|
}
|
|
|
|
/**
|
|
* Using given compute distance method, returns the closest data point from the
|
|
* given position.
|
|
*
|
|
* Giving optionally a minimum distance to satisfy.
|
|
*
|
|
* @param {Array} dataPoints List of DataPoints
|
|
* @param {Array} pos An [x,y] coordinate
|
|
* @param {Function} computeDist Function to compute distance between 2 points
|
|
* @param {Number} minDist Minimal distance to satisfy
|
|
* @return {Object|undefined} Closest data point
|
|
*/
|
|
ChartInternal.prototype.findClosest = function(
|
|
dataPoints,
|
|
pos,
|
|
computeDist,
|
|
minDist = Infinity
|
|
) {
|
|
const $$ = this
|
|
|
|
let closest
|
|
|
|
// find closest bar
|
|
dataPoints
|
|
.filter(v => v && $$.isBarType(v.id))
|
|
.forEach(function(v) {
|
|
if (!closest) {
|
|
const shape = $$.main
|
|
.select(
|
|
'.' +
|
|
CLASS.bars +
|
|
$$.getTargetSelectorSuffix(v.id) +
|
|
' .' +
|
|
CLASS.bar +
|
|
'-' +
|
|
v.index
|
|
)
|
|
.node()
|
|
if ($$.isWithinBar(pos, shape)) {
|
|
closest = v
|
|
}
|
|
}
|
|
})
|
|
|
|
// find closest point from non-bar
|
|
dataPoints
|
|
.filter(v => v && !$$.isBarType(v.id))
|
|
.forEach(v => {
|
|
let d = computeDist(v, pos)
|
|
if (d < minDist) {
|
|
minDist = d
|
|
closest = v
|
|
}
|
|
})
|
|
|
|
return closest
|
|
}
|
|
ChartInternal.prototype.dist = function(data, pos) {
|
|
var $$ = this,
|
|
config = $$.config,
|
|
xIndex = config.axis_rotated ? 1 : 0,
|
|
yIndex = config.axis_rotated ? 0 : 1,
|
|
y = $$.circleY(data, data.index),
|
|
x = $$.x(data.x)
|
|
return Math.sqrt(Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2))
|
|
}
|
|
ChartInternal.prototype.horizontalDistance = function(data, pos) {
|
|
var $$ = this,
|
|
config = $$.config,
|
|
xIndex = config.axis_rotated ? 1 : 0,
|
|
x = $$.x(data.x)
|
|
|
|
return Math.abs(x - pos[xIndex])
|
|
}
|
|
ChartInternal.prototype.convertValuesToStep = function(values) {
|
|
var converted = [].concat(values),
|
|
i
|
|
|
|
if (!this.isCategorized()) {
|
|
return values
|
|
}
|
|
|
|
for (i = values.length + 1; 0 < i; i--) {
|
|
converted[i] = converted[i - 1]
|
|
}
|
|
|
|
converted[0] = {
|
|
x: converted[0].x - 1,
|
|
value: converted[0].value,
|
|
id: converted[0].id
|
|
}
|
|
converted[values.length + 1] = {
|
|
x: converted[values.length].x + 1,
|
|
value: converted[values.length].value,
|
|
id: converted[values.length].id
|
|
}
|
|
|
|
return converted
|
|
}
|
|
|
|
/**
|
|
* Get ratio value
|
|
*
|
|
* @param {String} type Ratio for given type
|
|
* @param {Object} d Data value object
|
|
* @param {Boolean} asPercent Convert the return as percent or not
|
|
* @return {Number} Ratio value
|
|
* @private
|
|
*/
|
|
ChartInternal.prototype.getRatio = function(type, d, asPercent = false) {
|
|
const $$ = this
|
|
const api = $$.api
|
|
let ratio = 0
|
|
|
|
if (d && api.data.shown.call(api).length) {
|
|
ratio = d.ratio || d.value
|
|
|
|
if (type === 'arc') {
|
|
if ($$.hasType('gauge')) {
|
|
ratio =
|
|
(d.endAngle - d.startAngle) /
|
|
(Math.PI * ($$.config.gauge_fullCircle ? 2 : 1))
|
|
} else {
|
|
const total = $$.getTotalDataSum()
|
|
|
|
ratio = d.value / total
|
|
}
|
|
} else if (type === 'index') {
|
|
const total = $$.getTotalPerIndex($$.axis.getId(d.id))
|
|
|
|
d.ratio =
|
|
isNumber(d.value) && total && total[d.index] > 0
|
|
? d.value / total[d.index]
|
|
: 0
|
|
|
|
ratio = d.ratio
|
|
}
|
|
}
|
|
|
|
return asPercent && ratio ? ratio * 100 : ratio
|
|
}
|
|
|
|
ChartInternal.prototype.updateDataAttributes = function(name, attrs) {
|
|
var $$ = this,
|
|
config = $$.config,
|
|
current = config['data_' + name]
|
|
if (typeof attrs === 'undefined') {
|
|
return current
|
|
}
|
|
Object.keys(attrs).forEach(function(id) {
|
|
current[id] = attrs[id]
|
|
})
|
|
$$.redraw({
|
|
withLegend: true
|
|
})
|
|
return current
|
|
}
|