教你Java5分钟制作海报、彻底解决APP兼容性问题

一、需求背景

​ 我们经常在多终端应用开发中会遇到这样的需求:用户在浏览商品时觉得不错,希望分享给朋友。此时终端(安卓、苹果、H5等)生成一张精美的商品海报,通过微信或者其他途径分享给他人。也可能会遇到需求:制作个人名片打印出来或者分享给他人。效果大概是这样的:

也可能是这样

示例2 示例3

(上面的图都是我从网上临时找的,只做参考学习,避免广告已经做了部分处理。)

刚开始设计这个需求的时候,我们是在前端来完成的,即由安卓、IOS、H5、微信几个端的开发者自主实现功能。各端完成开发后发布到全网,很快就发现一些用户机型上出现了兼容性的问题(C端安卓机型有很多版本)。用户手机安卓版本从5.N到最新的版本、从ip6到最新款,最大跨度超10年,这种兼容性问题对我们来说无法预料。曾尝试使用的dom-to-image和html2canvas效果都不太理想,解决了白屏、跨域问题又遇到低版本不支持标签的问题…。一通折腾,最后我们决定在服务端将海报图片生成好,在终端直接显示图片。

二、用JAVA生成海报

从上面的三张海报,我选《美女》图,作为今天演示效果。(在做此演示时并没有使用之前项目上的图,我也是首次照着图在开发)。

首先将海报分别为3类,背景图、其他图、文字、二维码。

如: 1-底图纯白,2-商品介绍图,3-头像 素材,4-“严选”字样的图素材,5-带色的二维码,6-标题、价格等文字,实际开发中根据视觉和美工给的图即可。

先上我完成的最终效果:

简单做一下,大概和视觉图差不多了, 虽然有点糙但足以表达到效果。

2.1 Easy Poster 易海报生成器

​ 在开发海报过程中,我也找了不少资料,花费了较多时间,后来发现了Easy Poster的设计还是不错的。所以在开发结束以后,我对代码进行了重新整理完善:修复了一些问题,并增加了二维码功能,成为开箱即用的海报生成工具。

接下来,我将介绍一下如何用来快速的制作海报。

创建一个新的海报,只需要3步即可完成

  • 修改pom.xml添加依赖和打包过滤字体库。
  • 创建海报对象及配置相关属性。
  • 传入参数,生成海报

2.2修改pom.xml添加依赖和打包过滤字体库。

pom.xml

<properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><lombok.version>1.16.18</lombok.version><hutool-all.version>5.7.19</hutool-all.version><zxing.version>3.4.1</zxing.version><testng.version>6.8.8</testng.version><slf4j.version>1.7.13</slf4j.version>
</properties>
<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>compile</scope></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><!-- 二维码生成 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>${zxing.version}</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool-all.version}</version></dependency><dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>${testng.version}</version><scope>test</scope></dependency>
</dependencies>
<!-- SpringBoot项目的maven项目引用的字体库font经过maven的filter,会破坏font文件的二进制文件格式 -->
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><configuration><nonFilteredFileExtensions><nonFilteredFileExtension>ttf</nonFilteredFileExtension><nonFilteredFileExtension>woff</nonFilteredFileExtension><nonFilteredFileExtension>woff2</nonFilteredFileExtension></nonFilteredFileExtensions></configuration></plugin></plugins>
</build>

*注意:我们海报用到了字体作为资源文件引入,在经过maven的filter,会破坏font文件的二进制文件格式 导致打包异常,此处要一定要注意。

2.3 创建海报对象及配置相关属性

CommodityPosterPojo.java

package com.naiqing.poster.demo;import com.quaint.poster.annotation.PosterBackground;
import com.quaint.poster.annotation.PosterBarCodeCss;
import com.quaint.poster.annotation.PosterFontCss;
import com.quaint.poster.annotation.PosterImageCss;
import com.quaint.poster.core.abst.AbstractDefaultPoster;
import com.quaint.poster.core.dto.PosterBarcode;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Tolerate;import java.awt.*;
import java.awt.image.BufferedImage;/*** 〈商品分享海报元素及相关参数定义〉<br>** @author naiqing* @Date 2022/1/21* @see [相关类/方法]* @since [产品/模块版本]*/
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
public class CommodityPoster2Pojo extends AbstractDefaultPoster {/*** 背景图*/@PosterBackground(width = 540, height = 868)private BufferedImage backgroundImage;/*** 商品图*/@PosterImageCss(position = {0, 0}, width = 540, height = 614)private BufferedImage commodityImage;/*** 严选图标*/@PosterImageCss(position = {16, 625}, width = 50, height = 28)private BufferedImage yanxuanImage;/*** 商品标题*/@PosterFontCss(position = {16, 625}, size = 22, canNewLine = {1, 482, 2}, style = Font.BOLD)private String commodityTitle;/*** 特权价*/@PosterFontCss(position = {16, 706}, size = 20, color = {247,23,61})private String vipPrice;/*** 原价*/@PosterFontCss(position = {16, 742}, size = 15, color = {51, 51, 51}, delLine = true)private String oldPrice;/*** 头像*/@PosterImageCss(position = {10, 780}, width = 55, height = 55, circle = true)private BufferedImage headImage;/*** 昵称*/@PosterFontCss(position = {77, 788}, color = {85,85,85}, name = "腾祥爱情体细简", style = Font.BOLD)private String nickName;/*** 昵称下的描述*/@PosterFontCss(position = {75, 813}, size = 15, color = {104,104,104}, name = "腾祥爱情体细简")private String nickDesc;/*** 二维码*/@PosterBarCodeCss(position = {376, 695}, width = 130, height = 130, foreColor = {17,125,124})private PosterBarcode qrCode;/*** 二维码字*/@PosterFontCss(position = {386, 833}, size = 20, color = {104,104,104}, center = true)private String qrCodeText;@Toleratepublic CommodityPoster2Pojo() {}
}

此处定义了海报全部的元素,通过注解:背景图片@PosterBackground、其他图片@PosterImageCss、字体

@PosterFontCss和二维码@PosterBarCodeCss,来配置位置、宽度等参数(更多参数可通过源码了解)。

@PosterBarCodeCss 二维码注解,只适用类PosterBarcodeDto

@PosterBackground 背景图片注解、@PosterImageCss,只适用类BufferedImage

@PosterFontCss文字注解,只适用类String

  • 如何快速得到x\y坐标和width\heigth尺寸

    正常来说,视觉稿给到我们开发的时候,页面上都是可以快速得到每个元素的位置和尺寸,但此处因为是从网上找到整图,所以只能自己动手了。

    此处我是通过ps打开图片,打开”窗口-信息“,可以查看到鼠标的坐标及圈选的尺寸,如下图可以快速得到各元素的位置:

2.5 传入参数,生成海报

1) 加载字体库

在此调用生成海报之前,我们要将用到的字体库放到项目中,比如说我这里用到了2个字体库:resources\fonts\simkai.ttfresources\fonts\TTAiQingXiJ_0.ttf

这里我要特别说明:如果不加载字体库在windows下也是可以直接使用的(会默认使用宋体),但是在将服务发布到服务器下Linux时所有中文都会乱码,因为Linux下并没有相应字体库。

2)生成海报

我用一个单元测试来实现海报生成调用示范,传入商品名称相关信息

package com.naiqing.poster.demo;import com.quaint.poster.core.dto.PosterBarcode;
import com.quaint.poster.core.impl.PosterBarcodeImpl;
import lombok.SneakyThrows;
import org.testng.annotations.Test;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;/*** 〈测试海报〉<br>** @author naiqing* @Date 2022/1/22* @see [相关类/方法]* @since [产品/模块版本]*/
public class CommodityPoster2Test {@SneakyThrows@Testpublic void testCreate() {//背景图,此处测试我是用的本地图,实际开发可换成网络获取图片(下面有示例)BufferedImage backgroundImage = ImageIO.read(new File("D:\\temp\\s_bg.jpg"));//商品主图BufferedImage commodityImage = ImageIO.read(new File("D:\\temp\\s_commodity.jpg"));//严选图标BufferedImage yanxuanImage = ImageIO.read(new File("D:\\temp\\s_yanxuan.jpg"));//头像BufferedImage headImage = ImageIO.read(new File("D:\\temp\\s_head.jpg"));//二维码logoBufferedImage qrLogo = headImage;//二维码内容String qrContent = "http://www.baidu.com";//全局默认字体(如果不将字体库资源引入,在windows下没问题,但linux没有默认的"宋体"会显示乱码)InputStream in1 = this.getClass().getResourceAsStream("/fonts/simkai.ttf");Font defaultFont = Font.createFont(Font.TRUETYPE_FONT, in1);//昵称显示的字体(此字体库是从网上下载的,非windows自带),使用时引用FontName字体名称即可(字体名称:双击字体库可以看到字体名称)InputStream in2 = this.getClass().getResourceAsStream("/fonts/TTAiQingXiJ_0.ttf");Font txin2 = Font.createFont(Font.TRUETYPE_FONT, in2);CommodityPoster2Pojo shareCommodityInfo = CommodityPoster2Pojo.builder().backgroundImage(backgroundImage).commodityImage(commodityImage).yanxuanImage(yanxuanImage).commodityTitle("         雾中女孩2022冬季新款女装连帽拉链长袖棉服 WH88888").vipPrice("特权价¥0.01").oldPrice("售价¥268").headImage(headImage).nickName("叫我胡歌啊").nickDesc("邀请好友享受内部优惠价").qrCode(PosterBarcode.builder().content(qrContent).logo(qrLogo).build()).qrCodeText("微信扫一扫").build();//创建海报生成器PosterBarcodeImpl<CommodityPoster2Pojo> poster = new PosterBarcodeImpl<>();//设置默认字体库  /安装用到的全部字体库(支持传多个)poster.defaultFont(defaultFont).installFonts(txin2,...);//生成海报BufferedImage image = poster.annotationDrawPoster(shareCommodityInfo).draw(null);ImageIO.write(image, "png", new File("D:\\temp\\out2.png"));}
}

可以看到用起来还是非常简单的,开箱即用!有了这个工具,5分钟可以搞一个海报出来!再也不需要去考虑APP端的不确定的兼容问题了,也不用兴师动众让安卓、苹果、H5等多端的开发者多人开发了。美滋滋~

我上面的示例是使用的本地图,也可以使用图片链接。

   //远程图片BufferedImage backgroundImage = ImageIO.read(new URL("https://img-blog.csdnimg.cn/8bf7094ae7b044f495035c8ea734dca8.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6LGB6L6-6aOO562d,size_18,color_FFFFFF,t_70,g_se,x_16"));
  • 如何使用自定义字体库?

​ 当我们在制作海报时,视觉给的效果图可能除了颜色、粗体要求以外,可能还会要求使用指定的字体。此时我们要拿到此字体库文件”*.ttf“并放到项目资源目录下,比如我的是resources\fonts\*.ttf

​ 第二步,是我们要得到此字体库的字体名称,在创建海报时配置@PosterFontCss 设置字体需要指定字体名称。双击此字体库文件,第一行就能看到字体名称,如下图:

  • 如何将海报图片转成base64返回给前端

    //将生成的海报图片以base64形式回写至终端
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    ImageIO.write(image, "png", stream);
    String asBase64 = "data:image/png;base64,"+Base64.encode(stream.toByteArray());
    System.out.println(asBase64);
    

三、 用到的技术及相关源码

3.1 Easy Poster 易海报生成器

​ 以上的源码和示例代码均在gitee上,可直接下载。欢迎大家一起来修复完善此工具。
https://gitee.com/naiqing/easyposter

在此特别感谢框架Easy Poster 的作者,我是基于此框架,修复了一些问题后进行的二次开发。

3.3 二维码生成zxing

对于二维码的生成我是使用了谷歌的zxing,然后利用hutool-all来简化调用。

教你Java5分钟制作海报、彻底解决APP兼容性问题相关推荐

  1. Java5分钟制作海报

    一.需求背景 我们经常在多终端应用开发中会遇到这样的需求:用户在浏览商品时觉得不错,希望分享给朋友.此时终端(安卓.苹果.H5等)生成一张精美的商品海报,通过微信或者其他途径分享给他人.也可能会遇到需 ...

  2. 《教你10分钟制作3D网游》视频吐槽

    源自GAMERES社区的MGE引擎(也即神秘游戏引擎),近期曝光了第一份制作游戏的带演示视频,透过视频我们发现,这不仅是一份演示或教程,更是一个略带心酸的故事. 视频刚开始,在悲伤的气氛下介绍了作者从 ...

  3. asp.net 报表页面模板_20套大屏模板,教你3分钟制作出酷炫的可视化大屏

    犹记得好莱坞大片<摩天营救>中,监控中心的全方位展示屏幕给人印象深刻,而这种立体化大屏幕似乎已成了科幻电影大片的标配.其实,这种逼格很高的镜头就是一个数据可视化大屏.如今在会议展厅.园区管 ...

  4. linux手机刷机包制作工具_大神教你五分钟制作安卓ROM包 ROM包修改教程

    之前很多人在网上问:"如何自己制作安卓ROM包?"今天,刷机帮的小编就给大家分享一篇关于安卓ROM包制作以及修改的实用教程,感兴趣的朋友可以一起来看看,当然,老司机就直接略过. 制 ...

  5. 炫酷大屏demo_20套大屏模板,教你3分钟制作出酷炫的可视化大屏

    犹记得好莱坞大片<摩天营救>中,监控中心的全方位展示屏幕给人印象深刻,而这种立体化大屏幕似乎已成了科幻电影大片的标配.其实,这种逼格很高的镜头就是一个数据可视化大屏.如今在会议展厅.园区管 ...

  6. python语言表白超炫图形_经验分享 篇二:三分钟教你用Excel制作各种尺寸、底色的证件照...

    经验分享 篇二:三分钟教你用Excel制作各种尺寸.底色的证件照 2018-12-29 07:00:00 654点赞 7174收藏 245评论 一.前言 继上一篇用PPT制作了证件照以后 有的值友反应 ...

  7. 教你用PS制作创意分割海报,让海报更有新意

    公司制作宣传海报的时候要考虑到很多因素,其中一个就是要有创意,能够吸引用户的眼球:具有新意的海报才能给人眼前一亮的感觉,怎么制作海报才能别具一格呢?小编今天教大家一个用PS制作创意分割海报的方法,让你 ...

  8. java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题

    文章目录 先看成品 前言 一.项目目录结构 一.海报制作PosterUtil.java工具类 1. 描述 2. 代码 二.测试生成海报 1. 描述 2. 直接上代码 四.其他测试 1. Test1_C ...

  9. 5 分钟,教你用 Python 制作一个生日提醒!

    大家好,我是安果! 在国内,大部分人都是过农历生日,然后借助日历工具获取农历日期对应的阳历日期,以这一天来过生! 这里还有一个痛点,即:每一年的农历生日对应的阳历日期都不一样 本篇文章将教你利用 Py ...

最新文章

  1. Python程序员Debug利器,和Print说再见 | 技术头条
  2. 回归模型-线性回归算法
  3. Java并发编程:Thread类的使用
  4. python取特定年份的数据_python,_怎样用python提取不同股票csv里特定时间段的数据,python - phpStudy...
  5. kafka一直rebalance故障,重复消费
  6. quick time不可用是什么意思_fpga是什么意思(fpga怎么用)
  7. 【使用注意】Jsoup的select方法
  8. Eclipse构建Maven分包分模块项目并构建服务端
  9. 波特率与频率的换算公式?_高中物理公式总结表
  10. 【报告分享】“十四五”时期的战略机遇-招商证券.pdf(附下载链接)
  11. Spark:windows下配置spark开发环境
  12. iOS开发UIScrollView使用详解
  13. php前段时间戳转字符串,JavaScript_js获取时间并实现字符串和时间戳之间的转换,废话少说,直接上代码 复制 - phpStudy...
  14. VARCHART XGantt甘特图具有更多功能的HTML5 / Gantt图表的可视计划小部件
  15. 科技爱好者周刊(第 148 期):微增长时代
  16. 4种方法解决鼠标反应慢(迟钝)
  17. 【转】PV3D的小练习~太阳系八大行星
  18. ubuntu18.04安装cudnn出现错误:FreeImage is not set up correctly. Please ensure FreeImae is set up correctly
  19. RecyclerView让置顶项置顶
  20. linux vi 编辑器下经常会用到保存退出与不保存退出

热门文章

  1. 进程间通信之匿名管道和命名管道
  2. 图腾42u服务器机柜型号,图腾42u机柜一般多少斤
  3. [校园网]UDP绕过校园网,纯手工搭建Linux版
  4. 低级格式化的主要作用(转)
  5. C语言编程图书销售系统,C语言图书销售的管理系统.doc
  6. Mysql全套看这一篇就够了特别详细
  7. jQuery--事件、效果
  8. 昂达v80 plus linux,昂达V80 Plus平板电脑评测 眼就被惊艳到了
  9. 《念奴娇.赤壁怀古》
  10. TypeScript设计模式之策略、模板方法