项目一个需求,展示横向柱状图,自己动手封装了一个生成柱状图的工具类,效果图如下:
下面上代码:
import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; import com.wangyun.vo.Style; /** * @ClassName: 柱状图工具类 * @Description: 根据设置各个参数,生成柱状图 * @author: wangyun * @date: 2018-5-4 下午3:00:20 */ public class PlotUtils { /** * 生成图片 * @param names 城市名称 * @param dls 对应数值 * @param objList RGB 值 * @param dl 平均值 * @param cutValue 分割线最大值 * @throws FileNotFoundException */ public static String CreatePicture(String[] names,double[] dls,List<Style> objList ,double dl,double cutValue,String name,HttpServletRequest request ) throws FileNotFoundException{ String proute = null; //图片宽度 int width = 1000; //左侧标题栏宽度 int lwidth = 200; //图片高度 int high = (names.length+1)*40; //求出负数最大值 double dlss [] =new double[dls.length]; //解释:主要是为了防止指向同一个地址 for (int i = 0; i < dls.length; i++) { dlss[i]=dls[i]; } Arrays.sort(dlss);//从小到大 double fudl =0.00 ; if(dlss[0]<0){ fudl =dlss[0]; cutValue=-dlss[0]*5; }else{ cutValue=dlss[dlss.length-1]+dl; } // 得到图片缓存区 宽度 高度 图片类别 BufferedImage bi = new BufferedImage(width, high, BufferedImage.TYPE_INT_RGB); // 得到它的绘制环境(这张图片的笔) Graphics2D g2 = (Graphics2D)bi.getGraphics(); // 设置左侧画布颜色 g2.setColor(new Color(Integer.valueOf(objList.get(0).getR()), Integer.valueOf(objList.get(0).getG()), Integer.valueOf(objList.get(0).getB()))); // 填充整张图片(其实就是设置背景颜色)int x, int y, int width, int height g2.fillRect(0, 0, lwidth, high); //设置左侧标题框 int k=0; for (int i = 0; i < names.length; i++) { // 设置字体 g2.setFont(new Font("宋体", Font.BOLD, 26)); //设置城市名称字体颜色 g2.setColor(new Color(Integer.valueOf(objList.get(1).getR()), Integer.valueOf(objList.get(1).getG()), Integer.valueOf(objList.get(1).getB()))); // 抗锯齿 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.drawString(" "+sub_Str(names[i]), 30, 40+i*40); if(k>=0&&k<5){ g2.setColor(new Color(Integer.valueOf(objList.get(2).getR()), Integer.valueOf(objList.get(2).getG()), Integer.valueOf(objList.get(2).getB()))); k++; }else{ g2.setColor(new Color(Integer.valueOf(objList.get(3).getR()), Integer.valueOf(objList.get(3).getG()), Integer.valueOf(objList.get(3).getB()))); k++; if(k>9){ k=0; } } g2.fillRoundRect(5,20+i*40,26,26, 0, 0); //序号颜色 g2.setColor(new Color(Integer.valueOf(objList.get(4).getR()), Integer.valueOf(objList.get(4).getG()), Integer.valueOf(objList.get(4).getB()))); g2.setFont(new Font("宋体", Font.BOLD, 26)); if(i>=0&&i<9){ g2.drawString(""+(i+1)+" ", 5, 40+i*40); }else{ g2.drawString(i+1+" ", 5, 40+i*40); } } //设置右侧画布颜色 g2.setColor(new Color(Integer.valueOf(objList.get(5).getR()), Integer.valueOf(objList.get(5).getG()), Integer.valueOf(objList.get(5).getB()))); // 填充整张图片(其实就是设置背景颜色)int x, int y, int width, int height g2.fillRect(lwidth, 0, width, high); //设置分割线颜色 g2.setColor(new Color(Integer.valueOf(objList.get(6).getR()), Integer.valueOf(objList.get(6).getG()), Integer.valueOf(objList.get(6).getB()))); for (int i = 0; i <5; i++) { g2.drawLine(lwidth+(width-lwidth)/5*i,0, lwidth+(width-lwidth)/5*i,high); } //设置分割线数字颜色 g2.setFont(new Font("宋体", Font.BOLD, 20)); g2.setColor(new Color(Integer.valueOf(objList.get(7).getR()), Integer.valueOf(objList.get(7).getG()), Integer.valueOf(objList.get(7).getB()))); for (int i = 0; i <5; i++) { g2.drawString(""+new BigDecimal((cutValue/5)*i+fudl).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(), lwidth+(width-lwidth)/5*i, 15);//设置分割线数值 } //设置柱体 int p = 0; for (int i = 0; i < dls.length; i++) {//int x, int y, int width, int height, int arcWidth, int arcHeight //设置柱体颜色 g2.setColor(new Color(Integer.valueOf(objList.get(8).getR()), Integer.valueOf(objList.get(8).getG()), Integer.valueOf(objList.get(8).getB()))); if(dls[i]>0){ if(dls[i]>cutValue){ if(dlss[0]<0){ g2.fillRoundRect(lwidth-(int)(fudl*(width-lwidth)/cutValue),20+i*40,(width-lwidth)*3/5,26, 0, 0); g2.fillRoundRect(lwidth-(int)(fudl*(width-lwidth)/cutValue)+(width-lwidth)*3/5+10,20+i*40,90,26, 0, 0); }else{ g2.fillRoundRect(lwidth-(int)(fudl*(width-lwidth)/cutValue),20+i*40,(width-lwidth)*4/5,26, 0, 0); g2.fillRoundRect(lwidth-(int)(fudl*(width-lwidth)/cutValue)+(width-lwidth)*4/5+10,20+i*40,90,26, 0, 0); } }else{ g2.fillRoundRect(lwidth-(int)(fudl*(width-lwidth)/cutValue),20+i*40,(int)(dls[i]*(width-lwidth)/cutValue),26, 0, 0); } }else{ g2.fillRoundRect(lwidth-(int)((fudl-dls[i])*(width-lwidth)/cutValue),20+i*40,(int)(-dls[i]*(width-lwidth)/cutValue),26, 0, 0); } if(p==0){ if(dls[i]>dl&&dls[i+1]<dl){ //绘制平均线 g2.setColor(new Color(Integer.valueOf(objList.get(9).getR()), Integer.valueOf(objList.get(9).getG()), Integer.valueOf(objList.get(9).getB()))); //int x1, int y1, int x2, int y2 g2.drawLine( lwidth,53+i*40, width,50+i*40); //绘制平均线数值 g2.setColor(new Color(Integer.valueOf(objList.get(10).getR()), Integer.valueOf(objList.get(10).getG()), Integer.valueOf(objList.get(10).getB()))); //int x1, int y1, int x2, int y2 g2.setFont(new Font("宋体", Font.BOLD, 20)); g2.drawString(new BigDecimal(dl).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()+"", width-100, 80+i*40); p++; } } } //设置柱体数值 for (int i = 0; i < dls.length; i++) { // 设置字体 g2.setColor(new Color(Integer.valueOf(objList.get(11).getR()), Integer.valueOf(objList.get(11).getG()), Integer.valueOf(objList.get(11).getB()))); g2.setFont(new Font("宋体", Font.BOLD, 20)); if(dls[i]>0){ if(dls[i]>cutValue){ if(dlss[0]<0){ g2.drawString(""+dls[i],lwidth-(int)(fudl*(width-lwidth)/cutValue)+(width-lwidth)*3/5+100, 40+i*40); }else{ g2.drawString(""+dls[i],lwidth-(int)(fudl*(width-lwidth)/cutValue)+(width-lwidth)*4/5+100, 40+i*40); } }else{ g2.drawString(""+dls[i],lwidth-(int)((fudl-dls[i])*(width-lwidth)/cutValue), 40+i*40); } }else{ g2.drawString(""+dls[i],lwidth-(int)(fudl*(width-lwidth)/cutValue), 40+i*40); } } //绘制图片右下边框线 //设置粗度 g2.setStroke(new BasicStroke(8.0f)); //设置颜色 g2.setColor(new Color(Integer.valueOf(objList.get(12).getR()), Integer.valueOf(objList.get(12).getG()), Integer.valueOf(objList.get(12).getB()))); //int x1, int y1, int x2, int y2 g2.drawLine( width,0,width,high);//绘制右黑色线 g2.drawLine( 0,high,width,high);//绘制下黑色线 String path =request.getSession().getServletContext().getRealPath("/upload/"); String realPath="/upload/"; try { File dir = new File(path,name+".jpg"); ImageIO.write(bi, "JPEG", dir); handleDpi(dir, 300, 300); g2.dispose(); bi=null; System.gc(); } catch (IOException e) { e.printStackTrace(); } proute = realPath+name+".jpg"; return proute; } /** * 根据输入的字符串判断字符长度,添加相应空格 * @param cityName * @return */ public static String sub_Str(String cityName){ String ss=null; int count =0; char[] c = cityName.toCharArray(); for(int i = 0; i < c.length; i ++) { String len = Integer.toBinaryString(c[i]); if(len.length() > 8) count ++; } if(count==2){ ss=cityName.substring(0, 1)+" "+" "+" "+cityName.substring(1); }else if(count==3){ ss=cityName.substring(0, 1)+" "+cityName.substring(1,2)+" "+cityName.substring(2,3); }else if(count==4){ ss=cityName.substring(0, 1)+" "+cityName.substring(1,2)+""+cityName.substring(2,3)+" "+cityName.substring(3,4); }else if(count==5){ ss=cityName; }else{ ss="11111111111"; } return ss; } /** * 改变图片DPI * * @param file * @param xDensity * @param yDensity */ public static void handleDpi(File file, int xDensity, int yDensity) { try { BufferedImage image = ImageIO.read(file); JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(new FileOutputStream(file)); JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image); jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH); jpegEncoder.setJPEGEncodeParam(jpegEncodeParam); jpegEncodeParam.setQuality(0.75f, false); jpegEncodeParam.setXDensity(xDensity); jpegEncodeParam.setYDensity(yDensity); jpegEncoder.encode(image, jpegEncodeParam); image.flush(); } catch (IOException e) { e.printStackTrace(); } } }
过程遇到的问题总结:
1.数据有正负,画图时需要做一些判断。
2.有些数据比其他数据要大很多,需要做折断。
3.Graphics2D和BufferedImage最后关闭的问题,如果不关闭,在程序运行是不可以访问图片,我的解决办法是:
问题解决,不足之处请多多指点。