jsp页面如何画线,折现,箭头等。
我有这样一个需求
web页面上有字符串 A1 ,A2, A3分别表示三个模块
点击A1,A2,A3会分别进入到A1 ,A2, A3的详细表示画面。
A1 ,A2, A3之间有调用关系,这种调用关系希望能够通过线和箭头标识出来。
例如
A1 A3
A2
A4
A1调用A2,A2调用A4,所以A1与A2之间要画一个箭头,A2与A4之间要画一个箭头, A1与A3之间是并列的关系,要画一个横向的箭头。
请问上面的需求应该用什么技术实现?
[解决办法]
vml 标签可以 不过是ie上的
[解决办法]
js 坐标
[解决办法]
- Java code
import javax.swing.*;import java.awt.*;<p>/** * 在两个Swing控件之间画箭头 * @author <a:href = "mailto:seth_yang@21cn.com">seth yang</a> */public class Arrow { /** 源控件,即箭头的出发控件 */ private JComponent source; /** 目标控件,即箭头的指向控件 */ private JComponent target; /** 箭头中间的文本,通常是该箭头标识的关系的名称 */ private String name = ""; /** 源控件关联出去的字段 */ private String sourceField = ""; /** 目标控件的关联字段 */ private String targetField = ""; /** 箭头扇形的开始角度 */ private int startAngle = 0;<p> /** 箭头扇形的半径 */ private static final int ARROW_HEIGHT = 20; /** 箭头扇形的角度 */ private static final int ARROW_ANGLE = 30;<p> public Arrow (JComponent source, JComponent target) { this (source.getName () + "_" + target.getName (), source, target); } /** * 构造函数 * * 创建指定名称,源控件和目标控件的箭头 * @param name 箭头的名称 * @param source 箭头的出发控件 * @param target 箭头的指向控件 */ public Arrow (String name, JComponent source, JComponent target) { this (name, source, target, source.getName (), target.getName ()); }<p> /** * 构造函数 * * 创建指定名称,源控件和目标控件的箭头 * @param name 箭头的名称 * @param source 箭头的出发控件 * @param target 箭头的指向控件 * @param sourceField 箭头的出发字段 * @param targetField 箭头的指向字段 */ public Arrow (String name, JComponent source, JComponent target, String sourceField, String targetField) { setName (name); setSource (source); setTarget (target); this.setSourceField (sourceField); this.setTargetField (targetField); }<p> private Point getCenter (JComponent c) { int x = c.getLocation ().x; int y = c.getLocation ().y; int w = c.getSize ().width; int h = c.getSize ().height;<p> return new Point (x + w / 2, y + h / 2); }<p> public void draw (Graphics g) { g.setColor (Color.black); Point ps = getClosestPoint (getTarget (), getSource ()); Point pt = getClosestPoint (getSource (), getTarget ()); // 画线 g.drawLine (ps.x, ps.y, pt.x, pt.y);<p> // 画箭头 // 简单起见,在这里从线段终点填充一个30度的扇形 if (ps.x != pt.x && ps.y != pt.y) { double k = getK (ps, pt); if (ps.x > pt.x) startAngle = 360 - (int) (Math.atan (k) * 180 / Math.PI) - 15; else startAngle = 180 - (int) (Math.atan (k) * 180 / Math.PI) - 15; } // 圆心 Point pc = new Point (pt.x - ARROW_HEIGHT, pt.y - ARROW_HEIGHT); g.fillArc (pc.x, pc.y, 2 * ARROW_HEIGHT, 2 * ARROW_HEIGHT, startAngle, ARROW_ANGLE);<p> FontMetrics fm = g.getFontMetrics (); int ascent = fm.getAscent (); int descent = fm.getDescent ();<p> // 在线条中心点处显示名称 int mx = (ps.x + pt.x) / 2; int my = (ps.y + pt.y) / 2; g.drawString (name, mx, my + ascent);<p> if (sourceField == null) sourceField = ""; if (targetField == null) targetField = "";<p> if (ps.y < pt.y) {// 源在目标上方,目标文字应该在更上面一些,源文字应该更下面一些 // 在箭头处显示目标 if (ps.x > pt.x) // 目标在源的左方 g.drawString (getTargetField (), pt.x - fm.stringWidth (getTargetField ()), pt.y - ascent - descent); else g.drawString (getTargetField (), pt.x, pt.y - ascent - descent); // 在线段起点处显示源 g.drawString (getSourceField (), ps.x, ps.y + ascent); } else { // 在箭头处显示目标 if (ps.x > pt.x) // 目标在源的左方 g.drawString (getTargetField (), pt.x - fm.stringWidth (getTargetField ()), pt.y + ascent + descent); else g.drawString (getTargetField (), pt.x, pt.y + ascent + descent); // 在线段起点处显示源 g.drawString (getSourceField (), ps.x, ps.y - descent); } }<p> /** * @param source 源控件 * @param target 目的控件 */ private Point getClosestPoint (JComponent source, JComponent target) { Point ps = getCenter (source); Point pt = getCenter (target);<p> if (ps.x == pt.x) { // 垂直线 if (ps.y < pt.y) {// 源在目标上方 this.startAngle = 90 - ARROW_ANGLE / 2; return new Point (ps.x, target.getLocation ().y); } startAngle = 270 - ARROW_ANGLE / 2; return new Point (ps.x, target.getLocation ().y + target.getSize ().height); }<p> if (Math.abs (ps.y - pt.y) < 15) { // 水平线 if (ps.x < pt.x) {// 源在目标左边 startAngle = 180 - ARROW_ANGLE / 2; return new Point (target.getLocation ().x, ps.y); } startAngle = - ARROW_ANGLE / 2; return new Point (target.getLocation ().x + target.getSize ().width, ps.y); }<p> double k0 = getK (ps, pt); // 直线方程: // y = kx + b // x = (y - b) / k double b = getB (ps, pt); int xt = target.getLocation ().x; int yt = target.getLocation ().y; int w = target.getWidth (); int h = target.getHeight ();<p> class DPoint extends Point { public static final int D_H = 0; public static final int D_V = 1; private int d;<p> public DPoint (int x, int y, int d) { super (x, y); this.d = d; }<p> public int getD () { return d; } }<p> // 取于水平边相交的点 DPoint[] pts = new DPoint[4]; // 取上边的点 DPoint pq = new DPoint ((int) ((yt - b) / k0), yt, DPoint.D_H); pts[0] = pq;<p> // 取下边的点 pq = new DPoint ((int) ((yt + h - b) / k0), yt + h, DPoint.D_H); pts[1] = pq; // 取左边的点 pq = new DPoint (xt, (int) (k0 * xt + b), DPoint.D_V); pts[2] = pq; // 取右边的点 pq = new DPoint (xt + w, (int) (k0 * (xt + w) + b), DPoint.D_V); pts[3] = pq;<p> DPoint p1 = null; DPoint p2 = null; for (int i = 0; i < pts.length; i++) { DPoint p = pts[i]; if (p.x < target.getLocation ().x || p.x > target.getLocation ().x + target.getSize ().width || p.y < target.getLocation ().y || p.y > target.getLocation ().y + target.getSize ().height) continue; if (p1 == null) p1 = p; else p2 = p; }<p> if (p1.getD () == DPoint.D_H) { // 水平线 if (Math.abs (p1.y - ps.y) < Math.abs (p2.y - ps.y)) return p1; return p2; } else { // 垂直线 if (Math.abs (p1.x - ps.x) < Math.abs (p2.x - ps.x)) return p1; return p2; } }<p> /** }
[解决办法]
最简单的就是你弄个图片啊 做好图片 比如一个箭头的图片 显示就好了。。
大小位置 随意部署啊。。
[解决办法]
弄个图片不行吗?干嘛这么麻烦,直接用webdings就可以了吧。
[解决办法]
顶三楼 我原以为只能用图片呢,没想到用java代码也能实现