* 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, getBmap, getAmap, getMapJSON } from '../chart-core/deps/utils'
import { HEAT_MAP_COLOR, HEAT_DEFAULT_COLOR, itemPoint, itemLabel, itemContent } from '../chart-core/deps/constants'
const getAxisList = (rows, label) => {
const result = []
rows.forEach((row) => !result.includes(row[label]) && result.push(row[label]))
return result
}
const getData = (args) => {
const { extraMetrics, innerXAxisList, innerYAxisList, metrics, rows, type, xDim, yDim } = args
let result = null
if (type !== 'cartesian') {
result = rows.map((row) => ({ value: [row[xDim], row[yDim], metrics ? row[metrics] : 1] }))
} else {
result = rows.map((row) => {
let { xIndex, yIndex, value, extra } = {}
yIndex = innerYAxisList.indexOf(row[yDim])
xIndex = innerXAxisList.indexOf(row[xDim])
extra = extraMetrics.map((m) => row[m] || '-')
value = metrics ? row[metrics] : 1
return { value: [xIndex, yIndex, value].concat(extra) }
})
}
return result
}
let getAxis = (list, name, type) => ({
data: list,
name,
nameLocation: 'end',
type: 'category',
splitArea: { show: false },
splitLine: { show: true, lineStyle: { color: '#6d8ff0' } },
axisLabel: { show: true, color: '#4E4E4E' },
offset: type === 'y' ? 25 : 5,
zlevel: 1
})
const getVisualMap = (args) => {
const { innerMin: min, innerMax: max, type, heatColor, series, visualMapConfig } = args
let { extra } = {}
if (type === 'map') {
extra = {}
!series[0].data.length && (extra.show = false)
} else if (type === 'bmap' || type === 'amap') {
extra = { show: false }
} else {
extra = { dimension: 2 }
}
const visualMapColor = visualMapConfig && visualMapConfig.color
const defaultColor =
type === 'map' || type === 'bmap' || type === 'amap' ? HEAT_MAP_COLOR : visualMapColor || HEAT_DEFAULT_COLOR
let result = Object.assign(extra, {
min,
max,
calculable: true,
left: 'right',
bottom: 'center',
orient: 'vertical',
align: 'left',
borderColor: '#6D8FF0',
inverse: true
})
if (type !== 'cartesian' || !visualMapColor) {
Object.assign(result, {
inRange: { color: heatColor || defaultColor }
})
}
return Object.assign(result, visualMapConfig)
}
const getSeries = (args) => [{ type: 'heatmap', data: args.chartData, label: { show: true, color: '#191919' } }]
const getTooltip = (args) => {
const { dataType, innerXAxisList, innerYAxisList, digit, extraMetrics, metrics } = args
function formatter({ color, data }) {
let { value: dataVal } = data
let [xDim, yDim, value, ...extraData] = dataVal
const tplt = [itemContent(`${innerXAxisList[xDim]} ~ ${innerYAxisList[yDim]}<br>`)]
extraMetrics.forEach((m, index) => tplt.push(`${m}: ${extraData[index]}<br>`))
tplt.push(`${itemPoint(color)}${itemLabel(metrics)}${itemContent(getFormated(value, dataType, digit))}<br>`)
return tplt.join('')
}
return { trigger: 'item', formatter }
}
const fixParam = ({ type, rows, dimension, metrics, extraMetrics, chartData, innerXAxisList, innerYAxisList }) => {
let chartDataParams
if (type !== 'cartesian') {
chartDataParams = { rows, xDim: dimension[0], yDim: dimension[1] }
Object.assign(chartDataParams, { metrics, type, extraMetrics })
chartData = getData(chartDataParams)
} else {
let flag = !innerXAxisList || !innerXAxisList.length
flag && (innerXAxisList = getAxisList(rows, dimension[0]))
flag = !innerYAxisList || !innerYAxisList.length
flag && (innerYAxisList = getAxisList(rows, dimension[1]))
chartDataParams = { xDim: dimension[0], yDim: dimension[1], rows }
Object.assign(chartDataParams, { innerXAxisList, innerYAxisList, metrics, type, extraMetrics })
chartData = getData(chartDataParams)
}
return { chartData, innerXAxisList, innerYAxisList }
}
const getResult = (args) => {
let { type, options, pointSize, blurSize, res, key, v, url, bmap, mapOrigin, geo, beforeRegisterMap } = args
let { echarts, specialAreas, position, positionJsonLink, beforeRegisterMapOnce } = args
let { mapURLProfix, amap, tooltip, xAxis, yAxis } = args
if (type === 'bmap') {
Object.assign(options.series[0], { coordinateSystem: 'bmap', pointSize, blurSize })
res = getBmap({ key, version: v, url }).then(() => ({ bmap, ...options }))
} else if (type === 'map') {
options.series[0].coordinateSystem = 'geo'
let jsonStr = JSON.stringify(mapOrigin)
if (jsonStr) {
const geoAttr = { map: jsonStr, ...geo }
beforeRegisterMap && (jsonStr = beforeRegisterMap(mapOrigin))
echarts.registerMap(jsonStr, { geoJSON: mapOrigin }, specialAreas)
res = new Promise((resolve) => resolve({ geo: geoAttr, ...options }))
}
else {
let params = { position, positionJsonLink, beforeRegisterMapOnce, mapURLProfix }
res = getMapJSON(params).then((json) => {
const geoAttr = { map: position, ...geo }
beforeRegisterMap && (json = beforeRegisterMap(json))
echarts.registerMap(position, { geoJSON: json }, specialAreas)
return { geo: geoAttr, ...options }
})
}
} else if (type === 'amap') {
Object.assign(options.series[0], { coordinateSystem: 'amap', pointSize, blurSize })
res = getAmap(key, v).then(() => ({ amap, ...options }))
} else {
res = { tooltip, xAxis, yAxis, ...options }
}
return res
}
export const heatmap = (columns, rows, settings, extra, extend) => {
const { type = 'cartesian' } = settings
const { dimension = [columns[0], columns[1]] } = settings
const { dataType = 'normal', min, max, digit, bmap, amap, geo, key, v = '2.0', url } = settings
const { position, mapOrigin, positionJsonLink, beforeRegisterMap, pointSize = 10, blurSize = 5 } = settings
const { heatColor, yAxisName, xAxisName, beforeRegisterMapOnce, specialAreas = {} } = settings
const { metrics = columns[2], mapURLProfix = 'https://unpkg.com/echarts@3.6.2/map/json/' } = settings
const { tooltipVisible, echartsLib: echarts } = extra
const visualMapConfig = extend && extend.visualMap
let { xAxisList: innerXAxisList, yAxisList: innerYAxisList } = settings
let { chartData = [], extraMetrics = [], mainColumn = dimension.concat([metrics]) } = {}
columns.forEach((column) => !~mainColumn.indexOf(column) && extraMetrics.push(column))
let ret = fixParam({ type, rows, dimension, metrics, extraMetrics, chartData, innerXAxisList, innerYAxisList })
chartData = ret.chartData
innerXAxisList = ret.innerXAxisList
innerYAxisList = ret.innerYAxisList
let metricsList = metrics ? rows.map((row) => row[metrics]) : [0, 5]
!metricsList.length && (metricsList = [0])
const innerMin = min || Math.min.apply(null, metricsList)
const innerMax = max || Math.max.apply(null, metricsList)
const xAxis = getAxis(innerXAxisList, xAxisName, 'x')
const yAxis = getAxis(innerYAxisList, yAxisName, 'y')
const series = getSeries({ chartData })
const visualMap = getVisualMap({ innerMin, innerMax, type, heatColor, series, visualMapConfig })
const tooltipParams = { dataType, innerXAxisList, innerYAxisList, digit, extraMetrics, metrics }
const tooltip = tooltipVisible && getTooltip(tooltipParams)
const options = { visualMap, series, grid: { left: 25, right: 80, width: 'auto', height: 'auto' } }
let res
let args = { type, options, pointSize, blurSize, res, key, v, url, bmap, mapOrigin, geo, beforeRegisterMap }
Object.assign(args, { echarts, specialAreas, position, positionJsonLink, beforeRegisterMapOnce })
Object.assign(args, { mapURLProfix, amap, tooltip, xAxis, yAxis })
res = getResult(args)
return res
}