echarts3实现柱状图和饼图详解

本篇文章实现的是以下两种需求:

1,使用Echarts3实现柱状图;

2,使用Echarts3实现饼图;

包含Echarts使用过程中遇到的部分坑的解决办法。


先上效果图:


(PS:饼图实际上是圆的,以上图片是被压缩了)


进入正题,下面是具体实践:

图表实现使用的是Echarts,Echarts官网地址为:http://echarts.baidu.com/examples.html


一,准备工作

1)获取Echarts

以下为官网推荐的几种获取 ECharts方式:

  1. 官网下载界面选择你需要的版本下载,根据开发者功能和体积上的需求,我们提供了不同打包的下载,如果你在体积上没有要求,可以直接下载完整版本。开发环境建议下载源代码版本,包含了常见的错误提示和警告。

  2. 在 ECharts 的 GitHub 上下载最新的 release 版本,解压出来的文件夹里的 dist 目录里可以找到最新版本的 echarts 库。

  3. 通过 npm 获取 echarts,npm install echarts --save,详见“在 webpack 中使用 echarts

  4. cdn 引入,你可以在 cdnjsnpmcdn 或者国内的 bootcdn 上找到 ECharts 的最新版本。

我是采用的第一种方式,直接去官网下载的。下载页面为 http://echarts.baidu.com/download.html


2)引入Echarts

ECharts 3 开始不再强制使用 AMD 的方式按需引入,代码里也不再内置 AMD 加载器。因此引入方式简单了很多,只需要像普通的 JavaScript 库一样用 script 标签引入。

下载后使用script标签引入:

<script src="pages/asset/echarts.min.js"></script>


二,具体实现

以我的demo为例,直接贴代码吧。

1)使用到的样式

.canvas_pie_chart{
    height: 90%;
    width: 90%;
    margin-left: 5%;
    margin-right: 5%;
}

.asset_pie_back{
    position: absolute;
    width: 2rem;
    height: 2rem;
    top: 6.5rem;
    left: 0.5rem;
    z-index: 99;
    display: none;
}


2)页面布局

        <!-- 为ECharts准备一个具备大小(宽高)的Dom -->
        <div id="asset_chart_bar" style="width: 100%;height:90%;"></div>
        <div id="asset_chart_pie" style="width: 100%;height:90%;"></div>
        <img src="images/query/search_clear.png" class="asset_pie_back">


3)js实现

var assetStatics = function () {

    var assetChartPie, assetChartBar, color_list;

    function beforeInit(p) {
        initData();
    }

    function init(p) {
        // 基于准备好的dom,初始化echarts实例
        assetChartPie = echarts.init(document.getElementById('asset_chart_pie'));

        assetChartBar = echarts.init(document.getElementById('asset_chart_bar'));

        $$('#asset_chart_pie').find("canvas").addClass('canvas_pie_chart');

        bindEvent("on");
    }

    function destroy(p) {
        bindEvent("off");
    }

    /*
     * 获取数据
     * */
    function initData() {
        color_list = ['#96CEEA', '#7BD6B1', '#4EA8F2', '#FF9566', '#F9E385', '#9C6448',
            '#FFBC6C', '#9E96EA', '#9EEA42', '#A1B1BE', '#96CEEA', '#7BD6B1',
            '#4EA8F2', '#FF9566', '#F9E385', '#9C6448', '#FFBC6C', '#9E96EA',
            '#9EEA42', '#A1B1BE', '#96CEEA', '#7BD6B1', '#4EA8F2', '#FF9566',
            '#F9E385', '#9C6448', '#FFBC6C', '#9E96EA', '#9EEA42', '#A1B1BE'];
    }

    /*
     * 绑定事件
     * */
    function bindEvent(method) {
        if (method == "on") {
            /*
            * 柱状图item项点击事件
            * 从seriesId获取当前item项id,然后可根据此id获取需要的数据
            * */
            assetChartBar.on('click', function (params) {
                // console.log(params);
                var resource_ids = params.seriesId;
                var item_index = params.dataIndex;
                var resource_id = resource_ids.split(',')[item_index];
                switchToPieChart(resource_id);
            });

            /*
             * 饼状图返回按钮
             * 返回到柱状图
             * */
            $$(document).on('click', '.asset_pie_back', function () {
                $$('#asset_chart_bar').css("display", "block");
                $$('#asset_chart_pie').css("display", "none");
                $$('.asset_pie_back').css("display", "none");
            });

            assetChartPie.on('click', function (params) {
            });

            // 图例开关的行为只会触发 legendselectchanged 事件
            assetChartPie.on('legendselectchanged', function (params) {
                // 获取点击图例的选中状态
                var isSelected = params.selected[params.name];
                // 在控制台中打印
                console.log((isSelected ? '选中了' : '取消选中了') + '图例' + params.name);
                // 打印所有图例的状态
                console.log(params.selected);
            });

            assetChartPie.on('legendselected', function (params) {

            });

            assetChartPie.on('legendunselected', function (params) {

            });
        }
    }

    /*
     * 显示饼图
     * */
    function showPieChart(data) {
        var option_pie_chart = {
            // 全图默认背景
            backgroundColor: 'rgba(0,0,0,0)',
            // 默认色板
            color: data.color_list,
            // 图表标题
            title: {
                show: false,
                x: 'center',                 // 水平安放位置,默认为左对齐,可选为:'center' ¦ 'left' ¦ 'right' ¦ {number}(x坐标,单位px)
                y: 45,                  // 垂直安放位置,默认为全图顶端,可选为:'top' ¦ 'bottom' ¦ 'center' ¦ {number}(y坐标,单位px)
                //textAlign: null          // 水平对齐方式,默认根据x设置自动调整
                backgroundColor: 'rgba(0,0,0,0)',
                borderColor: '#ccc',       // 标题边框颜色
                borderWidth: 0,            // 标题边框线宽,单位px,默认为0(无边框)
                padding: 5,                // 标题内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距,同css
                itemGap: 10,               // 主副标题纵向间隔,单位px,默认为10,
                textStyle: {
                    fontSize: 18,
                    fontWeight: 'bolder',
                    color: '#333'          // 主标题文字颜色
                },
                subtextStyle: {
                    color: '#aaa'          // 副标题文字颜色
                },
                text: data.title
            },
            // 图例
            legend: {
                orient: 'horizontal',      // 布局方式,默认为水平布局,可选为:'horizontal' ¦ 'vertical'
                x: 'center',               // 水平安放位置,默认为全图居中,可选为:'center' ¦ 'left' ¦ 'right' ¦ {number}(x坐标,单位px)
                y: 'bottom',                  // 垂直安放位置,默认为全图顶端,可选为:'top' ¦ 'bottom' ¦ 'center' ¦ {number}(y坐标,单位px)
                backgroundColor: 'rgba(0,0,0,0)',
                borderColor: '#ccc',       // 图例边框颜色
                borderWidth: 0,            // 图例边框线宽,单位px,默认为0(无边框)
                padding: 5,                // 图例内边距,单位px,默认各方向内边距为5,
                                           // 接受数组分别设定上右下左边距,同css
                itemGap: 10,               // 各个item之间的间隔,单位px,默认为10,
                                           // 横向布局时为水平间隔,纵向布局时为纵向间隔
                itemWidth: 20,             // 图例图形宽度
                itemHeight: 14,            // 图例图形高度
                textStyle: {
                    color: '#333'          // 图例文字颜色
                },
                data: data.detail
            },
            // 提示框
            tooltip: {
                trigger: 'item',           // 触发类型,默认数据触发,见下图,可选为:'item' ¦ 'axis'
                showDelay: 20,             // 显示延迟,添加显示延迟可以避免频繁切换,单位ms
                hideDelay: 100,            // 隐藏延迟,单位ms
                transitionDuration: 0.4,  // 动画变换时间,单位s
                backgroundColor: 'rgba(0,0,0,0.7)',     // 提示背景颜色,默认为透明度为0.7的黑色
                borderColor: '#333',       // 提示边框颜色
                borderRadius: 4,           // 提示边框圆角,单位px,默认为4
                borderWidth: 0,            // 提示边框线宽,单位px,默认为0(无边框)
                padding: 5,                // 提示内边距,单位px,默认各方向内边距为5,
                                           // 接受数组分别设定上右下左边距,同css
                axisPointer: {            // 坐标轴指示器,坐标轴触发有效
                    type: 'line',         // 默认为直线,可选为:'line' | 'shadow'
                    lineStyle: {          // 直线指示器样式设置
                        color: '#48b',
                        width: 2,
                        type: 'solid'
                    },
                    shadowStyle: {                       // 阴影指示器样式设置
                        width: 'auto',                   // 阴影大小
                        color: 'rgba(150,150,150,0.3)'  // 阴影颜色
                    }
                },
                textStyle: {
                    color: '#fff'
                },
                formatter: "{a} <br/>{b}: {c} ({d}%)"
            },
            series: [
                {
                    name: '植物分类统计',
                    type: 'pie',
                    center: ['50%', '50%'],    // 默认全局居中
                    radius: ['40%', '55%'],     //环
                    clockWise: false,          // 默认逆时针
                    startAngle: 90,
                    minAngle: 0,                // 最小角度改为0
                    selectedOffset: 10,         // 选中是扇区偏移量
                    itemStyle: {
                        normal: {
                            // color: 各异,
                            borderColor: '#fff',
                            borderWidth: 1,
                            label: {
                                show: true,
                                position: 'outer'
                                // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
                            },
                            labelLine: {
                                show: true,
                                length: 20,
                                lineStyle: {
                                    // color: 各异,
                                    width: 1,
                                    type: 'solid'
                                }
                            }
                        },
                        emphasis: {
                            // color: 各异,
                            borderColor: 'rgba(0,0,0,0)',
                            borderWidth: 1,
                            label: {
                                show: true,
                                position: 'outer'
                                // textStyle: null      // 默认使用全局文本样式,详见TEXTSTYLE
                            },
                            labelLine: {
                                show: true,
                                length: 20,
                                lineStyle: {
                                    // color: 各异,
                                    width: 1,
                                    type: 'solid'
                                }
                            }
                        }
                    },
                    data: data.detail
                }
            ]
        };
        assetChartPie.showLoading();
        //调整饼图参数
        option_pie_chart = adjustPieChartOption(data, option_pie_chart);
        assetChartPie.setOption(option_pie_chart, true);
        assetChartPie.hideLoading();
    }

    /*
     * 显示柱状图
     * */
    function showBarChart(data) {
        var option_bar_chart = {
            // 全图默认背景
            backgroundColor: 'rgba(0,0,0,0)',
            // 默认色板
            color: data.color_list,
            // 图表标题
            title: {
                show: false,
                x: 'center',                 // 水平安放位置,默认为左对齐,可选为:'center' ¦ 'left' ¦ 'right' ¦ {number}(x坐标,单位px)
                y: 'top',                  // 垂直安放位置,默认为全图顶端,可选为:'top' ¦ 'bottom' ¦ 'center' ¦ {number}(y坐标,单位px)
                //textAlign: null          // 水平对齐方式,默认根据x设置自动调整
                backgroundColor: 'rgba(0,0,0,0)',
                borderColor: '#ccc',       // 标题边框颜色
                borderWidth: 0,            // 标题边框线宽,单位px,默认为0(无边框)
                padding: 5,                // 标题内边距,单位px,默认各方向内边距为5,接受数组分别设定上右下左边距,同css
                itemGap: 10,               // 主副标题纵向间隔,单位px,默认为10,
                textStyle: {
                    fontSize: 18,
                    fontWeight: 'bolder',
                    color: '#333'          // 主标题文字颜色
                },
                subtextStyle: {
                    color: '#aaa'          // 副标题文字颜色
                },
                text: data.title
            },
            tooltip: {
                trigger: 'axis',
                axisPointer: {            // 坐标轴指示器,坐标轴触发有效
                    type: 'line',        // 默认为直线,可选为:'line' | 'shadow'
                    label: {
                        show: false
                    }
                }
            },
            calculable: true,
            grid: {
                left: '3%',
                right: '4%',
                bottom: '3%',
                containLabel: true
            },
            xAxis: [
                {
                    type: 'category',
                    data: data.x_axis,
                    axisTick: {
                        alignWithLabel: true
                    },
                    axisLabel: {
                        formatter: function (val) {
                            //x轴标签文字纵向排列,解决x轴标签过长时,柱状图部分item项不显示
                            return val.split("").join("\n");
                        }
                    }
                }
            ],
            yAxis: [
                {
                    name: '树木数',
                    type: 'value'
                }
            ],
            dataZoom: [
                {
                    //是否显示左侧收缩提示条
                    show: false,
                    start: 0,
                    end: 100
                },
                {
                    type: 'inside',
                    start: 0,
                    end: 100
                },
                {
                    //是否显示右侧收缩提示条
                    show: false,
                    yAxisIndex: 0,
                    filterMode: 'empty',
                    width: 30,
                    height: '80%',
                    showDataShadow: false,
                    left: '93%'
                }
            ],
            series: [
                {
                    name: '植物数',
                    type: 'bar',
                    center: ['50%', '50%'],    // 默认全局居中
                    barWidth: '25%',
                    barMaxWidth: 25,//最大宽度
                    data: data.y_axis,
                    id: data.id_arr,
                    itemStyle: {
                        //修改颜色
                        normal: {
                            color: function (params) {
                                return data.color_list[params.dataIndex]
                            },
                            //bar上显示的提示信息
                            label: {
                                show: true,
                                position: 'top',
                                formatter: '{c}'
                            }
                        }
                    }
                }
            ]
        };
        assetChartBar.showLoading();
        //调整柱状图参数
        option_bar_chart = adjustBarChartOption(data, option_bar_chart);
        //注意此处:echarts默认为merge,以下setOption会导致数据组合呈现,会同时显示本次和上次的数据
        // assetChartBar.setOption(option_bar_chart);
        //设置为true即可只使用新数据
        assetChartBar.setOption(option_bar_chart, true);
        assetChartBar.hideLoading();
    }

    /*
     * 根据当前所选切换表格视图
     * */
    function switchChartView(type) {
        if (type == 'bar') {
            switchToBarChart();
        } else {
            switchToPieChart();
        }
    }

    /*
     * 切换到柱状图视图
     * */
    function switchToBarChart(data) {
        $$('#asset_chart_bar').css("display", "block");
        $$('#asset_chart_pie').css("display", "none");
        $$('.asset_pie_back').css("display", "none");
        assembleDataForBarChart(data, function (bar_data) {
            console.log(bar_data);
            showBarChart(bar_data);
        });
    }

    /*
     * 切换到饼状图视图
     * */
    function switchToPieChart(data) {
        $$('#asset_chart_bar').css("display", "none");
        $$('#asset_chart_pie').css("display", "block");
        $$('.asset_pie_back').css("display", "block");
        assembleDataForPieChart(data, function (pie_data) {
            console.log(pie_data);
            showPieChart(pie_data);
        });
    }

    /*
     * 为饼图组装数据
     * 假数据
     * */
    function assembleDataForPieChart(data, _callback) {
        var pie_detail = [
            {
                name: '椰树',
                value: 85
            },
            {
                name: '榕树',
                value: 156
            },
            {
                name: '桂花树',
                value: 684
            },
            {
                name: '菠萝蜜',
                value: 48
            },
            {
                name: '木棉树',
                value: 62
            },
            {
                name: '四季树',
                value: 37
            },
            {
                name: '其他',
                value: 76
            }
        ];
        var pie_data = {
            title: '分类统计',
            color_list: color_list,
            detail: pie_detail
        }
        _callback(pie_data);
    }

    /*
     * 为柱状图组装数据
     * 假数据
     * */
    function assembleDataForBarChart(data, _callback) {
        var bar_id_arr = ['0_1', '0_2', '0_3', '0_4', '0_5', '0_6', '0_7', '0_8', '0_9', '0_10', '0_11', '0_12'];
        var bar_x_arr = ['园区1', '园区2', '园区3', '园区4', '园区5', '园区6', '园区7', '园区8', '园区9', '园区10', '园区11', '园区12'];
        var bar_y_arr = [895, 652, 485, 785, 123, 584, 74, 555, 256, 888, 777, 520];
        var bar_data = {
            title: '植物统计',
            color_list: color_list,
            id_arr: bar_id_arr,
            x_axis: bar_x_arr,
            y_axis: bar_y_arr
        };
        _callback(bar_data);
    }

    /*
     * 根据柱状图item项数量调整柱状图显示参数(柱状图item宽度、显示X轴item项显示数量、柱状图item项颜色等)
     * 避免柱状图item项太少时柱状图item项宽度太大,柱状图item项太多时柱状图item项宽度太小,难看
     * 这里是简单测试,可根据需求自行调整
     * */
    function adjustBarChartOption(data, option) {
        var count = data.x_axis.length;
        //柱状图item宽度
        var percent_show = 100;
        if (count < 11) {
            percent_show = 100;
        } else if (count > 10 && count < 21) {
            percent_show = percent_show * 0.8;
            option.series[0].barWidth = '40%';
        } else if (count > 20 && count < 31) {
            percent_show = percent_show * 0.45;
            option.series[0].barWidth = '50%';
        } else {
            percent_show = percent_show * 0.3;
            option.series[0].barWidth = '60%';
            //预置色数组长度不够用
            var color_list = [];
            for (var i = 0; i < count; i++) {
                color_list[i] = '#96CEEA';
            }
            //设置柱状图item项颜色
            option.color = color_list;
        }
        //设置柱状图X轴显示的item项数量
        option.dataZoom[0].end = percent_show;
        option.dataZoom[1].end = percent_show;

        return option;
    }

    /*
     * 根据饼图item项调整饼图参数(饼图圆心位置)
     * 避免饼图item项太多时,legend和饼图重叠
     * 这里是简单测试,可根据需求自行调整
     * */
    function adjustPieChartOption(data, option) {
        var count = data.detail.length;
        //饼图圆心高度
        var percent_location = '45%';
        if (count == 0) {
            percent_location = '50%';
            option.color = ['#BFBFBF'];
            option.series[0].data = {name: '', value: 0};
            option.series[0].itemStyle.normal.show = true;
            option.legend.data = {name: '', value: 0};
            option.legend.show = false;
        } else if (count > 0 && count < 11) {
            percent_location = '40%';
        } else if (count > 10 && count < 21) {
            percent_location = '35%';
        } else if (count > 20 && count < 31) {
            percent_location = '30%';
        } else {
            percent_location = '30%';
            //预置色数组长度不够用
            var color_list = [];
            for (var i = 0; i < count; i++) {
                color_list[i] = '#96CEEA';
            }
            //设置饼图item项颜色
            option.color = color_list;
        }
        //设置饼图圆心高度
        option.series[0].center[1] = percent_location;

        return option;
    }

    return {
        beforeInit: beforeInit,
        init: init,
        destroy: destroy,
        switchChartView: switchChartView
    }
}();


4) 使用

1,在页面初始化时如下调用,初始化图表相关

        assetStatics.beforeInit();
        assetStatics.init();

2,需要显示图标时如下调用

        assetStatics.switchChartView('bar');

三,写在后面

1)以上为项目前期技术调研时写的demo,非常简陋,勿喷。后面实际项目中做了不少优化处理(包括样式、关联逻辑、异常处理等),欢迎交流讨论;

2)已在以上代码注释中体现了部分坑的解决办法,后面实际项目中还遇到了些坑并都已解决,马上要下班了,在这里就不写出来了,后面有空也许会完善。各位亲碰到了问题的话可以在评论里留言,说不定你遇到的坑我也遇到过;





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值