PHP 生成分享海报

因为用户端有多个平台,如果做分享海报生成,需要三端都来做,工作量比较大。

所以这个艰巨的任务就光荣的交给后端了。经过一定时间的研究和调试,最终圆满完成了任务,生成分享海报图片实现笔记如下。

目录

准备字体文件

准备海报的图片素材

创建图片

调用

海报截图

总结


准备字体文件

字体文件需与设计图字体保持一致,所以需要下载使用相同的字体文件,否则效果肯定

不符合设计。这里实现使用的是阿里普惠体,下载到项目静态文件路径中,以备调用。

字体文件如下:

准备海报的图片素材

在真实的业务中,海报所需的图片素材来自于活动、商品、用户、小程序码,直接去准备相应的素材即可。在demo中使用了固定的图片素材。

如下:

创建图片

创建图片使用了PHP语言GD库的画图函数。

为方便调用和修改,已经将参数和最终方法进行了封装调用。

具体代码如下:

// 字体
const FONT = '/font/AlibabaPuHuiTi-3-55-Regular.ttf';
const FILEPATH = './test.png';/*** 获取字体全路径* @return string*/
function getFont()
{return dirname(__FILE__) . FONT;
}/*** 生成活动分享海报*/
function activity_poster()
{// 使用参数$param = ['id'            =>  1,  //活动id'title'         =>  '活动标题活动标题活动标题', //活动标题'text'          =>  '活动描述活动描述活动描述活动描述活动描述活动描述活动描述活动描述活动描述活动描述活动描述活动描述', // 活动描述'member_nick'   =>  '一个高尚的人,一个脱落了低级趣味的人', // 团长昵称'member_image'  =>  './img/head.png', // 团长头像'createTime'    =>  date('m/d H:i:s', time()), // 分享时间'cover'         =>  './img/big.png', // 封面图片'mini_logo_img' =>  './img/qr.png', // 小程序码'price'         =>  100,'mini_bg'       =>  './img/min_bg.png'];$refer_qrcode_logo = createPoster($param);if (file_exists($refer_qrcode_logo)) {echo FILEPATH;die;} else {echo '创建失败';}
}/*** 创建海报* @param $param* @return string*/
function createPoster($param)
{$font = getFont();// 存储图片路径$refer_qrcode_logo = FILEPATH;// 判断是否已生成海报if (!file_exists($refer_qrcode_logo)) {// 创建一个白色背景图$back_width = 530;$back_height = 1000;$t_logo2 = imagecreatetruecolor($back_width, $back_height);$background2 = imagecolorallocate($t_logo2, 255, 255, 255);imagefill($t_logo2, 0, 0, $background2);// 定义边距$left = 30;$top = 26;$textcolor = imagecolorallocate($t_logo2, 24, 24, 24);$textcolor2 = imagecolorallocate($t_logo2, 189, 189, 189);$textcolor3 = imagecolorallocate($t_logo2, 165, 165, 165);$textRed = imagecolorallocate($t_logo2, 254, 48, 49);// 团长头像$head_width = 64;$head_height = 64;$member_image = imagecreatefromstring(file_get_contents($param['member_image']));$source_info = getimagesize($param['member_image']);imagecopyresampled($t_logo2, $member_image, $left, $top, 0, 0, $head_width, $head_height, $source_info[0], $source_info[1]);// 团长昵称$nick_x = 106;$nick_y = 56;// 昵称过长处理$member_nick = $param['member_nick'];if (mb_strlen($member_nick) > 12) {$member_nick = mb_substr($member_nick, 0, 12) . '...';}imagefttext($t_logo2, 20, 0, $nick_x, $nick_y, $textcolor, $font, mb_convert_encoding($member_nick, 'html-entities', 'UTF-8'));// 分享时间$time_x = 106;$time_y = 85;imagefttext($t_logo2, 18, 0, $time_x, $time_y, $textcolor2, $font, mb_convert_encoding($param['createTime'], 'html-entities', 'UTF-8'));// 封面$cover_width = 470;$cover_height = 516;$cover_y = 110;$logo = imagecreatefromstring(file_get_contents($param['cover']));$source_info = getimagesize($param['cover']);imagecopyresampled($t_logo2, $logo, $left, $cover_y, 0, 0, $cover_width, $cover_height, $source_info[0], $source_info[1]);// 活动标题$y = 642;$line_split = 5;$goods_name_size = 30;$title_width = $back_width - ($left * 2);// 换行处理$text_array = draw_txt_to(array('fontsize' => $goods_name_size, 'width' => $title_width, 'left' => 0), $param['title']);foreach ($text_array as $text) {$y += $goods_name_size + $line_split;imagefttext($t_logo2, $goods_name_size, 0, $left, $y, $textcolor, $font, mb_convert_encoding($text, 'html-entities', 'UTF-8'));}// 活动描述$y += 20;$line_split = 5;$goods_name_size = 18;$desc_width = $back_width - ($left * 2);// 换行处理if ($param['text']) {$text_array = draw_txt_to(array('fontsize' => $goods_name_size, 'width' => $desc_width, 'left' => 0), $param['text']);foreach ($text_array as $text) {$y += $goods_name_size + $line_split;imagefttext($t_logo2, $goods_name_size, 0, $left, $y, $textcolor3, $font, mb_convert_encoding($text, 'html-entities', 'UTF-8'));}}// 价格$goods_name_size = 28;$priceY = $back_height - $goods_name_size - 61 - 40;$text = '¥' . $param['price'];imagefttext($t_logo2, $goods_name_size, 0, $left, $priceY, $textRed, $font, mb_convert_encoding($text, 'html-entities', 'UTF-8'));// 二维码$logo_size = 200;$logo_x = 314;$logo_y = $back_height - $logo_size - 15;$logo = imagecreatefromstring(file_get_contents($param['mini_logo_img']));$source_info = getimagesize($param['mini_logo_img']);imagecopyresampled($t_logo2, $logo, $logo_x, $logo_y, 0, 0, $logo_size, $logo_size, $source_info[0], $source_info[1]);/*$text = '长按识别小程序 跟团购买';$goods_name_size = 10;$left_top = $y + ($logo_size - $goods_name_size * 2);imagefttext($t_logo2, $goods_name_size, 0, $left, $left_top, $textcolor2, $font, mb_convert_encoding($text, 'html-entities', 'UTF-8'));*/// 长按识别小程序 跟团购买$text_x = 274;$text_y = 46;$left_top = $back_height - $text_y - 57;$mini_bg = imagecreatefromstring(file_get_contents($param['mini_bg']));$source_info = getimagesize($param['mini_bg']);imagecopyresampled($t_logo2, $mini_bg, $left, $left_top, 0, 0, $text_x, $text_y, $source_info[0], $source_info[1]);imagepng($t_logo2, $refer_qrcode_logo);}return $refer_qrcode_logo;
}/*** 分行处理* @param $pos* @param $string* @param $line* @return array*/
function draw_txt_to($pos, $string, $line = 2)
{$font = getFont();$_string = '';$__string = array();for ($i = 0; $i < mb_strlen($string, 'utf-8'); $i++) {$box = imagettfbbox($pos['fontsize'], 0, $font, $_string);$_string_length = $box[2] - $box[0];$box = imagettfbbox($pos['fontsize'], 0, $font, mb_substr($string, $i, 1, 'utf-8'));if ($_string_length + $box[2] - $box[0] < ($pos['width'] - $pos['left'])) {$_string .= mb_substr($string, $i, 1, 'utf-8');} else {if (count($__string) >= ($line - 1)) {$_string = mb_substr($_string, 0, mb_strlen($_string, 'utf-8') - 1, 'utf-8') . '...';break;}$pos['left'] = 0;$__string[] = $_string;$_string = mb_substr($string, $i, 1, 'utf-8');}}$__string[] = $_string;return $__string;
}

调用

activity_poster();

海报截图

总结

使用GD库函数,首先创建画布,然后根据画布大小定位加载其他内容。

不同效果可参考上方代码来调整实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/480324.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探索Python词云库WordCloud的奥秘

文章目录 探索Python词云库WordCloud的奥秘1. 背景介绍&#xff1a;为何选择WordCloud&#xff1f;2. WordCloud库简介3. 安装WordCloud库4. 简单函数使用方法5. 应用场景示例6. 常见Bug及解决方案7. 总结 探索Python词云库WordCloud的奥秘 1. 背景介绍&#xff1a;为何选择Wo…

git 学习笔记

目录 一、git 前期配置准备 1、托管平台的账号注册&#xff08;以gitee码云为demo&#xff09; 2、本地个人电脑配置 &#xff08;1&#xff09;配置用户属性 ​编辑 &#xff08;2&#xff09;配置SSH密钥 二、git 工作流程图 三、git 提交命令 &#xff08;1&#x…

uniapp中使用uni-forms实现表单管理,验证表单

前言 uni-forms 是一个用于表单管理的组件。它提供了一种简化和统一的方式来处理表单数据&#xff0c;包括表单验证、字段绑定和提交逻辑等。使用 uni-forms可以方便地创建各种类型的表单&#xff0c;支持数据双向绑定&#xff0c;可以与其他组件及API进行良好的集成。开发者可…

_C#_串口助手_字符串拼接缺失问题(未知原理)

最近使用WPF开发串口助手时&#xff0c;遇到一个很奇怪的问题&#xff0c;无论是主线程、异步还是多线程&#xff0c;当串口接收速度达到0.016s一次以上&#xff0c;就会发生字符串缺失问题并且很卡。而0.016s就一切如常&#xff0c;仿佛0.015s与0.016s是天堑之隔。 同一份代码…

JVM(JAVA虚拟机)内存溢出导致内存不足,Java运行时环境无法继续

1、先贴出服务最后打印出来的日志&#xff0c;意思就是给虚拟机分配的内存被用完了&#xff0c;没有可用的内存了&#xff0c;服务运行不了了&#xff0c;被动停服了。详细的日志记录在了/home/user/zx/tomcat/apache-tomcat-8.5.82/bin/hs_err_pid147951.log文件里。 Java Ho…

OGRE 3D----3. OGRE绘制自定义模型

在使用OGRE进行开发时,绘制自定义模型是一个常见的需求。本文将介绍如何使用OGRE的ManualObject类来创建和绘制自定义模型。通过ManualObject,开发者可以直接定义顶点、法线、纹理坐标等,从而灵活地构建各种复杂的几何体。 Ogre::ManualObject 是 Ogre3D 引擎中的一个类,用…

Spring Boot英语知识网站:架构与开发

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

如何借助AI生成PPT,让创作轻松又高效

PPT是现代职场中不可或缺的表达工具&#xff0c;但同时也可能是令人抓狂的时间杀手。几页幻灯片的制作&#xff0c;常常需要花费数小时调整字体、配色与排版。AI的飞速发展为我们带来了革新——AI生成PPT的技术不仅让制作流程大大简化&#xff0c;还重新定义了效率与创意的关系…

Unity ShaderLab 实现网格爆炸

实现思路&#xff1a; 沿着3D物体每个面的法线&#xff0c;将面偏移一定的位置。 Shader Graph实现如下&#xff1a; Shader Lab 实现如下&#xff1a; Shader "Unlit/MeshExplode" {Properties{_MainTex ("Texture", 2D) "white" {}_Distan…

阅读《基于蒙特卡洛法的破片打击无人机易损性分析》_笔记

目录 基本信息 1 引言 1.1 主要研究内容 1.2 研究必要性&#xff08;为什么要研究&#xff09; 1.3 该领域研究现状&#xff08;别人做了什么/怎么做的&#xff09; 2 主要研究过程&#xff08;我们做了什么&#xff09; 2.1 建立目标仿真模型 2.2 确定毁伤依据 2.3 无…

如何让控件始终处于父容器的居中位置(父容器可任意改变大小)

1、改变父容器大小前 父容器是一个panel&#xff0c;控件是一个按钮button1 1&#xff09;刚开始让button1的左边距离panel的左边缘和button1的右边距离panel的右边缘两个距离相等&#xff1b; 2&#xff09;将button1的Anchor属性设置为None 2、改变父容器大小后 直接改变…

【线程】Java多线程代码案例(2)

【线程】Java多线程代码案例&#xff08;2&#xff09; 一、定时器的实现1.1Java标准库定时器1.2 定时器的实现 二、线程池的实现2.1 线程池2.2 Java标准库中的线程池2.3 线程池的实现 一、定时器的实现 1.1Java标准库定时器 import java.util.Timer; import java.util.Timer…

非递归遍历二叉树(数据结构)

我的博客主页 非递归遍历二叉树 前序遍历&#xff08;迭代&#xff09;中序遍历&#xff08;迭代&#xff09;后续遍历&#xff08;迭代&#xff09; 二叉树的遍历方式有&#xff1a;前序遍历、中序遍历、后续遍历&#xff0c;层序遍历&#xff0c;而树的大部分情况下都是通过递…

【CSS】一篇掌握CSS

不是因为有了希望才去坚持,而是坚持了才有了希望 目录 一.导入方式 1.行内样式 2.内部样式 3.外部样式(常用) 二.选择器 1.基本选择器(常用) 1.1标签选择器 1.2类选择器 1.3id选择器 2.层次选择器 2.1后代选择器 2.2子选择器 2.3相邻兄弟选择器 2.4通用兄弟选择器…

封装类与封装函数

目录结构 src/ ├── utils/ │ ├── test.js │ ├── Calculator.js ├── views/ │ ├── Home.vue ├── App.vue 共同点&#xff1a;模块导出与模块引入 封装函数 场景 简单、轻量级和性能敏感的场景&#xff0c;适合快速开发和维护。 优 可维护性&…

【论文阅读】Federated learning backdoor attack detection with persistence diagram

目的&#xff1a;检测联邦学习环境下&#xff0c;上传上来的模型是不是恶意的。 1、将一个模型转换为|L|个PD,&#xff08;其中|L|为层数&#xff09; 如何将每一层转换成一个PD&#xff1f; 为了评估第&#x1d457;层的激活值&#xff0c;我们需要&#x1d450;个输入来获…

5 Java字符串操作

字符串操作 1、String类1.1 声明字符串1.2 创建字符串 1.3 字符串连接 /连接字符串连接其他数据类型 1.4 提取字符串信息获取字符串长度length()获取指定位置的字符 charAt()获取子字符串索引位置 indexOf()判断字符串首尾内容 startsWith()/endsWith()获取字符数组 toCharArra…

IDEA报错: java: JPS incremental annotation processing is disabled 解决

起因 换了个电脑打开了之前某个老项目IDEA启动springcloud其中某个服务直接报错&#xff0c;信息如下 java: JPS incremental annotation processing is disabled. Compilation results on partial recompilation may be inaccurate. Use build process “jps.track.ap.depen…

Mybatis-基础操作

Mybatis的基础操作就是通过Mybatis完成对数据的增删改查。我们通过例子来引入这些操作&#xff0c;之前的项目较久远&#xff0c;因此我们从零开始进行准备工作&#xff1a; 搭建项目 一、创建数据库user_list并插入数据&#xff1a; -- 创建数据库 create table user_list …

火山引擎VeDI在AI+BI领域的演进与实践

随着数字化时代的到来&#xff0c;企业对于数据分析与智能决策的需求日益增强。作为新一代企业级数据智能平台&#xff0c;火山引擎数智平台VeDI基于字节跳动多年的“数据驱动”实践经验&#xff0c;也正逐步在AI&#xff08;人工智能&#xff09;与BI&#xff08;商业智能&…