前言

最近公司让做一个数据看板,主要统计公司主站的订单、用户注册量以及用户访问量等数据。

数据看板

前面部分的订单都可以直接写个查询接口显示数据,后面的订单类型、用户注册量、用户访问量则涉及到可视化图表的使用。作为 web 图表库,highcharts 是我了解的前端库里的不二之选。

Highcharts 文档教程 Highcharts API 详解

这里面三个图表分别用了三种不同类型的图表来展示,分别是饼状图(pie)、柱状图(column)、直线图(line)。花了一天的时间去熟悉 highcharts 图表使用,以下针对使用过程中的细节点的总结。

highcharts 初始化方法

一种是官方网站使用的 Highcharts.chart('id', options)

        // 图表配置
        var options = {
            chart: {
                type: 'bar'                          //指定图表的类型,默认是折线图(line)
            },
            title: {
                text: '我的第一个图表'                 // 标题
            },
            xAxis: {
                categories: ['苹果', '香蕉', '橙子']   // x 轴分类
            },
            yAxis: {
                title: {
                    text: '吃水果个数'                // y 轴标题
                }
            },
            series: [{                              // 数据列
                name: '小明',                        // 数据列名
                data: [1, 0, 4]                     // 数据
            }, {
                name: '小红',
                data: [5, 7, 3]
            }]
        };
        // 图表初始化函数
        var chart = Highcharts.chart('container', options);

另外一种是在寻找解决方案的时候发现的 $('#container').highcharts(options)

两种都可以使用,前者是通过 Highcharts 类方法 chart() 创建对象,后者是用 jQuery 对象的实例方法 highcharts() 创建对象。显而易见,后者使用时必须要加载 jQuery。

图表类型标识

有三个属性都可以标识当前图标类型:chart.typeplotOptions.xxxseries[0].typechart.type 是最直接的图表属性标识,plotOptions 下每个对象都标识不同的图表数据列配置,series[0].type 是数据列中进行声明。三个地方都没有明确标识的,会默认初始化为 line (直线)类型。

隐藏图表右下角 highcharts 版权信息

版权信息默认是展示的,可以通过 credits 配置隐藏:

...
credits: {
    enabled:false,
},
...

标题、刻度标签、数据标签样式设置

标题分为总标题(title)、x 轴标题(xAxis.title)、y 轴标题(yAxis.title),刻度标签有 x 轴刻度标签(xAxis.labels)、y 轴刻度标签(yAxis.labels),提示工具 tooltip,数据标签 plotOptions.xxx.dataLabels。这些文本类型的属性,都可以通过他们的 style 属性进行设置字体颜色、字体大小等等样式。下面是以总标题 title 为例:

...
title: {
    text: '总标题',
    style: {
        'color': '#fff',
        'fontSize': 18,
    },
},
...

图表颜色设置

这里指图表主体的颜色,比如柱状图柱子的颜色,饼状图中每一块扇形的颜色。highcharts 默认是有一整套颜色的,也就是说如果不设置颜色 colors 属性,也是默认会显示不同颜色的。此外 plotOptions 下有些类型的图表还可以针对数据点(point)进行设置颜色,比如 plotOptions.column.colors。要想数据列配置项下的图表颜色配置生效,需要将其下的 colorByPoint 设置为 true,即 plotOptions.column.colorByPoint: true。如果设置的颜色数组元素个数不够(比展示数据少),highcharts 会循环使用数组中的颜色。

在柱状图中,内外设置的颜色都使用在了柱状图上,而在直线图中,外部颜色应用在不同的 series 数据列上,内部颜色用在了数据点(point)上。

图表渐变颜色设置

这个是在网上找的教程,参考了两个:HighCharts 柱状图设置渐变色highcharts 柱状图设置颜色渐变的效果

第一个教程核心代码摘录:

var colors = ['#F59656', '#90BF18', '#EDCA4E'];

Highcharts.getOptions().colors = Highcharts.map(colors, function (color) {
    return {
        radialGradient: { cx:0, cy: -0.8,r:2.3 },
        stops: [[0, color], [1, Highcharts.Color(color).brighten(14).get('rgb')] // darken
        ]
    };
});

这种属于全局设置,需要在初始化图表之前调用,图表初始化后调用无效,回调函数内调用无效。radialGradient 的 cx 属性和 cy 属性分别控制左右和上下方向的渐变。因为是需要的是上下渐变,所以 cx 设置为 0,cy 负值表示从上到下渐变,正值表示从下到上渐变,stops 中的两个颜色,0 表示渐变起始颜色,1 表示渐变结束颜色。r 不清楚具体含义,但调节大小(非负)可以使渐变范围增大或者减小,猜测是渐变半径的意思(没有找到这种定义方式的出处)。brighten(14) 表示颜色变浅,负值表示颜色加深。这样一个颜色可以从深到浅,或者从浅到深,实现颜色渐变的效果。也可以取两种不同深浅的颜色,将 colors 设置成二维数组,取值后分别设置 stops 中 0、1 不同颜色。

通过测试发现,还可以将其放到 highcharts 图表初始化配置中:

var colors = ['#F59656', '#90BF18', '#EDCA4E'];
Highcharts.chart('container',{

...

colors: Highcharts.map(colors, function (color) {
    return {
        radialGradient: { cx: 0, cy: -0.8, r: 2.3 },
        stops: [[0, color], [2, Highcharts.Color(color).brighten(14).get('rgb')] // darken
        ]
    };
}),

...

或者(这里以柱状图为例)

var colors = ['#F59656', '#90BF18', '#EDCA4E'];
Highcharts.chart('container',{

...

plotOptions: {
    column: {
        colorByPoint: true,
        colors: Highcharts.map(colors, function (color) {
            return {
                radialGradient: { cx:0, cy: -0.8,r:2.3 },
                stops: [[0, color], [1, Highcharts.Color(color).brighten(14).get('rgb')] // darken
                ]
            };
        }),
    }
},
...

第二个教程核心代码摘录:

    var colorArr = [['#7C39B0', '#DF8EE6'], ['#2C1EAF', '#00BCEC']];
    var chart;
    Highcharts.chart('container', options, function (c) {
            SetEveryOnePointColor(c);
            chart = c;
        });
    }
    //设置每一个数据点的颜色值
    function SetEveryOnePointColor(chart) {
        //获得第一个序列的所有数据点
        var series = chart.series;
        for (var j = 0; j < series.length; j++) {
            var pointsList = series[j].points;
            //遍历设置每一个数据点颜色
            for (var i = 0; i < pointsList.length; i++) {
                series[j].points[i].update({
                    color: {
                        //横向渐变效果 如果将x2和y2值交换将会变成纵向渐变效果
                        linearGradient: {x1: 0, y1: 1, x2: 0, y2: 0}, 
                        stops: [
                            [0, Highcharts.Color(colorArr[j][0]).setOpacity(1).get('rgba')],
                            [1, Highcharts.Color(colorArr[j][1]).setOpacity(1).get('rgba')]
                        ]
                    }
                });
            }
        }
    }

这种是在图表初始化之后去更新图表点的数据(上面提到过,柱状图点的颜色与外部 colors 都作用于柱状图本身,所以也适用)。在图表的回调函数内,执行更新数据点颜色的操作。原文评论区有人说这个方法对性能消耗比较大,这个不确定,当前的目标是显示颜色渐变的效果。linearGradient 中 x1、x2 都为 0 表示横向上没有渐变,y1 > 0, y2 < 0 表示从下到上渐变,反之就是从上到下渐变。stops 中采用了前面提到的二维数组取点颜色设置,0 表示渐变起始颜色,1 表示渐变结束颜色。

两种方法都尝试过,都是可行的。

数据列与数据更新

这里以柱状图为例。

从官网的入门 demo 中可以看到,需要更新的数据有两个部分:xAxis.categoriesseriesxAxis.categories 就是一数组,里面存放的是 x 轴刻度上展示的数据,正常的如日期或者一些类型字符串,表示一个维度上的变化。y 轴上的刻度数据是根据数据列 series[xx].data[xx].y 数值范围自动生成。图表主体则是一系列的点位数据生成的,在某某一点位上 {point.name} 就是 series[xx].name{point.y} 就是 series[xx].data[xx].y

当 series 存在多项数据时,柱状图每一个点位上就会有多个矩形柱,对应在直线图中就是多条折线。

更新数据:

chart.xAxis[0].categories = data.date;
chart.series[0].update(data.series[0]);
chart.series[1].update(data.series[1]);
// 或者
var obj = data.series[0];
chart.series[0].update({name:obj.name,data:obj.data});

数据列中数据条数较少时可以直接这么赋值,多了可以遍历。