其实这是个蛋疼的需求, 除了需要画文字之外还需要 把不同用户的二维码也要合成上去,交给前端来做的画 有可能会导致浏览器版本差点的手机会长时间白屏没有反应。现在只能交给后端API方式去请求。
进入正题:
我找了很久都没有找到很好的解决方案,只能取巧的解决一下(笨方法):
如果有其他方法希望大佬们留言告知告知!!!!!!谢谢(*^_^*)(*^_^*)(*^_^*)(*^_^*)
解决方案就是对文字进行判断是否含有Emoji表情符号,然后使用支持符号表情的字体去画,如果是中文的话就很好解决了 直接使用普通字体来画,所以说这是个很笨的方法,一个字符一个字符的去画。。。。。。。我都觉得笨 先用着把 哈哈哈啊哈
第一步:判断字符中是否含有特殊表情符号也就是(UniCode)
/**
* 检测是否有emoji字符
* @param source
* @return 一旦含有就抛出
*/
public static boolean containsEmoji(String source) {
if (StringUtils.isBlank(source)) {
return false;
}
int len = source.length();
for (int i = 0; i < len; i++) {
char codePoint = source.charAt(i);
// 文字
if (!isEmojiCharacter(codePoint)) {
return true;
}
}
return false;
}
public static boolean isEmojiCharacter(char codePoint) {
return (codePoint == 0x0) ||
(codePoint == 0x9) ||
(codePoint == 0xA) ||
(codePoint == 0xD) ||
((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
}
第二步:使用上面的第二个方法(isEmojiCharacter)判断该字符是否是特殊符号(\uD83C\uDF40),
如果是特殊符号的话,加载支持符号的字体进行画即可(这里不是重点)
重点:在画特殊符号之前是需要转义的 不然画出来的还是会乱码 上代码
/**
* unicode 转义输出 "\\ud3c4\\us3f4" 输出表情符号
* @param ascii
* @return
*/
public static String ascii2native(String ascii) {
List ascii_s = new ArrayList();
String zhengz= "\\\\u[0-9,a-f,A-F]{4}";
Pattern p = Pattern.compile(zhengz);
Matcher m=p.matcher(ascii);
while (m.find()){
ascii_s.add(m.group());
}
System.out.println(ascii_s);
for (int i = 0, j = 2; i < ascii_s.size(); i++) {
String code = ascii_s.get(i).substring(j, j + 4);
char ch = (char) Integer.parseInt(code, 16);
ascii = ascii.replace(ascii_s.get(i),String.valueOf(ch));
}
return ascii;
}
这个方法是这坑 如果没有这个转义的话使用字符进行循环 取每一个字符的char在转成String进行绘画的时候他会把
\uD83C中的D83c给转成String,转成String的时候需要把\\u加上,而且需要注意(\uD83C\uDF40)两个一起画才是一个特殊符号
还有一点就是如果把(\uD83C\uDF40)转义后在进行绘画的话也是会乱码的 原因也很简单
String tv = "\uD83C\uDF40";
System.out.println(tv);
System.out.println(ascii2native("\\uD83C\\uDF40"));
System.out.println("\\uD83C\\uDF40");
--------------
输出:
\uD83C\uDF40
这样就很清楚了
上完整一点的代码:
if (containsEmoji(tv)) {
Font enmojiF = Font.createFont(Font.TRUETYPE_FONT, new ClassPathResource("seguiemj.ttf").getFile());
Font emnoji = enmojiF.deriveFont(Font.PLAIN, 30);
int chars = -1;
int len = x;
for (int i = 0; i < tv.length(); i++) {
if (!isEmojiCharacter(tv.charAt(i))) {
if (chars == i) {
continue;
}
chars = i + 1;
ImageUtil.drawText(baseMapBufferedImage, emnoji, color, StringUtils.ascii2native("\\u" + Integer.toHexString((int) tv.charAt(i)) + "\\u" + Integer.toHexString((int) tv.charAt(i + 1))), len, y, null, false);
len += FontDesignMetrics.getMetrics(emnoji).charWidth(tv.charAt(i)) * 2;
}
else {
ImageUtil.drawText(baseMapBufferedImage, font, color, String.valueOf(tv.charAt(i)), len, y, null, false);
len += FontDesignMetrics.getMetrics(font).stringWidth(String.valueOf(tv.charAt(i))) - 5;
}
}
}
else {
ImageUtil.drawText(baseMapBufferedImage, font, color, tv, x, y, null, false);
}
到这里就可以解决 这是个很笨的方法,后来发现一种方法 使用下面的字体可以解决符号文字一起绘画,但是在linux服务器上面会乱码原因也很简单 liinux上面没有这种字体 我本地测试是window 在window服务器上应该是没有上面问题
Font font = new Font("Menlo", Font.BOLD, 30)
到此结束啦 !!!!! 有更好的方法欢迎留言!!!!!!!!!!!!!!!!