【详解】添加分渠道注册量显示

时间:2021-08-23 17:18:01

本例中,我们要做的是,

在原有echart表格的基础上,添加新的数据显示。

【大致思想】

分析原有表格中某项数据的显示原理,根据此原理,将我们所需要的数据展现出来。

即,最关键的就是分析数据库的数据,是通过一个怎样的过程,以图表的形式展现的。


第一步、分析

这一步,我们直到最后做出来,才刚刚搞清楚我们需要的原理。也即是说,这一步其实是最重要的。

接下来我们首先叙述下分析原理过程中的问题,然后再解释原理。

【问题】

我们依样画葫芦试着做的时候,遇到一个比较大的问题是,页面不停的刷新,刷新了一下午也刷不出最后的结果。

这里的原因可能有两点,

一者,

js错误,即,JSP页面不显示的原因,是JSP页面的代码出错了。

显而易见,显示的部分应当是不会出错的。因为我们根本就不需要动这部分。

JSP代码中的另一部分,js是我们改过的,所以,分析可能是这里出错。

二者,

后台出错,即,Controller中的某部分代码出错了。因为我们改了这部分里的一些代码。

【分析问题】

以上两个可能的问题,我们需要确定是哪一个。

我们首先需要知道,

前者js错误需要在F12控制台选项的js菜单中观察,我们怀疑js出错的时候,往往要到这里看有没有报错。

后者Controller代码报错,是在Eclipse的控制台中报错的。


最后我们分析得知,是js报错,但根本原因还是Controller中的代码错了。所以是二者都有错!

但js的报错信息,告诉我们哪里错了,我们从报错的地方追溯回去,才发现了问题所在。


【原理】

因为我们做的这个例子,是要在图表中显示新加的数据。新加的,我们要做的事情有人已经做过了。

我们要做的,要分析已经实现的部分的原理。

【数据流】

这里提出一个私人定义的概念,数据流。

即分析,我们看到的东西是从哪里来的。将这条路线画出来。正向推,反向推都是可以的。

接下来我们采用反向推!

以最接近我们要求的注册量为例:

{ 
/* 注册量 */
name : chart_line_names[i][0],
type : 'line',
data : data.list[i].data[0],
markPoint : {
data : [ {
type : 'max',
name : '最大值'
}, {
type : 'min',
name : '最小值'
} ]
},
markLine : {
data : [ {
type : 'average',
name : '平均值'
} ]
}
},

这里涉及到ECharts的知识。我们发现,图中的这条数据线的显示,所需的数据来自data。

 data : data.list[i].data[0]
再分析,data中的data是哪里来的

 function base_member_regist_cnt_doChart(data){
来自于这里,画图的js函数doChart所需的数据都来自于这个方法传进来的参数data

再分析,这个data是哪里来的

var jsonObj= data.chartDatas;
base_member_regist_cnt_doChart(jsonObj);
来自于jsonObj,jsonObj又来自于data.chartDatas

分析这里的data是哪儿的。【注意:我们分析数据来源时,只分析源,不需要管data.balabala里的balabala这些东西】

$.getJSON(base_member_regist_cnt_url, paramdata, function (data) {
我们发现data是通过访问链接得到的JSON数据。

分析下paramdata是哪里来的。

function base_member_regist_cnt_genJson(paramdata){
var $form = $(form);var paramdata = $form.serializeArray();base_member_regist_cnt_genJson(paramdata);
我们发现paramdata来自于form。

<form id="form1" action="chart/base_member_regist_cnt.html" method="get" onsubmit="return base_member_regist_cnt_submit(this);">
<div class='ichartjs_details' style="margin-left:200px;margin-bottom:10px">
日期:<input type="text" id="base_member_regist_cnt_startDate" name="startDate" class="date" minDate="2010-07-15" value="" maxDate="{%y}-%M-{%d}" />
  与  
<input type="text" id="base_member_regist_cnt_compareDate" name="compareDate" class="date" minDate="2010-07-15" value="" maxDate="{%y}-%M-{%d}" />
  与  前<select name="intervalDay" id="base_member_regist_cnt_intervalDay">
<option value="3" >3日</option>
<option value="7" >7日</option>
<option value="30">1个月</option>
</select>平均值  
<button type="submit">比较</button><br />

</div>
</form>
也即是,来自于表单的提交。

我们如果想得到这个JSON数据,就需要传递paramdata,才能够得到。

@RequestMapping("/base_member_regist_cnt.json")
public String base_member_regist_cnt(String startDate,String compareDate, String intervalDay, ModelMap modelMap) throws MyException, ParseException {
我们找到了要访问的链接。而且这个链接的确是返回了一个jsonView。

也就是说,这个名为base_member_regist_cnt的方法中,在jsonView中装入了数据。

我们接下来就是要分析,它是怎么在这个方法里取得数据并把它装入jsonView的。

该方法的精简版方法体如下

         if(startDate == null || startDate.trim().length() == 0) {
             startDate=dateUtil.getString(new Date(), "yyyy-MM-dd");
         }
         if(intervalDay == null || intervalDay.trim().length() == 0) {
             intervalDay="7";
         }
         if(compareDate == null || compareDate.trim().length() == 0) {
             Date date=dateUtil.addDay(new Date(), -Integer.valueOf(intervalDay));
             compareDate=dateUtil.getString(date, "yyyy-MM-dd");
         }
        ParamMap paramMap=new ParamMap();
        paramMap.put("startDate", startDate);
        paramMap.put("compareDate", compareDate);
        paramMap.put("intervalDay", intervalDay);
        EChartsData eChartsData=new EChartsData(paramMap);
        
     String sqlStr;
        String[] hoursLabels = LabelUtil.getLabelByIntBegin_00(24);
        ECharts eCharts2 = new ECharts(hoursLabels);
        
        //当日注册数
        List<Map<String,Object>> list2;
        sqlStr = stringUtil.formatMsg(
                "select DATE_FORMAT(b.CREATED_DATE,'%H') as label,count(MEMBER_ID) as STARTDATE_COUNT from moyoyo_member.BASE_INFO b where DATE_FORMAT(b.CREATED_DATE,'%Y-%m-%d') = '{0}' group by DATE_FORMAT(b.CREATED_DATE,'%H')",
                new Object[]{startDate});
        list2 = chartDataService.getChartList(sqlStr);
        eCharts2.add(LabelUtil.getValue(list2, hoursLabels,"label","STARTDATE_COUNT"));
        
        List<Map<String,Object>> list21;
        sqlStr = stringUtil.formatMsg(
                "select DATE_FORMAT(b.CREATED_DATE,'%H') as label,count(MEMBER_ID) as COMPAREDATE_COUNT from moyoyo_member.BASE_INFO b where DATE_FORMAT(b.CREATED_DATE,'%Y-%m-%d') = '{0}' group by DATE_FORMAT(b.CREATED_DATE,'%H')",
                new Object[]{compareDate});
        list21 = chartDataService.getChartList(sqlStr);
        eCharts2.add(LabelUtil.getValue(list21, hoursLabels,"label","COMPAREDATE_COUNT"));
        
        Date date=dateUtil.getDateObj(startDate);
        date=dateUtil.addDay(date, -Integer.valueOf(intervalDay));
        String compareStartDate=dateUtil.getString(date, "yyyy-MM-dd");
        
        List<Map<String,Object>> list22;
        sqlStr = stringUtil.formatMsg("select DATE_FORMAT(b.CREATED_DATE,'%H') as label,round(count(MEMBER_ID)/{0},0) as AVG_COUNT from moyoyo_member.BASE_INFO b where b.CREATED_DATE >= '{1}' and b.CREATED_DATE<'{2}' group by DATE_FORMAT(b.CREATED_DATE,'%H')"
                , new Object[]{intervalDay,compareStartDate,startDate});
        list22 = chartDataService.getChartList(sqlStr);
        eCharts2.add(LabelUtil.getValue(list22, hoursLabels,"label","AVG_COUNT"));
        eChartsData.add(eCharts2);
        
        modelMap.addAttribute("chartDatas", eChartsData);
        return "jsonView";
    }
根据以上方法体的代码, 我们依然反向来推!

jsonView 的数据肯定是来自于modelMap

        modelMap.addAttribute("chartDatas", eChartsData);

modelMap中的数据来自于eChartsData。

eChartsData中的又装入了eCharts2。

        eChartsData.add(eCharts2);
而eCharts2中的数据又是eCharts2 add了三次得到的。

        eCharts2.add(LabelUtil.getValue(list2, hoursLabels,"label","STARTDATE_COUNT"));
        eCharts2.add(LabelUtil.getValue(list21, hoursLabels,"label","COMPAREDATE_COUNT"));
        eCharts2.add(LabelUtil.getValue(list22, hoursLabels,"label","AVG_COUNT")); 
而add的内容中又包含了list2,list21,list22三个list。

        list2 = chartDataService.getChartList(sqlStr);
        list21 = chartDataService.getChartList(sqlStr);
        list22 = chartDataService.getChartList(sqlStr);
而每个list又是通过sqlStr取得的数据。

这样看来,

方法这种不变的东西,如果重复了很多遍,我们只需要分析一次就可以,我们需要找的,是这一个方法追溯到最后,

不一样的那个参数,而这个参数绝对是很明显的那种。

sqlStr = stringUtil.formatMsg(
"select DATE_FORMAT(b.CREATED_DATE,'%H') as label,count(MEMBER_ID) as STARTDATE_COUNT from moyoyo_member.BASE_INFO b where DATE_FORMAT(b.CREATED_DATE,'%Y-%m-%d') = '{0}' group by DATE_FORMAT(b.CREATED_DATE,'%H')",
new Object[]{startDate});
就像这样!而这里就是我们得到数据的地方。SQL从数据库中取得数据。

至此,我们要分析的原理,其实就是数据流已经分析完成了。

我们看到了数据从哪里来,到哪里去。

我们要注意的是,没有分析到最明显的参数那一步时,就不算分析完,因为还没有找到数据的源头。


【知识】

JSON格式的数据。什么是JSON数据?

我们在分析代码的时候,怀疑过为什么直接return一个jsonView就可以返回数据呢?

这个JSONVIEW到底是什么东西。经过研究,我们可以知道:

json是一种轻量级的数据交换格式。可以是一堆键值对,也可以是一堆数组。这里我们没有分析出它是什么?

但是没有关系,只需要知道json数据就是可以封装一大堆数据的数据对象。

否则,我们在JSP中画图的时候为什么总是传递JSON对象呢?23333333333


第二步、搭建框架

我们从需求就可以知道,我们要改动的关键地方就是SQL。

我们需要增加多少个数据,就按原理分析的来,增加多少个一样的部分。

这些一样的部分!是体力活!最后我们才专注于改动SQL。


第三步、改动SQL

这里的SQL又涉及到了联表查询。又是我们比较头疼的这种联表查询。

本例中,其实我们实际做的时候是很快就把SQL写好了,只是一直不太确定是不是正确的。

这里如何判断是否SQL正确呢?

一个最好用且最常用的办法,【我们也是今天才明确这个东西的作用】

使用Navicat的查询功能。

【详解】添加分渠道注册量显示

我们看下Navicat的界面,发现查询选项是在某个数据库的菜单下的,这个数据库中有很多的表。

我们要做的联表查询,肯定是在一个数据库中做的。

所以我们活用这个查询功能。

这里再提出一个私人的定义。

【SQL调试器】

我们可以把Navicat的查询功能当做一个SQL的调试器,我们不确定写出来的SQL是不是对的,

换句话说,就是它能不能够取到数据,取到的数据是否正确,这些东西,

查询之后,是可以直接在界面中看到的。如果有错,选择不到我们需要的数据,随时修改就可以。

而且这样做还有一个好处,Navicat中有美化SQL格式的功能。

我们可以更加清晰的看到SQL的语法,如果哪里需要修改,也很清晰明了。


最终我们用来联表查询的SQL例子如下:

SELECT
    DATE_FORMAT(b.CREATED_DATE, '%H') AS label,
    count(d.MEMBER_ID) AS STARTDATE_COUNT
FROM
    moyoyo_member.BASE_INFO b
LEFT JOIN moyoyo_member.DETAIL_INFO d ON b.MEMBER_ID = d.MEMBER_ID
WHERE
    DATE_FORMAT(b.CREATED_DATE, '%Y-%m-%d') = '{0}'
AND d.CHANNEL_TYPE = 1
GROUP BY
    DATE_FORMAT(b.CREATED_DATE, '%H')
发现其实意外的简单。其它几个SQL,只要照猫画虎,按照原来的SQL来写就可以啦。


第四步、画图

接下来,到了最为关键的一步。画图!

我们拿到了数据,并且传回来了。怎么来画这个图呢?

还是分析原来已经画好的图的原理。

                      function base_member_regist_cnt_doChart(data){
$("input#base_member_regist_cnt_startDate").val(data.paramMap['startDate']);
$("input#base_member_regist_cnt_compareDate").val(data.paramMap['compareDate']);
$("#base_member_regist_cnt_intervalDay").val(data.paramMap['intervalDay']);
chart_titles = ['用户注册情况','当日注册数量比较'];

chart_line_names = [
['总数'],
[data.paramMap['startDate']+' 注册量',
data.paramMap['startDate']+' WAP 注册量',
data.paramMap['startDate']+' WEB 注册量',
data.paramMap['startDate']+' APP 注册量',
data.paramMap['startDate']+' SDK 注册量',
data.paramMap['compareDate']+' 注册量',
data.paramMap['compareDate']+' WAP 注册量',
data.paramMap['compareDate']+' WEB 注册量',
data.paramMap['compareDate']+' APP 注册量',
data.paramMap['compareDate']+' SDK 注册量',
'前'+data.paramMap['intervalDay']+'天平均注册量',
'前'+data.paramMap['intervalDay']+'天 WAP 平均注册量',
'前'+data.paramMap['intervalDay']+'天 WEB 平均注册量',
'前'+data.paramMap['intervalDay']+'天 APP 平均注册量',
'前'+data.paramMap['intervalDay']+'天 SDK 平均注册量',
]
];
画图主要靠这个js函数,doChart来完成。

先定义了一堆title和图例的名字。。。。

接下来,要画图的data传递进来了,这个函数是如何处理这个data的呢?

i = 1
if(data.list[i].data[0].length==0){
chart_div = document.getElementById('base_member_regist_cnt_canvasDiv' + i)
html = '';
html+='<div style="font-size: 14px;text-align: center; width: 100%;height:100%;color:red">'
html+= data.paramMap["startDate"]+ chart_titles[i] + ' 暂时没有数据'
html+= '</div>'

chart_div.innerHTML=html;
}
if(data.list[i].data[0].length>0){
echarts.init(document.getElementById('base_member_regist_cnt_canvasDiv' + i)).setOption({
title : {
text : data.paramMap["startDate"]+ chart_titles[i],
x : "center"
},
tooltip : {
trigger : 'axis'
},
legend : {
data : chart_line_names[i],
y : 'bottom'
},
toolbox : {
show : true,
feature : {
dataView : {
show : true,
readOnly : false
},
magicType : {
show : true,
type : [ 'line', 'bar' ]
},
restore : {
show : true
},
saveAsImage : {
show : true
}
}
},
calculable : true,
xAxis : [ {
type : 'category',
data : data.list[i].labels
} ],
yAxis : [ {
type : 'value',
scale : true,
name : '注册数量',
axisLabel : {
formatter : '{value} 个'
}
} ],
series : [

{
/* 注册量 */
name : chart_line_names[i][0],
type : 'line',
data : data.list[i].data[0],
markPoint : {
data : [ {
type : 'max',
name : '最大值'
}, {
type : 'min',
name : '最小值'
} ]
},
markLine : {
data : [ {
type : 'average',
name : '平均值'
} ]
}
},
到这一步,完全就是ECharts的知识了。

如何定义坐标轴,如何定义图例,如何定义标题等等等等。

这些东西都已经写好了,我们只需要添加新的数据进去就可以了。

经过分析,我们可以知道,series里面是一条一条的数据。我们新添加一项数据,就是在这里添加。

根据特定的格式添加就去就好了,很简单!

【图例问题】

图画出来以后,我们发现有个问题,图例过于混乱了,

【详解】添加分渠道注册量显示

如何整理这个图例呢?

【图例相关的修改】

要整理图例,要修改的是-------图例相关代码!

legend : {
data : chart_line_names[i],
textStyle:{fontSize:12},
//x:'left',
//y:'50px',
//orient:'vertical',
y : '365px',
},
在整理这个图例的过程中,我们主要修改了legend(英文意思就是传奇、图例)

中的x、y,即图例的位置。因为图例最开始与图表重合了,我们将图例向下移动,即调整y的坐标,最终发现y的坐标为365px比较合适。

这个365px是图例与图表顶端的距离。

后来发现怎么修改都不合适,只能调整图例字体的大小,

textStyle:{fontSize:12},
才调整到了一个比价合适的状态,如下!

【详解】添加分渠道注册量显示

另一种方法,其实可以不用修改字体的大小,转而修改字的多少,把图例简化,如:

2015-11-23注册量改为11-23,就可以节省不少空间。该例中,图例不合适的原因就是太多,占的空间也太多了!

修改的过程中,我们用到了js取子字符串的知识。

【js取子字符串】

data.paramMap['startDate'].substr(5,5),
即substr函数,表示从第几位开始,取几位数!

【js检测数据的传送】

这个问题我们之前就说过,这里又用到了,但是没有想起来用,所以再重申一遍。

alert()的用法。相当于Java代码中的System.out.println,相当于Python代码中的print。

加了alert(),我们刷新页面的时候,就会自动跳出包含了数据信息的提示框。



【ECharts表格的默认选中或默认不选中】

接下来我们要实现另一个效果,即,刚刷出页面的时候,需要只显示前五条记录。其它的数据默认不显示。

我们从ECharts的官方网站例子中了解到应当在legend的selected中进行设置。

option = {
legend: {
orient: 'horizontal', // 'vertical'
x: 'right', // 'center' | 'left' | {number},
y: 'top', // 'center' | 'bottom' | {number}
backgroundColor: '#eee',
borderColor: 'rgba(178,34,34,0.8)',
borderWidth: 4,
padding: 10, // [5, 10, 15, 20]
itemGap: 20,
textStyle: {color: 'red'},
selected: {
'降水量' : false
},
data: [
{
name:'蒸发量',
icon : 'image://../asset/ico/favicon.png',
textStyle:{fontWeight:'bold', color:'green'}
},
'降水量','最高气温', '最低气温'
]
},
其中,将'降水量'这一项设置为false,刷新页面的时候降水量这一项就会默认不选中。

本例中,我们的图例很多,而且图例的名字不是死的,而是由每天的日期与其它字符串组成的。

chart_line_names = [
['总数'],
[data.paramMap['startDate'].substr(5,5),
data.paramMap['startDate'].substr(5,5)+' WAP',
data.paramMap['startDate'].substr(5,5)+' WEB',
data.paramMap['startDate'].substr(5,5)+' APP',
data.paramMap['startDate'].substr(5,5)+' SDK',
<pre name="code" class="javascript"> data.paramMap['compareDate'].substr(5,5),
<pre name="code" class="javascript"> data.paramMap['compareDate'].substr(5,5)+' WAP',
data.paramMap['compareDate'].substr(5,5)+' WEB',
data.paramMap['compareDate'].substr(5,5)+' APP',
data.paramMap['compareDate'].substr(5,5)+' SDK',
'前'+data.paramMap['intervalDay']+'天平均',
'前'+data.paramMap['intervalDay']+'天 WAP 平均',
'前'+data.paramMap['intervalDay']+'天 WEB 平均',
'前'+data.paramMap['intervalDay']+'天 APP 平均',
'前'+data.paramMap['intervalDay']+'天 SDK 平均',
]
];

 
官方的例子中,这种效果实现时,图例名字是死的,直接写出来。 

这里如果我们直接传参数进去,

if(data.list[i].data[0].length>0){<pre name="code" class="javascript">echarts.init(document.getElementById('base_member_regist_cnt_canvasDiv' + i)).setOption({
 title : {
                            text : data.paramMap["startDate"]+ chart_titles[i],
                            x : "center"
                        },
                        tooltip : {
                            trigger : 'axis'
                        },
                        legend : {
                            data : chart_line_names[i],
                            textStyle:{fontSize:12},
                            //x:'left',
                            //y:'50px',
                            //orient:'vertical',
                            y    : '365px',
selected:{
chart_line_names[1][0]:false
}
                        },
});

这种写法,没有达到我们想要的效果。 

即,

官方的写法只适用于图例名字死的时候,

如果图例名字为变量,这样写是不行的,因为这个变量的值,传不到legend中的selected中去。

最终,我们只能改变代码的结构来达到目的。如下:

先定义一个option

option= {
title : {
text : data.paramMap["startDate"]+ chart_titles[i],
x : "center"
},
tooltip : {
trigger : 'axis'
},
legend : {
data : chart_line_names[i],
textStyle:{fontSize:12},
//x:'left',
//y:'50px',
//orient:'vertical',
y : '365px',
selected:{}
 },
option.legend.selected[chart_line_names[1][5]] = false;option.legend.selected[chart_line_names[1][6]] = false;option.legend.selected[chart_line_names[1][7]] = false;option.legend.selected[chart_line_names[1][8]] = false;option.legend.selected[chart_line_names[1][9]] = false;option.legend.selected[chart_line_names[1][10]] = false;option.legend.selected[chart_line_names[1][11]] = false;option.legend.selected[chart_line_names[1][12]] = false;option.legend.selected[chart_line_names[1][13]] = false;option.legend.selected[chart_line_names[1][14]] = false;echarts.init(document.getElementById('base_member_regist_cnt_canvasDiv' + i)).setOption(option);}
即先定义好option,然后再定义option中的legend中的selected属性。

这样最终可以达到我们想要的效果。

【注意】

这样的修改,代码结构发生了变化。还有一个地方需要注意,

我们要在option定义完后再修改legend中的selected属性值,需要现在option中声明一下有selected这么个属性。

 legend : {
data : chart_line_names[i],
textStyle:{fontSize:12},
//x:'left',
//y:'50px',
//orient:'vertical',
y : '365px',
selected:{}
 },
否则会js报错,option.legend.selected没有被定义。

修改过这个图例以后的效果如下:

【详解】添加分渠道注册量显示


接下来我们要做的另外一件事情,是自定义tooltip,我们现在的代码中,

tooltip是默认样式的,

 tooltip : {
trigger : 'axis'
},
即跟着图例走。

我们想定义我们想要的悬浮框,就需要自己来写!

【自定义ECharts悬浮框样式】

实现这个自定义的悬浮框,我们参考的是ECharts官方的例子代码,最终成功实现!

官方的代码如下:

option = {
tooltip : { // Option config. Can be overwrited by series or data
trigger: 'axis',
//show: true, //default true
showDelay: 0,
hideDelay: 50,
transitionDuration:0,
backgroundColor : 'rgba(255,0,255,0.7)',
borderColor : '#f50',
borderRadius : 8,
borderWidth: 2,
padding: 10, // [5, 10, 15, 20]
position : function(p) {
// 位置回调
// console.log && console.log(p);
return [p[0] + 10, p[1] - 10];
},
textStyle : {
color: 'yellow',
decoration: 'none',
fontFamily: 'Verdana, sans-serif',
fontSize: 15,
fontStyle: 'italic',
fontWeight: 'bold'
},
formatter: function (params,ticket,callback) {
console.log(params)
var res = 'Function formatter : <br/>' + params[0].name;
for (var i = 0, l = params.length; i < l; i++) {
res += '<br/>' + params[i].seriesName + ' : ' + params[i].value;
}
setTimeout(function (){
// 仅为了模拟异步回调
callback(ticket, res);
}, 1000)
return 'loading';
}
//formatter: "Template formatter: <br/>{b}<br/>{a}:{c}<br/>{a1}:{c1}"
},
toolbox: {
show : true,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {show: true, type: ['line', 'bar', 'stack', 'tiled']},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
xAxis : {
data : ['周一','周二','周三','周四','周五','周六','周日']
},
yAxis : {
type : 'value'
},
series : [
{
name:'坐标轴触发1',
type:'bar',
data:[
{value:320, extra:'Hello~'},
332, 301, 334, 390, 330, 320
]
},
{
name:'坐标轴触发2',
type:'bar',
data:[862, 1018, 964, 1026, 1679, 1600, 157]
},
{
name:'数据项触发1',
type:'bar',
tooltip : { // Series config.
trigger: 'item',
backgroundColor: 'black',
position : [0, 0],
formatter: "Series formatter: <br/>{a}<br/>{b}:{c}"
},
stack: '数据项',
data:[
120, 132,
{
value: 301,
itemStyle: {normal: {color: 'red'}},
tooltip : { // Data config.
backgroundColor: 'blue',
formatter: "Data formatter: <br/>{a}<br/>{b}:{c}"
}
},
134, 90,
{
value: 230,
tooltip: {show: false}
},
210
]
},
{
name:'数据项触发2',
type:'bar',
tooltip : {
show : false,
trigger: 'item'
},
stack: '数据项',
data:[150, 232, 201, 154, 190, 330, 410]
}
]
};
这个代码例子乍看很复杂,我们这里再提出一个私人的定义。

【代码简化法则】

有一个需求,我们需要编程来实现功能会有以下几种情况:

一者,从头开始写,这个时候我们需要寻找例子来参考,官方的或是私人的,有可能是比较复杂的例子;

二者,一部分有人已经做过了,本例就是这样。

这个时候我们需要做的就是理清楚逻辑。

看清楚代码的逻辑,我们要做的就是把代码简化到只剩逻辑!这就是简化!

比如以上这个自定义悬浮框的例子代码,我们可以去掉很多东西。

比如悬浮框的样式定制,字体定制,模拟异步回调等等。这些都是无关紧要的东西,我们可以去掉。

知道最后我们可以清楚的看到自定义悬浮框的核心代码,tooltip部分。

 tooltip : {
trigger : 'axis',
formatter: function (s) {
var res = 'Formatter:<br/>'+s[0].name;
for (var i = 0, l = s.length; i < l; i++) {
res += '<br/>' + s[i].seriesName + ' 注册量 : ' + s[i].value;
}
return res;
}
},
这部分代码的意思是:

当鼠标移到光标时,会有数据传回来,装入参数s中,

然后这个function会执行下面的代码,实现对tooltip的定制。

这里的这个参数s,可以随意起名字,比如params等等。

这个参数之所以可以这样使用,我们可以类比AJAX的数据回调,function(data)这个data就可以随意起名字,

参数名字只不过是传回来的数据的一个容器,AJAX中不过是习惯性的起名为data而已。


最终我们的效果图如下!

【详解】添加分渠道注册量显示


截图快捷键:ctrl+alt+a