📄 stockindex.jsp
字号:
<!--
Fig. 7.13_02: stockIndex.jsp
功能: 基于Java2D的Web图表实例17: 股市大盘指数走势图
-->
<%@ page language="java" contentType="image/png;charset=GB2312"
import="java.awt.*"
import="javax.imageio.*"
import="java.awt.geom.*"
import="java.awt.image.*"
import="java.text.*"
import="java.util.*"
import="com.fatcat.webchart.*"
%>
<%!
Graphics2D g2d;
// 创建一个 990X600 的图像
int width = 990, height = 600;
int counter = 240;
double xPoint[] = new double[counter];
double yPoint[] = new double[counter];
int volume[] = new int[counter]; // 交易手数
double preClose; // 昨日收盘指数
double open, close, max, min; // 今日开盘指数、收盘指数、最高指数、最低指数
// scale: 今日收盘指数与昨日收盘指数之差; ration: scale和昨日收盘指数之商
double scale, ratio;
String time[] = {"09:30", "10:00", "10:30", "11:00",
"11:30", "13:30", "14:00", "14:30", "15:00"};
// 创建虚线笔划
float[] dashes = { 3.f };
BasicStroke bs = new BasicStroke(1.0f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 10, dashes, 0);
// 格式化浮点数的输出格式
DecimalFormat twoDigits = new DecimalFormat("0.00");
// 随机生成并初始化每分钟股市指数及交易手数的数据
public void init()
{
preClose = 1000+Math.random() * 1500; // 初始化昨日收盘指数
max = preClose;
min = preClose;
for (int i = 0; i < counter; i++)
{
if (i == 0)
{
if (Math.random() > 0.5)
yPoint[i] = preClose + Math.random() * 10;
else
yPoint[i] = preClose - Math.random() * 10;
volume[i] = (int)(10000 * (1+Math.random() * 5));
}
else
{
if (Math.random() > 0.5)
{
if ((yPoint[i - 1] + Math.random() * 3) >= preClose * 1.018)
yPoint[i] = yPoint[i - 1] - Math.random() * 3;
else
yPoint[i] = yPoint[i - 1] + Math.random() * 3;
}
else
{
if ((yPoint[i - 1] - Math.random() * 3) <= preClose * 0.982)
yPoint[i] = yPoint[i - 1] + Math.random() * 3;
else
yPoint[i] = yPoint[i - 1] - Math.random() * 3;
}
if (Math.random() > 0.5)
volume[i] = volume[i - 1] + (int)(Math.random() * 10000);
else
volume[i] = volume[i - 1] - (int)(Math.random() * 10000);
if (volume[i] >= 100000)
volume[i] -= 10000+(int)(Math.random() * 5000);
if (volume[i] <= 10000)
volume[i] += 10000+(int)(Math.random() * 5000);
}
// 计算今日开盘指数及收盘指数
if (i == 0)
{
open = yPoint[i];
}
else if (i == counter - 1)
{
close = yPoint[i];
}
// 计算今日最高指数
if (yPoint[i] > max)
{
max = yPoint[i];
}
// 计算今日最低指数
if (yPoint[i] < min)
{
min = yPoint[i];
}
xPoint[i] = 80+i * 840 / 240; // 计算指数走势曲线横坐标
}
scale = close - preClose; // 计算今日收盘指数与昨日收盘指数之差
ratio = scale / preClose; // 计算scale和昨日收盘指数之商
}
public double getMax()
{
return max;
}
public double getMin()
{
return min;
}
public double getOpen()
{
return open;
}
public double getClose()
{
return close;
}
public double getPreClose()
{
return preClose;
}
public double getScale()
{
return scale;
}
public double getRatio()
{
return ratio;
}
// 绘制数字字符
public void drawDigits(Graphics2D g2d, double digits, int x, int y)
{
// 关闭反锯齿功能,用于绘制数字
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
String number = twoDigits.format(digits);
g2d.setFont(new Font("Arial", Font.PLAIN, 18));
String n1 = number.substring(0, number.length() - 3);
g2d.drawString(n1, x, y);
int digitsLength = g2d.getFontMetrics().stringWidth(n1);
x += digitsLength;
g2d.setFont(new Font("Arial", Font.BOLD, 14));
String n2 = number.substring(number.length() - 2);
g2d.drawString(n2, x, y - 3);
digitsLength = g2d.getFontMetrics().stringWidth(n2);
g2d.drawLine(x, y - 1, x + digitsLength, y - 1);
// 重新设置反锯齿功能,用于平滑处理相关图形对象
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
// 设置绘制数字字符所应用的颜色,今日收盘指数大于昨日收盘指数则用红色,反之绿色
public void setDigitColor()
{
if (getScale() >= 0)
{
g2d.setColor(Color.RED);
}
else
{
g2d.setColor(Color.GREEN);
}
}
// 绘制上半部的网格
public void drawTopGrid()
{
// 关闭反锯齿功能,用于绘制数字
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
int stringLength = 0, stringHeight = 0;
int gridWidth = 105, gridHeight = 20;
g2d.setFont(new Font("Courier New", Font.PLAIN, 12));
// 绘制垂直方向的直线
for (int i = 0; i < time.length; i++)
{
g2d.setColor(new Color(168, 0, 0));
if (i % 2 != 0)
{
g2d.setStroke(bs);
}
else
{
g2d.setStroke(new BasicStroke());
}
g2d.drawLine(80+i * gridWidth, 40, 80+i * gridWidth, 360);
}
double max = getPreClose() * 1.02;
// 绘制水平方向的直线
for (int i = 0; i < 17; i++)
{
g2d.setColor(new Color(168, 0, 0));
g2d.drawLine(80, 40+i * gridHeight, 920, 40+i * gridHeight);
g2d.setColor(Color.RED);
String leftStr = "", rightStr = "";
if (i < 17 / 2)
{
leftStr = twoDigits.format(max * (1-i * 0.02 / 8));
rightStr = twoDigits.format(2-i * 0.25);
}
else
{
if (i == 17 / 2)
{
g2d.setColor(Color.WHITE);
leftStr = twoDigits.format(getPreClose());
rightStr = twoDigits.format(0.00);
}
else
{
g2d.setColor(Color.GREEN);
leftStr = twoDigits.format(max * (1-i * 0.02 / 8));
rightStr = twoDigits.format(i * 0.25 - 2);
}
}
// 绘制水平方向上的左边关于指数以及右边关于指数百分比的说明文字
g2d.setFont(new Font("Arial", Font.BOLD, 12));
stringHeight = g2d.getFontMetrics().getAscent();
stringLength = g2d.getFontMetrics().stringWidth(leftStr);
g2d.drawString(leftStr, 75-stringLength, 40+i * gridHeight + stringHeight / 2);
g2d.drawString(rightStr + "%", 925, 40+i * gridHeight + stringHeight / 2);
}
// 重新设置反锯齿功能,用于平滑处理相关图形对象
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
// 绘制下方的网格
public void drawBottomGrid()
{
// 关闭反锯齿功能,用于绘制数字
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
int stringLength = 0, stringHeight = 0;
int gridWidth = 105, gridHeight = 20;
g2d.setFont(new Font("Courier New", Font.PLAIN, 12));
// 绘制垂直方向的直线
for (int i = 0; i < time.length; i++)
{
g2d.setColor(new Color(168, 0, 0));
if (i % 2 != 0)
{
g2d.setStroke(bs);
}
else
{
g2d.setStroke(new BasicStroke());
}
g2d.drawLine(80+i * gridWidth, 380, 80+i * gridWidth, 580);
// 绘制垂直方向上的关于时间段的说明文字
g2d.setColor(Color.WHITE);
stringLength = g2d.getFontMetrics().stringWidth(time[i]);
g2d.drawString(time[i], 80+i * gridWidth - stringLength / 2, 595);
}
// 绘制水平方向的直线
for (int i = 0; i <= 10; i++)
{
g2d.setColor(new Color(168, 0, 0));
g2d.drawLine(80, 380+i * gridHeight, 920, 380+i * gridHeight);
g2d.setColor(Color.YELLOW);
String leftStr = "";
if (i == 10)
leftStr = "5000";
else
leftStr += 10000 * (10-i);
// 绘制水平方向上关于交易手数的说明文字
g2d.setFont(new Font("Arial", Font.BOLD, 12));
stringHeight = g2d.getFontMetrics().getAscent();
stringLength = g2d.getFontMetrics().stringWidth(leftStr);
g2d.drawString(leftStr, 75-stringLength, 380+i * gridHeight + stringHeight / 2);
}
// 重新设置反锯齿功能,用于平滑处理相关图形对象
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
// 绘制指数走势曲线
public void drawIndexCurve()
{
Line2D.Double line = new Line2D.Double();
g2d.setColor(Color.WHITE);
for (int i = 0; i < counter; i++)
{
if (i < counter - 1)
{
line.setLine(xPoint[i], countCurveY(yPoint[i]), xPoint[i + 1], countCurveY(yPoint[i + 1]));
g2d.draw(line);
}
}
}
// 计算指数走势曲线纵坐标的绘制位置
public double countCurveY(double yPoint)
{
double y;
y = 360-(320 * (yPoint - getPreClose() * 0.98) / (getPreClose() * 0.04) );
return y;
}
// 绘制表示交易手数的直线
public void drawVolume()
{
Line2D.Double line = new Line2D.Double();
g2d.setColor(Color.YELLOW);
for (int i = 0; i < counter; i++)
{
line.setLine(xPoint[i], countVolumeY(volume[i]), xPoint[i], 580);
g2d.draw(line);
}
}
// 计算交易手数纵坐标的绘制位置
public double countVolumeY(int volume)
{
return 580-180 * (double)volume / 100000;
}
%>
<%
// 清空缓冲区
response.reset();
// 注意这里的MIME类型
response.setContentType("image/png");
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 创建Java2D对象
g2d = image.createGraphics();
// 打开反锯齿功能,用于平滑处理相关图形对象
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 填充整个背景
g2d.setPaint(Color.BLACK);
g2d.fillRect(0, 0, width, height);
// 初始化绘制指数走势图的相关数据
init();
// 绘制图表顶部文字说明区域
String chartTitle = "上证领先";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
int stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 0, 25);
setDigitColor();
drawDigits(g2d, getClose(), stringLength + 5, 23);
chartTitle = "涨跌";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 190, 25);
setDigitColor();
drawDigits(g2d, Math.abs(getScale()), stringLength + 210, 23);
// 调用TriangleServlet类,绘制坐标轴上的箭头
TriangleServlet ts = new TriangleServlet();
ts.setBaseLine(12);
ts.setAlpha(60);
if (getScale() >= 0)
{
ts.setFillColor(Color.RED);
ts.drawTrigangle(stringLength + 202, 21, 1, 2, g2d); // 绘制红色箭头向上的三角形
}
else
{
ts.setFillColor(Color.GREEN);
ts.drawTrigangle(stringLength + 202, 12, 3, 2, g2d); // 绘制绿箭头向下的三角形
}
chartTitle = "幅度";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 315, 25);
g2d.setFont(new Font("Arial", Font.PLAIN, 18));
setDigitColor();
g2d.drawString("" + twoDigits.format(getRatio() * 100) + "%", 317+stringLength, 23);
chartTitle = "最高";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 448, 25);
if (getMax() >= getPreClose())
{
g2d.setColor(Color.RED);
}
else
{
g2d.setColor(Color.GREEN);
}
drawDigits(g2d, Math.abs(getMax()), stringLength + 450, 23);
chartTitle = "最低";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 580, 25);
if (getMin() >= getPreClose())
{
g2d.setColor(Color.RED);
}
else
{
g2d.setColor(Color.GREEN);
}
drawDigits(g2d, getMin(), stringLength + 582, 23);
chartTitle = "今开";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 720, 25);
if (getOpen() >= getPreClose())
{
g2d.setColor(Color.RED);
}
else
{
g2d.setColor(Color.GREEN);
}
drawDigits(g2d, getOpen(), stringLength + 722, 23);
chartTitle = "昨开";
g2d.setColor(Color.YELLOW);
g2d.setFont(new Font("楷体_GB2312", Font.BOLD, 25));
stringLength = g2d.getFontMetrics().stringWidth(chartTitle);
g2d.drawString(chartTitle, 850, 25);
g2d.setColor(Color.WHITE);
drawDigits(g2d, getPreClose(), stringLength + 852, 23);
// 绘制顶部网格
drawTopGrid();
// 绘制走势曲线
drawIndexCurve();
// 绘制底部网格
drawBottomGrid();
// 绘制交易手数直线
drawVolume();
// 部署图形
g2d.dispose();
// 利用ImageIO类的write方法对图像进行编码
ServletOutputStream sos = response.getOutputStream();
ImageIO.write(image, "PNG", sos);
sos.close();
%>
<%
/**************************************************************************
* (C) Copyright 2004-2005 by Jingkui Zhong(钟京馗) and Huan Tang(唐桓). *
* All Rights Reserved. *
* *
* DISCLAIMER: The authors of this code have used their *
* best efforts in preparing the code. These efforts include the *
* development, research, and testing of the theories and programs *
* to determine their effectiveness. The authors and publisher make *
* no warranty of any kind, expressed or implied, with regard to these *
* programs or to the documentation contained in these codes. The authors *
* shall not be liable in any event for incidental or consequential *
* damages in connection with, or arising out of, the furnishing, *
* performance, or use of these programs. *
**************************************************************************/
%>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -