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. Windows 7系统安装MySQL5.5.21图解

    Win7系统安装MySQL5.5.21图解 大家都知道MySQL是一款中.小型关系型数据库管理系统,非常具有有用性,对于我们学习非常多技术都有帮助,前几天我分别装了SQL Server 2008和Or ...

  2. 使用sql生成UUID

    在SQLServer中使用该sql语句可以生成GUID:select cast(NEWID() as varchar(36)) as uuid 通过一下语句将GUID中的'-'字符去掉: select ...

  3. Error creating bean with name &#39;menuController&#39;: Injection of autowired dependency……

    出现了一大串错误 Error creating bean with name 'userController': Injection of autowired dependencies failed. ...

  4. MySQL 灵异事件一则 -- desc报语法错误

    今天有一开发同学找到我,说查询SQL中倒序报错,不明原因,于是奔赴工位现场研究情况. 果然,只要SQL中带有desc 就会报错,而ASC没问题. 哪怕desc放在句首用作explain也会报错. 报错 ...

  5. LeetCode: Reverse Words in a String:Evaluate Reverse Polish Notation

    LeetCode: Reverse Words in a String:Evaluate Reverse Polish Notation Evaluate the value of an arithm ...

  6. focuskye 学习及下载

    学习:http://www.focusky.com.cn/tutorials/ 下载:http://www.focusky.com.cn/download/

  7. BloomFilter——读数学之美札记

    之前接触过bitmap,读吴军先生的数学之美,看到了一个更强大的数据结构,布隆过滤器(Bloomfilter),赶紧记下来吧,忘了怪可惜的. bitmap的使用是很有局限性的,往往只能用于海量数值型数 ...

  8. Java中执行外部命令

    在项目中执行一个linux的shell脚本,于是需要在java环境下执行外部命令如系统命令.linux命令的需求,本人小小研究了一下,又上网查了一些资料先整理如下. java执行外部命令主要依赖两个类 ...

  9. cocos2d-x, protobuf, no config.h, #error "No suitable threading library available."

    在用cocos2d-x3.2 + protobuf编译Android项目的时候,protobuf出现了两个问题: 1. 首先是config.h找不到,查阅自后说是通过命令或工具生成的,里面的内容根据不 ...

  10. Extjs之success、failure

    Ext.form.Action.Submit的配置选项success.failure是根据返回json中success属性判断的,如果success为true,则success,false则failu ...