在数据可视化的项目中,会遇到大量的数据格式化的工作。为了减轻后端同学数据格式化的工作,我们前后端共同制定了一套格式化方案。后端提供格式化方式,由前端来负责格式化处理。
下面的代码,我采用简写的方式来整理出了一些常用格式化类型。这样无论是后端提供类型让前端数据格式化,还是前开发中直接用于格式化,都变得很方便。
特别注意:在格式化数据时尤其要注意四舍五入的问题。我采用的 numeral 库是进行了四舍五入操作的。
下面是我格式化工具函数:
import numeral from 'numeral'
/**
* 通用的格式化数据方式
*
* N - normal
* P - percent
* TI - time
* S - second
* MS - millisecond
* C - currency
* T - thousand
* M - ten thousand
* U - unit
* 1 - decimal
*/
export const formatData = (data, formatType) => {
if (data === null || data === undefined) {
return '-'
}
const numberData = Number(data)
if (Number.isNaN(numberData)) {
return data
}
switch (formatType) {
case 'N':
return data
case 'P':
return formatPercent(data, 0)
case 'P1':
return formatPercent(data, 1)
case 'P2':
return formatPercent(data, 2)
case 'TIMS':
return formatMillisecond(numberData)
case 'TIS':
return formatSecond(numberData)
case 'T':
return numeralFormat(numberData, 0)
case 'T1':
return numeralFormat(numberData, 1)
case 'T2':
return numeralFormat(numberData, 2)
case 'TU':
return formatThousandsSuffixUnit(numberData, 0)
case 'CT':
return `¥${numeralFormat(numberData, 0)}`
case 'CT1':
return `¥${numeralFormat(numberData, 1)}`
case 'CT2':
return `¥${numeralFormat(numberData, 2)}`
case 'CTU':
return `¥${formatThousandsSuffixUnit(numberData, 0)}`
case 'MU':
return formatMyriadSuffixUnit(numberData, 0)
case 'MU2':
return formatMyriadSuffixUnit(numberData, 2)
case 'CMU':
return `¥${formatMyriadSuffixUnit(numberData, 0)}`
case 'CMU2':
return `¥${formatMyriadSuffixUnit(numberData, 2)}`
default:
return data
}
}
function numeralFormat (value, decimal) {
let formatStr = '0,0'
if (decimal > 0) {
formatStr += '.'
for (let i = 0; i < decimal; i++) {
formatStr += '0'
}
}
return numeral(value).format(formatStr)
}
function formatPercent (value, decimal) {
return numeralFormat(value * 100, decimal) + '%'
}
function formatMillisecond (value) {
return formatSecond(parseInt(value) / 1000)
}
function formatSecond (value) {
const result = parseInt(value)
const h =
Math.floor(result / 3600) < 10
? '0' + Math.floor(result / 3600)
: Math.floor(result / 3600)
const m =
Math.floor((result / 60) % 60) < 10
? '0' + Math.floor((result / 60) % 60)
: Math.floor((result / 60) % 60)
const s =
Math.floor(result % 60) < 10
? '0' + Math.floor(result % 60)
: Math.floor(result % 60)
return `${h}:${m}:${s}`
}
const formatThousandsSuffixUnit = (value, decimal = 0) => {
let val = Math.abs(value)
const sign = value >= 0 ? '' : '-'
let suffix = ''
if (val >= 1000) {
val = val / 1000
suffix = 'K'
}
if (val >= 1000) {
val = val / 1000
suffix = 'M'
}
if (val >= 1000) {
val = val / 1000
suffix = 'B'
}
return sign + numeralFormat(val, decimal) + suffix
}
const formatMyriadSuffixUnit = (value, decimal = 0) => {
let val = Math.abs(value)
const sign = value >= 0 ? '' : '-'
let suffix = ''
if (val >= 10000) {
val = val / 10000
suffix = '万'
}
if (val >= 10000) {
val = val / 10000
suffix = '亿'
}
if (val >= 10000) {
val = val / 10000
suffix = '万亿'
}
return sign + numeralFormat(val, decimal) + suffix
}
下面是实际效果:

chart 的格式化
之前说过,数据可视化项目大多数情况下就 chart 和 table 勒种类型的数据。其中,table 的格式化相对简单,针对每一列提供它的格式化方式即可。而对于 chart 会有不少地方需要格式化。下面我以我项目中用到的 g2plot 为例:
- x 轴 label 格式化
- y 轴 label 格式化
- tooltip 的 item 格式化
- label 格式化
- annotations 文本标记格式化
- statistic 环图的统计文本
对于这种情况,我们根据 chart 本身的属性以及业务需求制定了一些 chart 的格式化组合,这是一组格式化类型数组,分别代表 chart 各部分数据的格式化方式。这就是 getFormatTypesForChartType 这个函数的由来。
export const getFormatTypesForChartType = chartType => {
switch (chartType) {
case 'currency':
return ['CMU', 'CT2', 'CT2', 'CT2']
case 'ratio':
return ['P', 'P2', 'P2', 'P2']
case 'absolute':
return ['KU', 'K', 'K', 'K']
case 'avarage':
return ['K', 'K2', 'K2', 'K2']
case 'time':
return ['TIMS', 'TIMS', 'TIMS', 'TIMS']
default:
return ['N', 'N', 'N', 'N']
}
}
最后
这是我目前的格式化方案,提供一种思路。
按理说应该会有现成的库去提供类似的功能,不过目前来说自己写的工具函数够用了。
网友评论