自己在做统计图的时候发现前端框架不是很会!所以自己研究 自己封装了一个统计图处理器(折线图 ,条形图 等等...)
说一下大概原理
首先用到的前端技术Highcharts 是一个用纯JavaScript编写的一个图表库。
在绘图前我们需要为 Highcharts 准备一个 DOM 容器,并指定其大小
"container" style="width: 600px;height:400px;">div>然后通过 Highcharts 的初始化函数 Highcharts.chart
来创建图表,该函数接受两个参数,第一个参数是 DOM 容器的 Id,第二个参数是图表配置,代码如下:
<html>
<head>
<meta charset="utf-8">
<title>第一个 Highcharts 图表title>
head>
<body>
<div id="container" style="width: 600px;height:400px;">div>
<script src="http://cdn.hcharts.cn/highcharts/highcharts.js">script>
<script>
// 图表配置
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);
script>
body>
html>
这样你的第一个图表就诞生了!
这样简单的一个静态图标也就完成了!
详细学习网址:https://www.hcharts.cn/docs/start-helloworld 这也是上面案例来源!
很简单吧! 但是呢? 现在问题来了! 这是静态的数据, 如果动态呢 改怎么解决, 也好解决
public class VideotexBean{
private int nameId;
private String name;
}
封装bean转成需要的格式即可
public class ResultCode {
/**
* 请求成功返回
*/
public static final int SUCC = 0;
/**
* 请求失败返回
*/
public static final int FAILT = 1;
/**
* 特殊情况处理 一般很少用(主要用前端显示)
*/
public static final int SPECIAL = 2;
/**
* 请求返回图表配置
*/
public static final int VIDEOTEX = 3;
/**
* 创建成功请求结果
* @param map
* @param message
* @return
*/
public static JSONObject error(String message){
JSONObject json=new JSONObject();
json.put("status",FAILT);
json.put("msg", message);
return JSONObject.fromObject(json.toString());
}
public static JSONObject succ(String message){
JSONObject j=new JSONObject();
j.put("status",SUCC);
j.put("msg", message);
return JSONObject.fromObject(j.toString());
}
public static JSONObject SPECIAL(String message){
JSONObject j=new JSONObject();
j.put("status",SPECIAL);
j.put("msg", message);
return JSONObject.fromObject(j.toString());
}
public static Object writeJson(Object object) {
// return JSONObject.fromObject(object);
String str = JSON.toJSONStringWithDateFormat(object, "yyyy-MM-dd HH:mm:ss", SerializerFeature.PrettyFormat);
return JSON.parse(str);
//String json = JSON.toJSONStringWithDateFormat(object, "yyyy-MM-dd HH:mm:ss", SerializerFeature.PrettyFormat);
//return json;
}
也能勉强实现功能;但是大家有想过吗? 如果你是个后端或者是个技术初学者前端.多轴图 日期图,实时更新图,实时变化图这个繁杂的数据一大堆 根本不可能一下实现! 接下来开始我的封装方法来实现任何格式任何多么复杂的数据都可轻易解决的问题的方法
第一步:封装
/**
* 图表配置类型 直线图、曲线图、曲线面积图、面积范围图、柱状图、条形图、饼图、散点图、气泡图
* @author JiaYi
* @date 2018年4月17日 下午2:34:57
* @package com.game.admin.dto.videotex
*/
public enum ChartType {
/** 直线图 */
line,
/** 曲线图 */
spline,
/** 曲线面积图*/
area,
/** 面积范围图*/
arearange,
/** 柱状图 */
column,
/** 条形图 */
bar,
/** 饼图*/
pie,
/** 散点图 */
scatter,
/** 气泡图 */
bubble
}
图表配置器参数封装
/**
* 图表配置器参数封装
* @author JiaYi
* @date 2018年4月17日 下午12:35:58
* @package com.game.admin.dto.videotex
*/
public class VideotexData {
/**
* 图表类型
*/
private ChartType chartType;
/**
* 图表标题
*/
private String chartTitle;
/**
* 图表X轴字段
*/
private String chartXAxis;
/**
* Y轴标题
*/
private String yAxisTitle;
/**
* 数据列参数分装
*/
private List list;
public VideotexData() {
}
/**
* 初始化
* @param chartType 图表类型
* @param chartTitle 图表标题
* @param chartXAxis 图表X轴字段
* @param yAxisTitle Y轴标题
* @param list 数据列参数分装
* @return
*/
public static VideotexData valueOf(ChartType chartType, String chartTitle, String chartXAxis, String yAxisTitle, List list) {
VideotexData instance =new VideotexData();
instance.chartType = chartType;
instance.chartTitle = chartTitle;
instance.chartXAxis = chartXAxis;
instance.yAxisTitle = yAxisTitle;
instance.list = list;
return instance;
}
public ChartType getChartType() {
return chartType;
}
public void setChartType(ChartType chartType) {
this.chartType = chartType;
}
public String getChartTitle() {
return chartTitle;
}
public void setChartTitle(String chartTitle) {
this.chartTitle = chartTitle;
}
public String getChartXAxis() {
return chartXAxis;
}
public void setChartXAxis(String chartXAxis) {
this.chartXAxis = chartXAxis;
}
public String getyAxisTitle() {
return yAxisTitle;
}
public void setyAxisTitle(String yAxisTitle) {
this.yAxisTitle = yAxisTitle;
}
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
}
仔细看上图,类型是枚举,标题,x轴字段,y轴标题,数据列
全部动态生成!只需要考虑数据即可
接下来做个小案例 :
服务器每日充值数据统计图 通过注册 开始时间:结束时间时间段获取每天的项目收入情况对比
/server/allServertree',method:'get',animate:true,checkbox:true">
这是页面中的写法
此div是容器一切都是他是主体
这是他的效果,选择时间段:点击发送
发送事件:
function submitok(){
var serverIds=getServerIds();
var startTime = $('#startTime').datetimebox("getValue");
var endTime = $('#endTime').datetimebox("getValue");
if(startTime == '' || endTime==''){
alert("请选择时间段 !");
return ;
}
$.post('<%=request.getContextPath() %>/请求类/方法名',{
serverIds:serverIds, //多服
startTime:startTime,
endTime:endTime
},function(data) {
var d = $.parseJSON(data);//回传格式
if(d.videotexConfig==3){
var msg = d.msg
document.getElementById("container").style.display = "block";
var chart = Highcharts.chart('container', msg);//图形显示
}else if (d.status==1) {//失败原因提示
$.messager.show({
title : '提示',
msg : d.msg
});
}
});
}
由此前端代码就写完了.剩下的交给服务器来处理
/**
* 请求多服并且所选择日期之间计算后的充值数据折线图
* @param serverIds 多服
* @param startTime 开始时间
* @param endTime 结束时间
* @return
*/
public Object serverContrasTimeTotalPay(@Param("serverIds") String serverIds,
@Param("startTime")String startTime,@Param("endTime")String endTime){
if(StringUtil.isEmpty(serverIds)){
return ResultCode.error("请选择服务器");
}else {
if(StringUtil.isEmpty(startTime) || StringUtil.isEmpty(endTime)){
return ResultCode.error("请选择时间段!");
}
List timeLists = TimerUtils.getAmongTime(startTime, endTime);
if(CollectionUtil.isEmptyCollection(timeLists)){
return ResultCode.error("请检查选择时间段!");
}
List dailyRateDtoLists = eachTimeTotalServerData(serverIds,timeLists);
//到这在算
if(!CollectionUtil.isEmptyCollection(dailyRateDtoLists)){
String totalPay= passTimeBetweenTotalPay(dailyRateDtoLists,timeLists);
return ResultCode.videotex(totalPay);
}
return ResultCode.error("获取数据为空!");
}
}
/**
* 获取多服之间的总和数据(1个服的话就要一个服务的就行)
* @param serverIds
* @return
*/
private List eachTimeTotalServerData(String serverIds,List timeLists){
//DailyRateDto类为留存率计算就是数据集合可以把你的数据封装list集合中
}
说一下时间段的获取
利用这个Calendar tempEnd = Calendar.getInstance();来获取时间段
把你的eachTimeTotalServerData这个方法数据按照你需求封装成list集合(集合中list必须规则排序)list本身有序按照下标0开始
passTimeBetweenTotalPay这个方法开始给封装对象VideotexData赋值
简单的set进去就行,serieslist这个list集合用来动态数据列参数分装
getTimeBetweenYAxis这个方法用来返回[格式数据]
他就是个list集合的toString
getPassTimeXAxisTotalPay 是X轴数据
接下来:
public class VideotexUtils {
/**
* 图表配置器
* @param videotexData
* @return
*/
public static String getVideotexContainer(VideotexData videotexData){
StringBuffer stringBuffer = new StringBuffer();
stringBuffer
.append("{")
.append("'chart': { 'type': ")
.append("'")
.append(videotexData.getChartType().name())
.append("'")
.append("},")
.append("'title': { 'text': ")
.append("'")
.append(videotexData.getChartTitle())
.append("'")
.append("},")
.append("'xAxis': { 'categories' : ")
.append(videotexData.getChartXAxis())
.append("},")
.append("'yAxis': { 'title': { 'text': ")
.append("'")
.append(videotexData.getyAxisTitle())
.append("'")
.append("} },")
.append("'series': [{ ");
List seriesLists = videotexData.getList();
for (SeriesParameter seriesParameter : seriesLists) {
stringBuffer.append("'name':")
.append("'")
.append(seriesParameter.getSeriesName())
.append("'")
.append(", 'data': ")
.append(seriesParameter.getSeriesData())
.append("},{" );//段尾
}
stringBuffer.delete(stringBuffer.length()-2, stringBuffer.length());
stringBuffer.append("] ")
.append("}");
return stringBuffer.toString();
}
返回对象格式
传给前端处理即可!
最后效果就出来了!
股票图原理都类似,对于不懂前端的你不妨试试!