* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { getFormated, htmlHandler, getLegend } from '../chart-core/deps/utils'
import { itemPoint, itemLabel, itemContent } from '../chart-core/deps/constants'
const getXAxis = (args) => {
const { columns, xAxisName, axisVisible, xAxisType } = args
return [
{
type: xAxisType,
nameLocation: 'middle',
nameGap: 22,
name: xAxisName || '',
axisTick: { show: true, lineStyle: { color: '#eee' } },
data: columns,
show: axisVisible
}
]
}
const getSeries = (args) => {
const { area, areaStyle, itemStyle, label, lineStyle, outliers = [], rows } = args
let { series = [], arr = ['boxplot', 'scatter'] } = {}
arr.forEach((item) => {
if (item === 'scatter' && !outliers.length) {
return
}
let data = item === 'boxplot' ? rows : outliers
let seriesItem = { name: '', type: item, data }
area && (seriesItem.areaStyle = {})
label && (seriesItem.label = label)
lineStyle && (seriesItem.lineStyle = lineStyle)
itemStyle && (seriesItem.itemStyle = itemStyle)
areaStyle && (seriesItem.areaStyle = areaStyle)
series.push(seriesItem)
})
return series
}
const factoryFmt =
({ yAxisType, i, digit }) =>
(val) =>
getFormated(val, yAxisType[i], digit)
const getYAxis = (args) => {
const { axisVisible, digit, max, min, scale, yAxisName, yAxisType } = args
const yAxisBase = { type: 'value', axisTick: { show: false }, show: axisVisible }
let { yAxis = [], len = yAxisType.length >= 2 ? 2 : 1, i = 0 } = {}
for (; i < len; i++) {
if (!yAxisType[i]) {
yAxis[i] = { ...yAxisBase }
} else {
let formatter = factoryFmt({ yAxisType, i, digit })
let yAxisAdv = { axisLabel: { formatter } }
yAxis[i] = { ...yAxisBase, ...yAxisAdv }
let name = yAxisName[i] || ''
Object.assign(yAxis[i], { name, scale: scale[i] || false, min: min[i] || null, max: max[i] || null })
}
}
return yAxis
}
const tooltipTemplate = ({ data, seriesType, seriesName, color, value, name }, tooltipLabel) => {
let tpl = []
if (seriesType === 'boxplot') {
const tips = []
tooltipLabel.forEach((label, idx) => {
tips.push(`${itemPoint(color)}${itemLabel(label)}${itemContent(data[idx + 1])}`)
})
tpl.push(tips.join('<br/>'))
} else {
tpl.push(itemPoint(color))
if (Array.isArray(value)) {
tpl.push(value.join(': '))
} else {
tpl.push(`${seriesName || name}: `)
tpl.push(value)
}
tpl.push('<br>')
}
return tpl
}
const getTooltip = (args) => {
const { tooltipFormatter, tooltipLabel } = args
return {
trigger: 'item',
formatter(items) {
if (tooltipFormatter) {
return tooltipFormatter.apply(null, arguments)
}
let tpl = []
const { name, axisValueLabel } = items[0] || {}
const title = name || axisValueLabel
title && tpl.push(`${title}<br>`)
if (Array.isArray(items)) {
items.forEach((item) => {
tpl = tpl.concat(tooltipTemplate(item, tooltipLabel))
})
} else {
tpl = tooltipTemplate(items, tooltipLabel)
}
return tpl.join('')
}
}
}
export const boxplot = (columns, rows, settings, extra) => {
rows = Array.isArray(rows) ? rows : []
columns = Array.isArray(columns) ? columns : []
const { axisSite = {}, yAxisType = ['normal'], xAxisType = 'category', yAxisName = '', xAxisName = '' } = settings
const { axisVisible = true, area, scale = [false, false], min = [null, null], max = [null, null] } = settings
const { nullAddZero = false, digit = 2, legendName = {}, labelMap = {}, label, itemStyle } = settings
const { lineStyle, areaStyle, tooltipLabel = ['lower', 'Q1', 'median', 'Q3', 'upper'] } = settings
const { legendVisible, outliers, tooltipFormatter, tooltipVisible } = extra
let metrics = columns.slice()
if (axisSite.right && axisSite.left) {
metrics = axisSite.left.concat(axisSite.right)
} else if (!axisSite.right && axisSite.left) {
metrics = axisSite.left
} else if (settings.metrics) {
metrics = settings.metrics
}
const legend = legendVisible && getLegend({ metrics, legendName, labelMap })
const getParams = () => ({ tooltipFormatter, tooltipLabel: htmlHandler(tooltipLabel), digit })
const tooltip = tooltipVisible && getTooltip(getParams())
const xAxis = getXAxis({ columns, xAxisName, axisVisible, xAxisType })
const yAxisParams = { yAxisName, yAxisType, axisVisible }
Object.assign(yAxisParams, { scale, min, max, digit })
const yAxis = getYAxis(yAxisParams)
const seriesParams = { rows, axisSite, metrics, area, nullAddZero, labelMap, label }
Object.assign(seriesParams, { itemStyle, lineStyle, areaStyle, xAxisType, outliers })
const series = getSeries(seriesParams)
return { legend, xAxis, series, yAxis, tooltip }
}