Echarts是一款百度的开源图表库,里面提供了非常多的图表样式,我们今天要讲的内容是利用这一款开源js图表,制作一个能够动态定制的图表平台。

1)Echarts API介绍

首先我们先来看一下Echarts中的一个简单柱状图的API:

option = {
    color: ['#3398DB'],
    tooltip : {
        trigger: 'axis',
        axisPointer : {            // 坐标轴指示器,坐标轴触发有效
            type : 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
        }
    },
    grid: {
        left: '3%',
        right: '4%',
        bottom: '3%',
        containLabel: true
    },
    xAxis : [
        {
            type : 'category',
            data : ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
            axisTick: {
                alignWithLabel: true
            }
        }
    ],
    yAxis : [
        {
            type : 'value'
        }
    ],
    series : [
        {
            name:'直接访问',
            type:'bar',
            barWidth: '60%',
            data:[10, 52, 200, 334, 390, 330, 220]
        }
    ]
};

在这个option中包含了很多图表的属性,series是图表的基础属性,包含了图表的类型、数据的值等,xAxis包含了x轴上的数据列等。在其他的图表类型中,还会包含legend、title、tooltip、toolbox等属性,这些可以通过查看Echarts API查看,这里不一一叙述。

2)根据Echarts API建模

我们既然要实现一个报表平台,就需要对这些属性需要的数据进行建模:

public class TuBiao : IAggregateRoot
    {
        public title title { get; set; } = new title();
        public legend legend { get; set; } = new legend();

        public xAxis xAxis { get; set; } = new xAxis();

        public yAxis yAxis { get; set; } = new yAxis();

        public IList<series> serieList { get; set; } = new List<series>();

        public TuBiao GetTuBiaoByID(string tuBiaoID)
        {
            ITuBiaoRepository repo = IoC.Resolve<ITuBiaoRepository>();
            return repo.GetByTuBiaoID(tuBiaoID);
        }
    }

其中title、legend、xAxis、series都是图表模型中的值对象,熟悉领域驱动的同学可能看起来很熟悉,每一个都对应着Echarts API中的js属性,随便贴出一个两个代码示例:

public class title
    {
        public string text { get; set; }

        public string subtext { get; set; }
    }
public class series
    {
        public string name { get; set; }

        public string type { get; set; }

        public List<string> dataList { get; set; } = new List<string>();
    }
public class yAxis
    {
        /// <summary>
        /// 单位
        /// </summary>
        public string danwei { get; set; }
        /// <summary>
        /// 最大值
        /// </summary>
        public string ZuiDaZhi { get; set; }
        /// <summary>
        /// 最小值
        /// </summary>
        public string ZuiXiaoZhi { get; set; }
    }

值对象的创建方式可以参考Echarts的API创建,最终我们的模型要满足一个完整Echarts所需要的所有属性。

3)根据Echarts模型加载Echarts的JavaScript脚本

在页面加载的时候,我们可以获取Echarts的模型,并加载到Echarts图表中。示例代码如下:

myChart.setOption({
        title: {
            text: '@ViewBag.TuBiao.title.text',
            subtext: '@ViewBag.TuBiao.title.subtext'
        },
        tooltip: {
            trigger: 'axis',
        },
        legend: {
            data: [@for (;i<= ViewBag.TuBiao.legend.dataList.Count - ;i++ )
            {
                )
                {
                    <text>'@ViewBag.TuBiao.legend.dataList[i]'</text>
                }
                else
                {
                    <text>'@ViewBag.TuBiao.legend.dataList[i]',</text>
                }
            }]
            },
            @if(ViewBag.TuBiao.serieList.Count >= && ViewBag.TuBiao.serieList[].type != ].type != "funnel")
            { <text>
            xAxis: [
                {
                    data: [@for (; i <= ViewBag.TuBiao.xAxis.dataList.Count - ; i++)
                    {
                        )
                            {<text>'@ViewBag.TuBiao.xAxis.dataList[i]'</text>}
                        else
                            {<text>'@ViewBag.TuBiao.xAxis.dataList[i]',</text>}

                     }]
                 }
            ],
            yAxis: [
                {
                    type: 'value',
                    axisLabel: {
                        formatter: '{value}@ViewBag.TuBiao.yAxis.danwei'
                    },
                    @if(!string.IsNullOrEmpty(ViewBag.TuBiao.yAxis.ZuiXiaoZhi))
                    {
                        <text>min:@ViewBag.TuBiao.yAxis.ZuiXiaoZhi,</text>
                    }
                    @if(!string.IsNullOrEmpty(ViewBag.TuBiao.yAxis.ZuiDaZhi))
                    {
                        <text>max:@ViewBag.TuBiao.yAxis.ZuiDaZhi,</text>
                    }
                    boundaryGap:[, ]

                }
            ],</text>}
            toolbox: {
                show: true,
                feature: {
                    mark : {show: true},
                    dataView : {show: true, readOnly: true},
                    @if (ViewBag.TuBiao.serieList.Count >=  && ViewBag.TuBiao.serieList[].type != ].type != "funnel")
                    { <text>
                    magicType: { type: ['line', 'bar'] },</text>}
                    restore: {},
                    saveAsImage: {}
                }
            },
            series: [@for (; serie <= ViewBag.TuBiao.serieList.Count - ; serie++)
            {
                )
                {
                    <text>
                    {
                        name: '@ViewBag.TuBiao.serieList[serie].name',
                        type: '@ViewBag.TuBiao.serieList[serie].type',
                        data: [@for (;i<= ViewBag.TuBiao.serieList[serie].dataList.Count -;i++)
                        {
                            )
                            {
                                <text>{value:'@ViewBag.TuBiao.serieList[serie].dataList[i]',name:'@ViewBag.TuBiao.xAxis.dataList[i]'}</text>
                            }
                            else {
                                <text>{value:'@ViewBag.TuBiao.serieList[serie].dataList[i]',name:'@ViewBag.TuBiao.xAxis.dataList[i]'},</text>
                            }

                        }],
                            @if(ViewBag.TuBiao.serieList.Count >= && ViewBag.TuBiao.serieList[].type != ].type != "funnel")
                            { <text>
                                  markLine: {
                                      data: [
                                            { type: 'average', name: '平均值' }
                                            ]
                             }</text>}
                 }
                    </text>
                }
                else
                {
                    <text>
     {
        name: '@ViewBag.TuBiao.serieList[serie].name',
        type: '@ViewBag.TuBiao.serieList[serie].type',
        data: [@for (;i<= ViewBag.TuBiao.serieList[serie].dataList.Count -;i++)
                        {
                            )
                            {
                                <text>{value:'@ViewBag.TuBiao.serieList[serie].dataList[i]',name:'@ViewBag.TuBiao.xAxis.dataList[i]'}</text>
                            }
                            else {
                                <text>{value:'@ViewBag.TuBiao.serieList[serie].dataList[i]',name:'@ViewBag.TuBiao.xAxis.dataList[i]'},</text>
                            }

                        }],
                     @if(ViewBag.TuBiao.serieList.Count >= && ViewBag.TuBiao.serieList[].type != ].type != "funnel")
                    { <text>
                         markLine: {
                         data: [
                         { type: 'average', name: '平均值' }
                      ]
                    }</text>}
    },
    </text>
                }

            }]
    });

其中ViewBag.TuBiao就是我们从model层返回的报表模型,根据Echarts的API一一对应就可以了。

4)如何装载Echarts模型

前面所述的都是Echarts报表的展示部位,下面我们来看一下这个TuBiao的模型该如何生成,有心的同学可能已经注意到了TuBiao的模型中包含一个GetByTuBiaoID的方法,下面把该代码的实现分享一下:

public class TuBiaoRepository:Repository<TuBiao>,ITuBiaoRepository
    {public TuBiaoRepository(RepositoryContext context) : base(context) { }

        public TuBiao GetByTuBiaoID(string tuBiaoID)
        {
            TuBiaoShuJuYuan shujuyuan = TuBiaoShuJuYuan.GetByTuBiaoID(tuBiaoID);

            TuBiao result = new TuBiao();
            result.title.text = shujuyuan.BiaoTi;
            result.title.subtext = shujuyuan.FuBiaoTi;
            //设置Y轴的一些信息
            result.yAxis.danwei = shujuyuan.DanWei;
            result.yAxis.ZuiDaZhi = shujuyuan.ZuiDaZhi;
            result.yAxis.ZuiXiaoZhi = shujuyuan.ZuiXiaoZhi;

            //读取数据源
            StreamReader srsjy = new StreamReader(HttpContext.Current.Request.MapPath("~/TubiaoData/") + shujuyuan.ShuJuYuan, System.Text.Encoding.UTF8);
            try
            {
                shujuyuan.ShuJuYuan = srsjy.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                srsjy.Close();
            }

            foreach (var item in HttpContext.Current.Request.QueryString.AllKeys)
            {
                if (!string.IsNullOrEmpty(item))
                    shujuyuan.ShuJuYuan = shujuyuan.ShuJuYuan.Replace("[" + item + "]", HttpContext.Current.Request.QueryString[item]);
            }
            // \{([^\{^\}]*)\}
            shujuyuan.ShuJuYuan = Regex.Replace(shujuyuan.ShuJuYuan, @"\[\S*\]", "", RegexOptions.Multiline);

            DbHelper h = new DbHelper(ConnectionName.LocalDB);
            DataTable dt = h.ExecuteDataTable(shujuyuan.ShuJuYuan).DataResult;
            //检索图例
            var tuli = (from i in dt.AsEnumerable()
                        select i.Field<string>(TuBiaoZiDuanStruct.TuLi)).Distinct().ToList<string>();
            result.legend.dataList.AddRange(tuli);
            //检索统计单元
            var tongJiDy = (from i in dt.AsEnumerable()
                        select i.Field<string>(TuBiaoZiDuanStruct.TongJiDY)).ToList<string>();
            result.xAxis.dataList.AddRange(tongJiDy);

            //循环为每个图例赋值
            foreach (string dqtl in tuli)
            {
                //查询当前图例的图表类型
                var leiXing = (from i in dt.AsEnumerable()
                                where i.Field<string>(TuBiaoZiDuanStruct.TuLi) == dqtl
                                select i.Field<string>(TuBiaoZiDuanStruct.LeiXing)).ToList<string>().FirstOrDefault();
                //添加数据
                series srs = new series();
                srs.name = dqtl;
                srs.type = leiXing;

                //检索对应图例下的图表数据
                var tubiaosy = (from i in dt.AsEnumerable()
                                where i.Field<string>(TuBiaoZiDuanStruct.TuLi) == dqtl
                                select i.Field<dynamic>(TuBiaoZiDuanStruct.Zhi)).ToList<dynamic>();

                foreach (dynamic zhi in tubiaosy)
                {
                    srs.dataList.Add(Convert.ToString(zhi));
                }

                result.serieList.Add(srs);
            }

            return result;
        }
        struct TuBiaoZiDuanStruct
        {
            public static string TuLi { get { return "TULI"; } }
            public static string LeiXing { get { return "LEIXING"; } }
            public static string TongJiDY { get { return "TONGJIDY"; } }
            public static string Zhi { get { return "ZHI"; } }
        }
    }

这个方法的作用主要是从数据库中查询图表的数据源定义,并执行该数据源,得到图表所需要的数据,并装载TuBiao模型,示例数据源的SQL语句如下:

5)Echarts模型的数据源定义

SELECT T.XINGMING AS TULI,'line' AS LEIXING,T.TIWEN AS ZHI,T.JILUSJ AS TONGJIDY 

FROM TIWEN T WHERE T.ID= '[ID]'

这个SQL语句是根据一个ID获取一个人的体温变化曲线图,在这里的ID涉及到了图表的参数化查询,包括报表的其他个性化的定制(如图表的曲线的范围、计量单位的定义等),下篇文章将会继续介绍该图表平台的其他实现。

利用Echarts设计一个图表平台(一)的更多相关文章

  1. 如何利用Excel设计一个唱票统计系统?

    具体操作如下: 首先需要一个如下的数据结构. 唱票数G列区域,不能手动输入候选人票数,这样很不方便,所以我们需要一个窗体控件,用点击鼠标的方法来实现唱票.在“开发工具-插入-数值调节钮”下图3处,然后 ...

  2. UE4笔记:利用Widget设计一个切换材质功能

    UE4引擎中的Widget蓝图是一个重要的工具,可用于场景中的页面叠加,镜头绑定,场景切换等多处地方,在这里笔者介绍一种利用控件蓝图和场景中物体进行信息交互的方法,直观的体现就是进行物体的材质切换. ...

  3. 如何利用GitHub设计一个炫酷的个人网站(含代码)

    1.在开始制作之前我们先预览一下我的网站吧! 1.方式一: 由于是手机版的所以用手机访问下面的链接体验比较好一点: https://tom-shushu.github.io/MyWeb.github. ...

  4. 如何利用Visio设计一个系统的结构图

    首先建立一个空的vison列表 添加图形和连接线 托选一个矩形块到操作台上,并进行底色填充 选择有向线段1拖到矩形模块上,此时有向线段1会自动吸附到矩形的中点处. 此时按下图操作即可取消,自动吸附 托 ...

  5. C语言中利用clock设计一个简单的定时器

    time.h是C/C++中的日期和时间头文件,用于需要时间方面的函数,定义了四个变量类型.两个宏和各种操作日期和时间的函数. 其中计时函数是clock(),而与其相关的数据类型是clock_t.clo ...

  6. 利用ELK构建一个小型的日志收集平台

    利用ELK构建一个小型日志收集平台 伴随着应用以及集群的扩展,查看日志的方式总是不方便,我们希望可以有一个便于我们查询及提醒功能的平台:那么首先需要剖析有几步呢? 格式定义 --> 日志收集 - ...

  7. 如何设计一个web容器

    开发一个web容器涉及很多不同方面不同层面的技术,例如通信层的知识,程序语言层面的知识等等,且一个可用的web容器是一个比较庞大的系统,要说清楚需要很长的篇幅,本文旨在介绍如何设计一个web容器,只探 ...

  8. 如何设计一个可用的web容器

    之前在另外一个平台(http://www.jointforce.com/jfperiodical/article/1035)发表的一篇文章,现在发布到自己的博客上. 开发一个web容器涉及很多不同方面 ...

  9. 利用 vue-cli 构建一个 Vue 项目

    一.项目初始构建 现在如果要构建一个 Vue 的项目,最方便的方式,莫过于使用官方的 vue-cli . 首先,咱们先来全局安装 vue-cli ,打开命令行工具,输入以下命令: $ npm inst ...

随机推荐

  1. ORACLE触发器具体解释

    ORACLE PL/SQL编程之八: 把触发器说透 本篇主要内容例如以下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 ...

  2. 【ZZ】如何选择适合自己项目的编程语言

    http://news.cnblogs.com/n/506473/ 与操作系统一样,在办公室软件套装和计算机中也具有各种计算机语言.存在这种多样性的原因与其它地方的多样性一样—-因为没有单一的解决方法 ...

  3. 判断手机andriod还是iphone

    手机识别:var isAndroid = navigator.appVersion.toLowerCase().indexOf(‘android’) >= 0,isIphone = naviga ...

  4. 详解ARM的AMBA设备中的 DMA设备PL08X的Linux驱动

    1. 此文目的记录笔者对ARM的PL08x的DMA驱动PL08x.c理解.给其他不熟悉此DMA驱动的读者一点借鉴和参考.2. 适合读者你已经具备一定驱动编程能力,知道一些最基本的概念,比如用于输出输出 ...

  5. Android广播接收者应用(电话拦截器)

    一.电话拦截器应用说明 在我们输入完电话号码并拨打电话时,系统会发出一个有序广播(action="android.intent.action.NEW_OUTGOING_CALL") ...

  6. 小白日记6:kali渗透测试之被动信息收集(五)-Recon-ng

    Recon-ng Recon-NG是由python编写的一个开源的Web侦查(信息收集)框架.Recon-ng框架是一个全特性的工具,使用它可以自动的收集信息和网络侦查.其命令格式与Metasploi ...

  7. 自问自答-hadoop在安全模式下究竟干了什么见不得人的事

    本来想自己从网上搜集整理的,但是发现吴超写的刚刚好,不多不少,所以直接转载(图片失效了,用自己的图片) http://www.superwu.cn/2013/08/23/548/ 在hadoop集群的 ...

  8. Android(java)学习笔记75:匿名内部类的方式实现多线程程序

    二话不说,首先利用代码体现出来,给大家直观的感觉: package cn.itcast_11; /* 4 * 匿名内部类的格式: 5 * new 类名或者接口名() { 6 * 重写方法; 7 * } ...

  9. Android(java)学习笔记97:Scanner类使用

    package cn.itcast_01; /* * Scanner:用于接收键盘录入数据. * * 前面的时候: * A:导包 * B:创建对象 * C:调用方法 * * System类下有一个静态 ...

  10. android开发之路07(无硝烟的战争)

    如何做一名优秀的android面试官? 如何做一名优秀的android候选者? 提到这个问题我不得不提起我们小升初,初升高,高生升本这几个历程中我们与出题人之间的无硝烟的战争.我们总是为自己的成绩担心 ...