元数分析云是一种数据可视化分析平台,它提供了强大的故事仪表板功能,其中包括了自定义图形逻辑能力。这种能力允许用户使用常用的开源图形库进行自定义图形的展示和操作。
ECharts 是一种开源的 JavaScript 图表库,它提供了丰富的可视化图表类型和交互功能,包括折线图、柱状图、饼图、雷达图等等。元数分析云集成了 ECharts,并在故事仪表板功能中提供了自定义图形微件逻辑的能力,使用户能够以更灵活的方式创建和定制图形。
使用自定义图形逻辑能力,用户可以根据自己的需求和数据特点,通过编写 JavaScript 代码来实现图表的定制和交互。用户可以定义图表的外观样式、数据处理逻辑以及交互行为等等。
故事仪表板设计
接上一篇 范例:AdventureWorks Sales - 4. 故事仪表板 我们创建的 销售总览页面,该页面可以提供全面的销售数据分析,包括各项销售核心指标、产品相关总览分析、销售渠道总览分析。本篇我们将更深入分析销售核心指标,使用日历和热力图的方式展示销售数据,以便更好的分析销售数据的变化趋势。另外一个页面将分析互联网销售(B2C Customers)数据指标,以客户所属区域进行分解分析。
技术点
本文我们只着重介绍故事仪表板页面涉及到的技术点,包括不同页面之间的跳转、自定义图形逻辑、联动分析等功能。
页面跳转
当我们创建了更多的故事仪表板页面后,为了更好的组织页面之间的逻辑关系,我们可以通过页面跳转功能来实现。在故事仪表板页面中,我们可以通过为 关键指标微件 和 文本微件 设置页面跳转来实现。
自定义图形逻辑
通过使用自定义 ECharts 图形逻辑,我们可以灵活地定制图表的样式和展示方式。利用日历图,我们可以直观地查看销售数据在不同日期之间的分布和趋势,帮助我们发现销售高峰和低谷,以及与时间相关的销售模式。而热力图则可以将销售数据以颜色深浅的形式展示在月份与月份中第几天的二维坐标系中,帮助我们了解销售数据在月份上的热门和冷门时间日期,进一步挖掘销售机会和问题所在。
我们以销售日历为例讲解如何编写自定义图形逻辑,此图形逻辑为将具体到天的销售数据按年份进行分组,每一年的销售数据以日历坐标(Calendar coordinates )的形式用热力图的效果展示,每一个日历坐标系平均分配在图形区域中。一般情况下要查看一个财年的数据,日历坐标将会有两个,一个是下半年,一个是上半年。
接下来我们逐步介绍代码的编写过程。
1. 获取元数据信息
- 自定义脚本函数的输入参数
chartAnnotation
代表了当前图形数据的元数据信息,里面包含维度和度量字段列表。由于我们的图形需要使用时间维度和销售金额度量,所以我们需要获取这两个字段的信息并判断是否存在。 - 输入参数
utils
对象拥有一系列工具函数,包括 echarts(包括 time format 工具函数)和 ocap 工具栏函数如getEntityHierarchy
// queryResult: QueryReturn<any>, chartAnnotation: ChartAnnotation, entityType: EntityType, locale: string, chartsInstance: ECharts, echarts
const measure = chartAnnotation.measures?.[0]
const dimension = chartAnnotation.dimensions?.[0]
const { echarts, getEntityHierarchy, getPropertyCaption } = utils
if (!dimension || !measure) {
return {}
}
2. 数据处理
- 函数输入参数
queryResult
代表图形的数据查询结果,里面包含了 data 数据数组,schema 数据结构信息,以及其他一些查询信息。 - 函数输入参数
entityType
代表了多维数据集的维度和度量信息,可以用来查询维度的具体层次结构和层级信息。 - 循环数据数组将数据按年份进行分组,每一年的数据存储在
yearsData
对象中,每一年的数据是一个数组,数组中的每一项是一个对象,包含了日历坐标和销售金额度量值,还有 slicer 代表当前数据点对应的切片器,用于图形的联动分析。
const yearsData = {}
const measureData = []
// 获取维度的层次结构字段信息
const hierarchy = getEntityHierarchy(entityType, dimension)
// 获取维度成员的显示名称字段名
const caption = getPropertyCaption(hierarchy)
// Group query result data by year
queryResult.data.forEach((row) => {
const datum = row[caption]
const year = datum.substring(0, 4)
yearsData[year] = yearsData[year] || []
yearsData[year].push({
// Use dimension member caption as calendar coordinate and measure as value
value: [
datum,
row[measure.measure],
],
// 计算数据点的切片器,便于点击事件的联动分析
slicer: {
dimension,
members: [{
value: row[hierarchy.name],
caption: row[caption]
}]
}
})
// 存储所有度量值数组
measureData.push(row[measure.measure])
})
// 计算度量值范围
const min = Math.min(...measureData)
const max = Math.max(...measureData)
3.图形配置
根据数据计算结果输出 ECharts 图形配置信息
tooltip
自定义图形提示框信息输出的格式visualMap
热力图的颜色视觉映射配置,包括最大值、最小值、位置等,颜色范围可以根据 measure 的调色板配置的 colors 属性或默认值calendar
日历坐标系配置,每一年对应一个坐标系,坐标系位置平均分布在图形范围内series
图形数据,以对应的日历为坐标系,使用 heatmap 展示类型
const formatUtil = echarts.format;
const years = Object.keys(yearsData).sort()
const options = {
tooltip: {
position: 'top',
formatter: (p) => {
// 提示框信息输出
return `<b>${p.data.value[0]}</b>` + ': ' + formatUtil.addCommas(p.data.value[1]?.toFixed(2))
}
},
// 热力图的颜色视觉映射配置
visualMap: {
min,
max,
calculable: true,
type: 'piecewise',
orient: 'horizontal',
left: 'center',
bottom: '10',
precision: 1,
// Measure palette colors as visualMap color
inRange: measure.palette?.colors ? {
color: measure.palette?.colors
} : null
},
// Calendar coordinate per year
calendar: years.map((year, i) => {
return {
range: year,
top: (i * (100 / years.length) + 15) + '%',
left: 30,
right: 20,
yearLabel: {
show: true,
position: 'top'
}
}
}),
// Heatmap series per year corresponding to calendar coordinate
series: years.map((year, i) => {
return {
type: 'heatmap', // 热力图类型
coordinateSystem: 'calendar', // 日历坐标系
calendarIndex: i, // 日历坐标系索引
data: yearsData[year] // 数据序列数组
}
})
};
4. 响应图形事件
自定义图形逻辑传入了 ECharts 的图形实例,所以可以通过 ECharts 的事件机制来响应图形的各类事件,下面逻辑响应鼠标 hover 事件以高亮当月数据点,鼠标移出事件取消高亮。
chartsInstance?.off('mouseover')
chartsInstance?.on('mouseover', (event) => {
chartsInstance.dispatchAction({
type: 'highlight',
seriesIndex: event.seriesIndex,
// 月份相同的数据点高亮
dataIndex: options.series[event.seriesIndex].data.map((item,i) => {
return item.value[0].substring(0, 7) === event.data.value[0].substring(0, 7) ? i : null
}).filter((i) => i !== null)
})
})
chartsInstance?.off('mouseout')
chartsInstance?.on('mouseout', (event) => {
chartsInstance.dispatchAction({
type: 'downplay',
})
})
5. 脚本返回结果
return
函数最终返回的数据类型为 {options: EChartOption, onClick: (event) => {...event, slicers: Slicer[]}}
options
为 ECharts 图形配置onClick
为图形点击事件回调函数,返回的 event 对象包含了原始的 ECharts 事件对象,以及 slicers 切片器数组,用于图形的联动分析
return {
options
}
图形变体
图形微件的图形变体 可以使得一个图形微件的同一数据展示为不同的表现形式,以便用户可以根据需要自行选择查看的图形类型。
总结
本文介绍了元数分析云中故事仪表板的自定义图形逻辑功能,并以 AdventureWorks Sales 数据集为例进行了说明。通过集成开源图表库 ECharts,用户可以使用自定义图形逻辑功能创建和定制图表,灵活展示和操作数据。