TP8 JS(html2canvas) 把DIV内容生成二维码并与背景图、文字组合生成分享海报

方法一:前端JS生成(推荐)

注意:

1.这个网页只能截图图片效果代码,其它任何html效果都不能有,不然截图就不准确

2.如果要生成的图片DIV内容中引用了第三个方的图片,就是不使用同一个域名下的图片,需要把后端把图片转为Base64才可以生成截图、不然会造成跨域的问题,生成的图片会是空白的

图片转为Base64后的显示方式:

<img src="data:image/jpeg;base64,{$PosterParameters['imgp_Base64']}" />

例子:

      <div class="container" id="capture-target">
        <div class="img">
          {notempty name="$PosterParameters['img_Base64']"}
          <img src="data:image/jpeg;base64,{$PosterParameters['img_Base64']}" />
          {/notempty}
        </div>
        <div class="username">
          <p>{notempty name="$PosterParameters['name']"}{$PosterParameters['name']}{/notempty}</p>
        </div>
        <div class="invite_text">
          <p>{notempty name="$PosterParameters['invite_text']"}{$PosterParameters['invite_text']}{/notempty}</p>
        </div>
        <div class="live_time_day">
          <p>{notempty name="$PosterParameters['day']"}{$PosterParameters['day']}{/notempty}</p>
        </div>
        <div class="live_time">
          <p>{notempty name="$PosterParameters['hi']"}{$PosterParameters['hi']}{/notempty}</p>
        </div>
        <div class="imgp">
          {notempty name="$PosterParameters['imgp_Base64']"}
          <img src="data:image/jpeg;base64,{$PosterParameters['imgp_Base64']}" />
          {else /}
          {notempty name="$PosterParameters['imgp']"}
          <img src="{$PosterParameters['imgp']}" />
          {/notempty}
          {/notempty}
        </div>
        <div class="title">
          <p id="myDiv">{notempty name="$PosterParameters['title']"}{$PosterParameters['title']}{/notempty}</p>
        </div>
        <div class="qr-code">
          <img src="{notempty name="$PosterParameters['QRcodeUrl']"}{$PosterParameters['QRcodeUrl']}{/notempty}" width="160px" height="160px" />
        </div>
      </div>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>网页内容转图片示例</title>
    <!-- 引入html2canvas库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
</head>
<body>

<!-- 截图内容 -->
<div id="capture-target">
    <h1>欢迎来到我的网站</h1>
    <p>这是一个用于演示如何将网页内容转换成图片的例子。</p>
</div>

<!-- 按钮触发截图 -->
<button onclick="captureAndSave()">点击截图保存</button>


<script>
        // 图片下载函数,增强对不同浏览器的支持
        function downloadImage(dataURL, filename) {
            const link = document.createElement('a');
            link.href = dataURL;
            link.download = filename;
            document.body.appendChild(link); // 确保元素添加到DOM中以触发点击事件
            link.click();
            document.body.removeChild(link); // 下载后移除元素
        }

        // 增强的截图并保存的函数,优化参数处理与错误提示
        async function captureAndSave() {
            try {
                const targetElement = document.querySelector('#capture-target');
                const dpiScale = window.devicePixelRatio || 1;
                const qualityFactor = 0.9; // 默认质量因子,可以根据需要调整
                const format = 'image/png'; // 图片输出格式,可根据需要更改为 'image/png' 等
                const scale = dpiScale >= 2 ? dpiScale : 2; // 动态调整缩放比例,优先考虑DPR,至少为2以保证清晰度

                const canvas = await html2canvas(targetElement, {
                    scale,
                    dpi: 300,
                    logging: false,
                    useCORS: true,
                    allowTaint: true,
                });

                // 根据图片格式动态调整dataURL的mime类型
                const mimeType = format === 'image/jpeg' ? 'image/jpeg' : 'image/png';
                const imageDataURL = canvas.toDataURL(mimeType, qualityFactor);

                // 动态检测浏览器对MIME类型的兼容性,必要时转换为Blob下载
                if (navigator.msSaveBlob) { // IE/Edge 特殊处理
                    const blob = await (await fetch(imageDataURL)).blob();
                    navigator.msSaveBlob(blob, 'screenshot.' + (format === 'image/jpeg' ? 'jpg' : 'png'));
                } else {
                    downloadImage(imageDataURL.replace(mimeType, 'image/octet-stream'), 'screenshot.' + (format === 'image/jpeg' ? 'jpg' : 'png'));
                }
            } catch (error) {
                //alert('截图保存时发生错误,请检查浏览器控制台详情。'); // 提供用户友好提示
                console.error('截图时发生错误:', error);
            }
        }
</script>

方法二:后端生成(没有测试)

	/**
	* @name 生成海报
	* @author 峰神
	* @date 2024-06-28
	* @param array $postData 必填 提交数组
	* @param  int [必填/选填] type 生成类型 默认0=伪直播邀请海报
	* @ruturn array
	*/
	public function CreatePoster(array $postData=[],int $type=0){
		$tmp_bg_image = 'static/images/live_share.png';//背景图路径

        //获取二维码,调用了上边那个方法
        $qrcode_img = 'static/images/portrait.png';
        // $qr_res = $this->extendQrcode();
        // if($qr_res['status']){
        //     $qrcode_img = $qr_res['data'];
        // }

        //新文件名
        $share_path = 'upload/share/';
        is_dir($share_path) OR mkdir($share_path, 0777, true);
        $share_img = $share_path.'1.jpg';
		
        $this->composite_picture($tmp_bg_image, $qrcode_img, $share_img, false, '', '', false, '', 150, 510); 
        //模板背景, 二维码, 海报, 二维码是否缩小, 二维码缩小的宽度,二维码缩小的高度,是否等比例缩放, 文字, 二维码在x轴的位置, 二维码在y轴的位置

       
        $result = ['status'=>true, 'data'=>$share_img];
        return json_encode($result, 320);
	}

	/*
	* 合并图片
	* @ $bg_img 背景图片
	* @ $qrcode_img 二维码图片
	* @ $new_filename 新文件名
	* @ $is_suoxiao 组合的图片是否缩小
	* @ $n_w 缩小的宽
	* @ $n_h 缩小的高
	* @ $is_per 是否按比例缩小
	* @ $text 文字
	* @ $s_width 要组合的图片在x轴的位置
	* @ $s_height 要组合的图片在y轴的位置
	*/
	public function composite_picture($bg_img, $qrcode_img, $new_filename, $is_suoxiao, $n_w='', $n_h='', $is_per=false, $text='', $s_width='0', $s_height='0'){
		
		if($is_suoxiao){
			$src_im = $this->imgsuoxiao($qrcode_img, $n_w, $n_h, $is_per);
		}else{
			$src_im = $qrcode_img;
		}
		
		$bgimg = imagecreatefromstring(file_get_contents($bg_img));//背景图
		$src = imagecreatefromstring(file_get_contents($src_im));//组合图
		list($src_w, $src_h) = getimagesize($src_im);

		imagecopy($bgimg, $src, $s_width, $s_height, 0, 0, $src_w, $src_h);

		list($bgimg_w, $bgimg_h, $bgimg_type) = getimagesize($bg_img);

		switch ($bgimg_type) {
			case 1://GIF
				header('Content-Type: image/gif');
				header('Content-Disposition: inline; filename="image.gif"');
				$result = imagegif($bgimg, $new_filename);
				break;
			case 2://JPG
				header('Content-Type: image/jpeg');
				header('Content-Disposition: inline; filename="image.jpg"');
				imagejpeg($bgimg, $new_filename);
				break;
			case 3://PNG
				header('Content-Type: image/png');
				header('Content-Disposition: inline; filename="image.png"');
				imagepng($bgimg, $new_filename);
				break;
			default:
				break;
		}
		imagedestroy($bgimg);
		imagedestroy($src);
		if($text){
			$newss = $this->numimage($text,$new_filename,15,3,230,720);
			return $newss;
		}else{
			return $new_filename;
		}
		
		return $new_filename;
		// exit;
	}

	//缩小图片
	public function imgsuoxiao($filename, $n_w, $n_h, $is_per=false){
		list($width, $height, $dst_type)=getimagesize($filename);
		if($is_per){
			$per=0.3;
			$n_w=$width*$per;
			$n_h=$height*$per;
		}
		switch ($dst_type) {
			case 2://JPG
				$img=imagecreatefromjpeg($filename);
				break;
			case 3://PNG
				$img = imagecreatefrompng($filename);
				break;
			default:
				break;
		}
		$new=imagecreatetruecolor($n_w, $n_h);
		//copy部分图像并调整
		imagecopyresized($new, $img,0, 0,0, 0,$n_w, $n_h, $width, $height);
		//图像输出新图片、另存为
		imagejpeg($new, $filename);
		imagedestroy($new);
		imagedestroy($img);
		return $filename;
	}


	/**
	* 像图片中添加文字
	* @param $txt 文本文字
	* @param $image 图片路径
	* @param $size  文字大小
	* @param $scale 文字旋转度
	* @param $x 在x轴上的位置
	* @param $y 在y轴上的位置
	* @param $color 字体颜色
	*/
	public function numimage($txt,$image,$size,$scale,$x,$y, $color="黑色")
	{
		list($dst_w, $dst_h, $dst_type) = getimagesize($image);
		switch ($dst_type) {
			case 2://JPG
				$im = imagecreatefromjpeg($image);
				break;
			case 3://PNG
				$im = imagecreatefrompng($image);
				break;
			default:
				break;
		}
		$textcolor = imagecolorallocate($im, 0, 0, 0);
		if($color=="白色"){
			$textcolor = imagecolorallocate($im, 255, 255, 255);
		}
		$qr_size = imagesx($im);
		$font = realpath('static/STSONG.TTF'); //引入字体
		imagettftext($im, $size,0,$x,$y, $textcolor, $font, $txt);
		$myImage = ImageCreate(245,245); //参数为宽度和高度
		imagecopyresampled($myImage, $im, 0, 0, 0, 0, 0, 80, 10, 10); //重新组合图片并调整大小
		header("Content-type: image/jpeg");
		imagejpeg($im, $image);
		imagedestroy($im);
		return $image;
	}

Thinkphp5 生成二维码并与背景图、文字组合生成分享海报_tp5+phpqrcode二维码下方带文字-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习】循环神经网络RNN、LSTM、GRU

李宏毅深度学习笔记 https://www.bilibili.com/video/BV1qM4y1M7Nv RNN 在 RNN 里面&#xff0c;每一次隐藏层的神经元产生输出的时候&#xff0c;该输出会被存到记忆元。下一次有输入时&#xff0c;这些神经元不仅会考虑输入 x1, x2&#xff0c;还会考虑存到记忆元里的值。 …

高危行业的安全守护者,顶坚防爆手机无惧挑战

高危行业的安全守护者&#xff0c;防爆手机以卓越性能&#xff0c;无惧极端挑战&#xff0c;为每一位前线工作者筑起坚不可摧的安全防线。石油勘探的深邃海洋、化工生产的复杂车间、矿山的幽深隧道……这些高危行业中&#xff0c;每一步都需谨慎前行&#xff0c;每一刻都需安全…

技术成神之路:设计模式(二)建造者模式

1.定义 建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它允许你分步骤创建复杂对象&#xff0c;而不必直接调用构造函数。建造者模式特别适合那些包含多个组成部分并且构造过程复杂的对象。 2. 结构 建造者模式的主要组成部分包括&#…

TensorRT动态形状(Dynamic Shape)出错,官方demo+自己模型运行时出错

(2024.7.2) 使用TensorRT处理动态输入形状推理时出现的错误&#xff0c;本案基于官方demo文件&#xff0c;已解决&#xff1a; TensorRT版本10.0&#xff0c;官方例子使用的是这个https://github.com/NVIDIA/trt-samples-for-hackathon-cn/blob/master/cookbook/01-SimpleDem…

数据文件传输连接超时?镭速教你如何解决!

Mysql作为一个广泛使用的开源关系型数据库管理系统&#xff0c;以快速、可靠、易于使用、开源的特色闻名&#xff0c;使用 MySQL 来存储和管理数据&#xff0c;已经广泛应用于各个领域、各类大小型应用中。 图片源于网络 使用 MySQL 来存储和管理数据的应用中&#xff0c;与数…

Windows打开redis以及Springboot整合redis

目录 前言Windows系统打开redisSpringboot整合redis依赖实体类yml配置文件config配置各个数据存储类型分别说明记录string数据写入redis&#xff0c;并查询通过命令行查询 list插入数据到redis中从redis中读取命令读取数据 hash向redis中逐个添加map键值对获取key对应的map中所…

【ubuntu18.04】 局域网唤醒 wakeonlan

ai服务器经常因为断电,无法重启,当然可以设置bios 来电启动。 这里使用局域网唤醒配置。 自动开关机设置 工具:ethtool 端口 : enp4s0 Wake-on: d 表示禁用Wake-on: g 激活 ,例如:ethtool -s eth0 wol g 配置/etc/rc.local ,这个文件不存在,自己创建工具下载 tengxun W…

mysql 命令 —— 查看表信息(show table status)

查询表信息&#xff0c;如整个表的数据量大小、表的索引占用空间大小等 1、查询某个库下面的所有表信息&#xff1a; SHOW TABLE STATUS FROM your_database_name;2、查询指定的表信息&#xff1a; SHOW TABLE STATUS LIKE your_table_name;如&#xff1a;Data_length 显示表…

开放式耳机哪个品牌最好?2024高热度机型推荐,选购不迷茫

选购开放式耳机时&#xff0c;面对琳琅满目的品牌与型号是否感到不知道怎么选择&#xff1f;别担心&#xff0c;作为耳机爱好者与资深评测人&#xff0c;我精心整理了几款热门开放式耳机的全面对比。这次对比不仅涵盖如何挑选&#xff0c;有哪些不要菜类的额点&#xff0c;还推…

第十四届蓝桥杯省赛C++B组E题【接龙数列】题解(AC)

需求分析 题目要求最少删掉多少个数后&#xff0c;使得数列变为接龙数列。 相当于题目要求求出数组中的最长接龙子序列。 题目分析 对于一个数能不能放到接龙数列中&#xff0c;只关系到这个数的第一位和最后一位&#xff0c;所以我们可以先对数组进行预处理&#xff0c;将…

数字化供应链:背景特点

​背景 1、外部环境 近年来&#xff0c;供应链脆弱性凸显&#xff0c;企业供应链压力难以缓解。 美国媒体针对美国零售联合会、美国服装和鞋类协会、美国供应链管理专业委员会等主体进行的一项供应链调查显示&#xff1a; 61%的供应链经理预计&#xff0c;供应链紊乱问题至少…

老师怎样将期末成绩怎样私发家长?

作为老师&#xff0c;期末成绩的发布不仅是对学生一学期学习成果的评价&#xff0c;更是家校沟通的重要环节。然而&#xff0c;这一过程往往比我们想象的更为复杂和繁琐。 我们需要确保每个学生的成绩准确无误。这意味着在成绩录入之后&#xff0c;必须进行多次核对&#xff0c…

Java将list数组中重复的对象进行去重

/*** 数组去重*/ public class ArrayDistinct {public static void main(String[] args) {ArrayList<Object> list new ArrayList<>();JSONObject jsonObject1 new JSONObject();jsonObject1.put("name","张三");jsonObject1.put("age&…

序号不足两位前面补0

预期目标 原始效果 代码实现 {${(index 1).toString().padStart(2, 0)}. ${item.sentence}}要实现自动编号并确保显示为两位数的格式&#xff0c;可以在 {index 1} 的地方进行格式化。在 JavaScript 中&#xff0c;可以使用 String.prototype.padStart() 方法来补足数字到指定…

终极指南:RNNS、Transformers 和 Diffusion 模型

一、说明 作为广泛使用这些工具和模型的人&#xff0c;我的目标是解开 RNN、Transformer 和 Diffusion 模型的复杂性和细微差别&#xff0c;为您提供详细的比较&#xff0c;为您的特定需求提供正确的选择。 无论您是在构建语言翻译系统、生成高保真图像&#xff0c;还是处理时间…

kettle从入门到精通 第七十四课 ETL之kettle kettle调用https接口教程,忽略SSL校验

场景&#xff1a;kettle调用https接口&#xff0c;跳过校验SSL。&#xff08;有些公司内部系统之间的https的接口是没有SSL校验这一说&#xff0c;无需使用用证书的&#xff09; 解决方案&#xff1a;自定义插件或者自定义jar包通过javascript调用https接口。 1、http post 步…

为什么是视频传输用YUV格式,而放弃RGB格式?

&#x1f60e; 作者介绍&#xff1a;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff0c;视频号&#xff1a;AI-行者Sun &#x1f388; 本文专栏&#xff1a;本文收录于《音视频》系列专栏&…

Linux系统之 — 线程

Linux系统之 — 线程 线程介绍线程使用死锁&#xff08;Deadlock&#xff09;竞态条件&#xff08;Race Condition&#xff09; 线程使用示例服务器端代码示例服务器端示例拆解1. 引入头文件和宏定义2. 定义全局变量3. 定义线程函数4. 主函数5. 错误处理和资源释放 客户端代码示…

Keil5 ST-LINK setting闪退问题解决

1. 官网下载新版驱动文件 MDK uVision crashes when using ST-Link debugger 2. 解压替换 STLinkUSBDriver6.1.2.0Signed 我的库文件目录&#xff1a; D:\Tool\Keil5\ARM\STLink

一文搞懂 java 线程池:ThreadPoolExecutor 和 FixedThreadPool 原理

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…