在Java绘制图片/画图/添加文字水印等文字内容时候,总感觉y轴有一定的偏差,导致与预期效果不一致,尤其是生产证书类型业务,对不准很影响观感。
首先上graphics.drawString方法的源码解释
/**
* Draws the text given by the specified string, using this
* graphics context's current font and color. The baseline of the
* leftmost character is at position (<i>x</i>, <i>y</i>) in this
* graphics context's coordinate system.
* @param str the string to be drawn.
* @param x the <i>x</i> coordinate.
* @param y the <i>y</i> coordinate.
* @throws NullPointerException if {@code str} is {@code null}.
* @see java.awt.Graphics#drawBytes
* @see java.awt.Graphics#drawChars
*/
public abstract void drawString(String str, int x, int y);
指定字符串和坐标即可。
但是简单认为字符串的起始位置就是左上顶点就错了,这样画起来每次的位置都不对,字体的大小不同,位置偏差很大。仔细看api注释后发现,y坐标是字符串基线位置的坐标,也就是说字符串基线与画布y重合。
字体的高由个元素组成:
drawString中用的y坐标是指baseline的y坐标,即字体所在矩形的左上角 y坐标+ascent
代码示例
BufferedImage srcBi = ImageIO.read("c:/1.jpg");
int owidth = srcBi.getWidth();
int oheight = srcBi.getHeight();
Graphics2D graphics = (Graphics2D)srcBi.getGraphics();
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.setColor(Color.BLUE);
int fontSize = 50;
Font font = new Font("楷体",Font.BOLD,fontSize);
//jdk 17
FontMetrics fontMetrics = graphics.getFontMetrics(font);
//jdk8
//FontDesignMetrics fontMetrics = FontDesignMetrics.getMetrics(font);
graphics.setFont(font);
int ascent = fontMetrics.getAscent();
//画字符串,x坐标即字符串左边位置,y坐标是指baseline的y坐标,即字体所在矩形的左上角y坐标+ascent
//基线对齐改为顶边对齐
改进前代码:
//graphics.drawString(DateUtil.formatDate(new java.util.Date(),DateUtil.FULL_TRADITION_PATTERN),10,10);
//改进后
graphics.drawString(DateUtil.formatDate(new java.util.Date(),DateUtil.FULL_TRADITION_PATTERN),10,10+ascent);
代码示例
String centerWords = "居中文字";
int strWidth = fontMetrics.stringWidth(centerWords);
int strHeight = fontMetrics.getHeight();
//左边位置
int left = (owidth-strWidth)/2;
//顶边位置+上升距离(原本字体基线位置对准画布的y坐标导致字体偏上ascent距离,加上ascent后下移刚好顶边吻合)
int top = (oheight-strHeight)/2+fontMetrics.getAscent();
graphics.drawString(centerWords,left,top);
https://blog.xqlee.com/article/2506061008408147.html