简单粗暴地上code:
const chartOptionsGeneration = (data) => {
const options = {
toolbox: {
y: 'bottom',
feature: {
dataView: {show: true, readOnly: false},
restore: {show: true},
saveAsImage: {show: true}
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: []
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: '5%',
containLabel: true
},
yAxis: {
type: 'value'
},
xAxis: {
type: 'category',
// triggerEvent: true,
// formatter: function(value) {
// return (value.length > 10 ? (value.slice(0,5)+"...") : value )
// },
axisTick: {
alignWithLabel: true
},
axisLabel: {
interval: 0,
rotate: 15,
textStyle: {
color: '#000',
fontSize: 10
}
},
data: []
},
series: []
}
options['legend']['data'] = data['legend'];
options['series'] = data['series']
options['xAxis']['data'] = data['x_axis'].sort((prev, post) => {
// get sum of fail for the same x_axis: loop series, get data of each series item, if it contains this xaxis, get its yaxis
// prev and post are both x_axis
console.log(prev, post)
const prev_y_num = data[by]['series'].reduce((total_fail, item) =>{
return total_fail + item['data'].reduce( (fail, point) =>{
if(point[0] === prev){
return fail + point[1]
}else{
return fail;
}
} , 0);
}, 0)
const post_y_num = data['series'].reduce((total_fail, item) =>{
return total_fail + item['data'].reduce( (fail, point) =>{
if(point[0] === post){
return fail + point[1]
}else{
return fail;
}
} , 0);
}, 0)
console.log(prev_y_num, post_y_num)
return post_y_num - prev_y_num;
});
return options
}
所需的数据结构如下:
data = {
'legend': ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎'],
'x_axis': ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
'series': [
{
name: '直接访问',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周一',320],['周三', 302]]
},
{
name: '邮件营销',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周四',320],['周三', 302], ['周二',320],['周六', 302]]
},
{
name: '联盟广告',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周二',320],['周一', 302], ['周三',320],['周五', 302]]
},
{
name: '视频广告',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周一',320],['周三', 302], ['周二',320],['周四', 302]]
},
{
name: '搜索引擎',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周五',320],['周四', 302], ['周一',320],['周三', 302]]
}
]
}
解释一下为啥要这么做。
首先如果不做任何处理,直接使用上面的数据生成chart,会长什么样呢?
那么,如果我们想要做到按照每根柱子的高度来从高到低排序,要怎么做呢?
就是要重排xAxis中的值,根据是xAxis中每个值对应的柱子高。
那么,我们要做的就是,遍历原xAxis的值(存放于data['x_axis']),对于每一个x值,取出series中每一个元素的值数组(如data['series'][0]['data'])。这个值数组中的每个元素都是一个数组,其中第一个值是横坐标值,第二个值是在y轴上的高度,那么如果这个值数组里头包含了当前的x值,把它找出来,对应的y值加起来。
把series中的每一个元素都这么操作一遍,就能找出某个x值的柱高。
对所有的x值都操作一遍,就能找出所有x值对应的柱高。
之后就sort一下就行了。
结果:
完整的例子。copy到echarts的实例里就可以用。比如https://echarts.apache.org/examples/zh/editor.html?c=bar-y-category-stack
option = {
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
yAxis: {
type: 'value'
},
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
},
series: [
{
name: '直接访问',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周一',320],['周三', 302]]
},
{
name: '邮件营销',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周四',320],['周三', 302], ['周二',320],['周六', 302]]
},
{
name: '联盟广告',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周二',320],['周一', 302], ['周三',320],['周五', 302]]
},
{
name: '视频广告',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周一',320],['周三', 302], ['周二',320],['周四', 302]]
},
{
name: '搜索引擎',
type: 'bar',
stack: '总量',
label: {
show: true,
position: 'insideRight'
},
data: [['周五',320],['周四', 302], ['周一',320],['周三', 302]]
}
]
};
//为了适应echarts的实例运行环境,对code做了小小的修改。不影响大局。
option['xAxis']['data'] = option['xAxis']['data'].sort((prev, post) => {
// get sum of fail for the same x_axis: loop series, get data of each series item, if it contains this xaxis, get its yaxis
// prev and post are both x_axis
console.log(prev, post)
const prev_y_num = option['series'].reduce((total_fail, item) =>{
return total_fail + item['data'].reduce( (fail, point) =>{
if(point[0] === prev){
return fail + point[1]
}else{
return fail;
}
} , 0);
}, 0)
const post_y_num = option['series'].reduce((total_fail, item) =>{
return total_fail + item['data'].reduce( (fail, point) =>{
if(point[0] === post){
return fail + point[1]
}else{
return fail;
}
} , 0);
}, 0)
console.log(prev_y_num, post_y_num)
return post_y_num - prev_y_num;
});
PS:
这个例子使用了echarts的官方例子的数据(我当然不可能用公司的真实数据写博客♪(^∇^*)),但我做了小小的修改。原本的数据是这样婶儿的:
原例子中,series的data是一维数组,顺序是与yAxis中值的顺序一一对应(为啥是yAxis?因为人家的图xy跟我的例子是反过来的呀┓( ´∀` )┏),我觉得这样不太灵活,就写成了二维数组的形式。这是从折线图里来的,用二维数组来表示一个点的xy值。echats这点做得很好,很多东西都是通的,这样就可以不用太教条,合理推导就能得到我们想要的东西。