java使用Graphics2D繪圖/畫圖方式
一、筆者在開發(fā)過程中遇到生成分享海報的需求
需要后端動態(tài)生成分享圖(最終前端自己實現(xiàn)的,哈哈);記錄下過程中遇到的一些問題和解決辦法。
二、Graphics2D常用API
首先獲取Graphics2D實例
BufferedImage bi = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = bi.createGraphics(); // 開啟抗鋸齒 RenderingHints renderingHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 使用高質(zhì)量壓縮 renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); graphics.setRenderingHints(renderingHints);
1、graphics.drawImage(),往畫布添加圖片,參數(shù)有位置及圖片寬高
BufferedImage bgmImage = ImageIO.read(new ByteArrayInputStream(FileUtils.readFileToByteArray(new File("filePath")))); graphics.drawImage(bgmImage, x, y, width, height, null);
2、graphics.drawString(),往畫布上添加文字(自動換行需自己實現(xiàn))
graphics.setFont(new Font("PingFangSC-Regular", Font.PLAIN, 24)); graphics.setColor(Color.WHITE); graphics.drawString(title, x, y);
3、graphics.fillRoundRect(),帶背景色的圓角矩形(用于給文字畫背景色,注意要先畫矩形背景,再畫文字上去),最后兩個參數(shù)是設(shè)置圓角弧度
// 背景色矩形 graphics.setColor(new Color(254, 68, 82)); graphics.fillRoundRect(x, y, width, height, 4, 4);
三、上才藝
1、剛剛提到的畫文字自動換行需要自己實現(xiàn),這里簡單說下實現(xiàn)原理;其實就是根據(jù)設(shè)置的行寬及要畫進去的字符串做一個計算,每個文字的行寬是可以拿到的,這樣就能算出每行能展示多少個字,然后就能算出總共分多少行展示,最后循環(huán)調(diào)用graphics.drawString()方法畫上去就好了;下面是換行的核心代碼:
private static int drawStringAutoLineFeed(Graphics g, String strContent, int rowWidth, int x, int y) { String[] split = strContent.split("\n"); int total = 0; for (String str : split) { int height = drawStringAutoLine(g, str, rowWidth, x, y); total += height; y += height; } return total; } /** * 根據(jù)指定寬度自動換行 * * @param g * @param rowWidth * @param strContent * @param x * @param y */ private static int drawStringAutoLine(Graphics g, String strContent, int rowWidth, int x, int y) { // 獲取字符串 字符的總寬度 int strWidth = getStringLength(g, strContent); // 獲取字符高度 int strHeight = getStringHeight(g); // 字符串總個數(shù) int rows = 0; if (strWidth > rowWidth) { int rowStrNum = getRowStrNum(strContent.length(), rowWidth, strWidth); rows = getRows(strWidth, rowWidth); String temp = ""; for (int i = 0; i < rows; i++) { // 獲取各行的String if (i == rows - 1) { // 最后一行 temp = strContent.substring(i * rowStrNum, strContent.length()); } else { temp = strContent.substring(i * rowStrNum, i * rowStrNum + rowStrNum); } if (i > 0) { // 第一行不需要增加字符高度,以后的每一行在換行的時候都需要增加字符高度 y = y + strHeight; } g.drawString(temp, x, y); } } else { // 直接繪制 g.drawString(strContent, x, y); } return strHeight * rows; } private static int getDrawStringAutoLineHeight(Graphics g, String strContent, int rowWidth) { String[] split = strContent.split("\n"); int height = 0; for (String str : split) { // 獲取字符串 字符的總寬度 int strWidth = getStringLength(g, str); // 獲取字符高度 height += getStringHeight(g) * getRows(strWidth, rowWidth); } return height; } private static int getStringLength(Graphics g, String str) { char[] strChar = str.toCharArray(); return g.getFontMetrics().charsWidth(strChar, 0, str.length()); } // 每一行字符的個數(shù) private static int getRowStrNum(int strNum, int rowWidth, int strWidth) { int rowsNum = 0; rowsNum = (rowWidth * strNum) / strWidth; return rowsNum; } // 字符行數(shù) private static int getRows(int strWidth, int rowWidth) { int rows = 0; if (strWidth % rowWidth > 0) { rows = strWidth / rowWidth + 1; } else { rows = strWidth / rowWidth; } return rows; } // 字符高度 private static int getStringHeight(Graphics g) { return g.getFontMetrics().getHeight(); }
使用方法:
graphics.setFont(new Font("PingFangSC-Regular", Font.PLAIN, 12)); graphics.setColor(Color.GRAY); drawStringAutoLineFeed(graphics, strContent, rowWidth, x, y);
四、輸出圖片
1、輸出圖片字節(jié)數(shù)組
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageIO.write(bi, "jpg", outputStream); return outputStream.toByteArray();
2、直接輸出圖片文件
ImageIO.write(bi, "jpg", new File("outFilePath"));
五、總結(jié)
1、簡單的并且圖片是固定尺寸和樣式的場景還比較好使
2、調(diào)試過程非常的惡心,不斷生成圖片看效果
3、樣式較為負責的推薦讓前端html2image,筆者的前端同事已經(jīng)實現(xiàn),效果比后端畫圖好很多!
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java基于狀態(tài)模式實現(xiàn)的文檔編輯模式切換功能實例
這篇文章主要介紹了Java基于狀態(tài)模式實現(xiàn)的文檔編輯模式切換功能,結(jié)合實例形式詳細分析了狀態(tài)模式的概念、原理及java使用狀態(tài)模式實現(xiàn)文檔編輯模式切換操作相關(guān)技巧與注意事項,需要的朋友可以參考下2018-05-05RxJava的消息發(fā)送和線程切換實現(xiàn)原理
這篇文章主要介紹了RxJava的消息發(fā)送和線程切換實現(xiàn)原理,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11MybatisPlus 主鍵策略之type=IdType.ASSIGN_ID等詳解
雪花算法(雪花)是微博開源的分布式ID生成算法其核心思想就是:使用一個64位的長型的數(shù)字作為全局唯一ID,這篇文章主要介紹了MybatisPlus 主鍵策略(type=IdType.ASSIGN_ID等詳解),需要的朋友可以參考下2024-04-04SpringBoot使用Spring Test進行集成測試的流程步驟
Spring Test 是 Spring Framework 提供的一個測試框架,它可以幫助我們進行集成測試,在本文中,我們將介紹如何使用 Spring Test 進行集成測試,需要的朋友可以參考下2023-06-06