html-to-image的使用及图片变形和无图问题修复

news2025/3/16 13:55:48

html-to-image的使用及图片变形和无图问题修复

最近迭代的时候因为新增了一个需求,需要前端提供素材及样式给后端,后端同步渲染,但是因为部分样式问题后端无法实现所以决定前端将页面生成图片然后传递给后端使用,本文记录一下使用的过程及遇到的部分问题。

技术调研

现在将页面元素转换成图片的插件有很多,普遍使用的技术原理都是利用canvas或者SVG将页面元素转换成画布或者svg元素,然后再转成图片。这里我在考虑到速度、易用性、稳定性后选择使用html-to-imag,文档地址在这里🚩,本文使用html-to-image版本1.11.11

使用

html-to-image的使用非常方便,内置了很多方法供我们使用:

import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';

这里根据具体需求选择不同的使用方式就好了,最开始我是用的toPng方法,使用的时候遇到了一些问题,不过已经是五个月前的事儿了所以这里就跳过,我使用的是toBlob方法,个人也推荐使用toBlob方法。

import { toBlob } from 'html-to-image'

toBlob(node,config)
  .then((blob)=> {
  ...
  });

基础的使用如上所示,其中第二个参数是生成图片的一些配置,用于一些定制化的需求。

  1. canvasWidthcanvasHeight
    • 作用:设置生成的 canvas 元素的宽度和高度。
    • 默认值:根据 HTML 元素的尺寸自动计算。
  2. style
    • 作用:添加额外的 CSS 样式到生成的 canvas 上。
    • 默认值:无。
  3. pixelRatio
    • 作用:设置生成图像的像素密度。值越大,图像质量越高,但文件大小也越大。
    • 默认值window.devicePixelRatio
  4. cacheBust
    • 作用:添加一个唯一的查询参数到图像 URL 中,以避免缓存问题。
    • 默认值true
  5. quality
    • 作用:设置生成图像的质量(仅适用于 JPEG 格式)。
    • 默认值1.0(最高质量)。
  6. imagePlaceholder
    • 作用:设置图像加载失败时的占位符图像 URL。
    • 默认值undefined
  7. skipFonts
    • 作用:跳过字体加载,加快生成速度。
    • 默认值false
  8. fontEmbedCSS
    • 作用:自定义字体嵌入的 CSS 样式。
    • 默认值undefined
  9. filter
    • 作用:一个函数,用于过滤不需要转换的节点或额外处理。
    • 默认值undefined
  10. backgroundColor
    • 作用:设置生成图像的背景颜色。
    • 默认值undefined
  11. widthheight
    • 作用:设置生成图像的宽度和高度。
    • 默认值:根据 HTML 元素的尺寸自动计算。
  12. type
    • 作用:设置生成图片的类型。
    • 默认值image/png

上面是部分配置项,更多的配置项和使用方法可以移步文档。

问题记录

基础的使用方法说完了,下面说说使用过程中遇到的问题

transform导致的元素偏移

在使用过程中我发现部分生成的图片没有元素,起初我以为是元素中图片的问题,后来发现部分元素的偏移使用的是定位部分使用的是transform,定位的top、left等值是可以正常捕捉到元素的,但是当使用transform的时候,因为偏移是相对自身的,所以会导致元素可能超出了生成的图片范围,这里我使用的方法是转图片的时候手动清除transform,转换完毕后再设置回去。

const transformList = []
const nodeTransform = node.style.transform
const rotateRegex = /rotate\([-.\d]+deg\)/
const match = nodeTransform.match(rotateRegex)
const isRotate = match && match[0] !== 'rotate(0deg)'
if (nodeTransform) {
   node.style.transform = '' // 这里应该保留rotate,因为我这里不需要处理所以直接清除,rotate只作匹配展示
}
toBlob(node).then((res) => {
  ...
}).finally(() => {
   requestAnimationFrame(() => {
     node.style.transform = transformList[index] // 我这里使用了nodeList遍历所以用到了index,具体使用看个人实际情况
   })
})
背景图渲染导致生成的图片变形

我们的页面中有部分元素是采用背景图然后设置background的方式实现的

background: url(...) 0% 0% / 100% 100% no-repeat;

当时排查到是背景图元素会导致生成图片变形后我尝试了使用其他背景参数去设置,无论是设置background-size还是background-position的其他值生成的图片都是被拉伸的。所以这里我采用第二种方案,转图片前将背景图转成图片元素然后再恢复。

// 在调用toBolb方法前添加下面代码
let backgroundImage = node.style.backgroundImage
let isBgRenderEle =
    backgroundImage !== '' && backgroundImage !== 'url("")'
if (isBgRenderEle) {
  const imgUrl = backgroundImage
  .replace(/^url\(["']?/, '')
  .replace(/["']?\)$/, '')
  const imgNode = document.createElement('img')
  imgNode.src = imgUrl
  imgNode.style.width = '100%'
  imgNode.style.height = '100%'
  node.style.backgroundImage = ''
  node.appendChild(imgNode)
}

// 转成图片后添加下面代码
 if (isBgRenderEle) {
   node.innerHTML = ''
   node.style.backgroundImage = backgroundImage
   backgroundImage = ''
   isBgRenderEle = false
 }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【eNSP基础使用教程-1】

座右铭: 纵有疾风起,人生不言弃。 文章目录 前言一、更改设备名称指令1、双击路由器进入2、 进入系统视图3、更改设备名称为R14、使用同样的办法修改路由器R2、R3 二、配置路由物理接口的IP 地址1、查看R1路由器当前接口IP 地址配置与路由表2、查看路由器上的路由表…

机器学习常见激活函数

激活函数的作用 引入非线性因素 若神经网络仅由线性层构成,那么无论网络的层数有多少,其整体的输出依然是输入的线性组合。这样的网络只能拟合线性函数,在处理复杂的非线性问题(如语音识别、图像分类)时能力十分有限。…

netcore publish报错 error CS1056: Unexpected character

问题:jenkins netcore publish报错 检查文件编码,发现是:GB2312。转换为:UTF-8-BOM。 问题解决 。

网页制作14-Javascipt时间特效の显示动态日期

<!doctype html> <html> <head> <meta charset"utf-8"> <title>动态日期</title> </head><script>var today new Date();//获取时间var ytoday.getFullYear();//截取年var mtoday.getMonth();//截取月份,返回0~11v…

《高效迁移学习:Keras与EfficientNet花卉分类项目全解析》

从零到精通的迁移学习实战指南&#xff1a;以Keras和EfficientNet为例 一、为什么我们需要迁移学习&#xff1f; 1.1 人类的学习智慧 想象一下&#xff1a;如果一个已经会弹钢琴的人学习吉他&#xff0c;会比完全不懂音乐的人快得多。因为TA已经掌握了乐理知识、节奏感和手指…

【单片机】嵌入式系统的硬件与软件特性

嵌入式系统的软件结构 嵌入式系统的软件结构一般分为 不带操作系统&#xff08;Bare Metal&#xff09; 和 带操作系统&#xff08;RTOS / Linux&#xff09; 两种。不同的软件架构适用于不同的应用场景&#xff0c;如 简单控制系统、实时控制系统、物联网、工业自动化等。 嵌…

5G核心网实训室搭建方案:轻量化部署与虚拟化实践

5G核心网实训室 随着5G技术的广泛应用&#xff0c;行业对于5G核心网人才的需求日益增长。高校、科研机构和企业纷纷建立5G实训室&#xff0c;以促进人才培养、技术创新和行业应用研究。IPLOOK凭借其在5G核心网领域的深厚积累&#xff0c;提供了一套高效、灵活的5G实训室搭建方…

蓝耘MaaS平台:阿里QWQ应用拓展与调参实践

摘要&#xff1a;本文深入探讨了蓝耘MaaS平台与阿里QWQ模型的结合&#xff0c;从平台架构、模型特点到应用拓展和调参实践进行了全面分析。蓝耘平台凭借其强大的算力支持、弹性资源调度和全栈服务&#xff0c;为QWQ模型的高效部署提供了理想环境。通过细化语义描述、调整推理参…

在线 SQL 转 SQLAlchemy:一键生成 Python 数据模型

一款高效的在线 SQL 转 SQLAlchemy 工具&#xff0c;支持自动解析 SQL 语句并生成 Python SQLAlchemy 模型代码&#xff0c;适用于数据库管理、后端开发和 ORM 结构映射。无需手写 SQLAlchemy 模型&#xff0c;一键转换 SQL 结构&#xff0c;提升开发效率&#xff0c;简化数据库…

LLM本地化部署与管理实用工具实践记录

文章目录 前言OllamaQWen模型部署Python调用API AnythingLLM本地基础配置AI知识库检索 CherryStudio访问DeepSeek系统内置AI助手嵌入知识库文档 LLMStudio基础环境安装模型管理应用命令行的管理 总结 前言 发现好久没更新 CSDN 个人博客了&#xff0c;更多的是转移到了个人私有…

第十次CCF-CSP认证(含C++源码)

第十次CCF-CSP认证 分蛋糕满分题解 学生排队满分题解 Markdown语法题目解读满分代码 结语 分蛋糕 题目链接 满分题解 基本思路&#xff1a;我们需要保证除了最后一个小朋友之外的所有人&#xff0c;分得的蛋糕都大于等于给定的K值&#xff0c;为什么是大于等于&#xff0c;是…

windows 启用linux子系统不必再装双系统

搜索栏搜索:启用或关闭Windows功能,把下面3项勾选上: 若没有Hyper-V,则根据以下步骤添加: 在桌面新建一个txt文件,将下面的程序复制进去,之后修改文件后缀名为.bat 右键管理员运行即可。 pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.m…

lanqiaoOJ 1180:斐波那契数列 ← 矩阵快速幂

【题目来源】 https://www.lanqiao.cn/problems/1180/learning/ 【题目描述】 定义斐波那契数列数列为 F11&#xff0c;F21&#xff0c;FnFn-1Fn-2&#xff0c;n&#xff1e;2。 给定一个正整数 n&#xff0c;求 Fn 在模 10^97 的值。 【输入格式】 第1行为一个整数 T&#x…

go程序运行Spaitalite踩坑记录

Spatialite参考资料&#xff1a;8.1. 开源地理空间数据库 — Python与开源GIS Ubuntu安装SpaitaLite&#xff1a; apt-get install libspatialite7 libsqlite3-mod-spatialite apt-get install spatialite-bin 命令行打开数据库&#xff1a;spatialite xxx.db 执行一个空间函…

Everything搜索工具下载使用教程(附安装包),everything搜索工具文件快速查找

文章目录 前言一、Everything搜索工具下载二、Everything搜索工具下载使用教程 前言 Everything搜索工具能凭借文件名实时精准定位文件&#xff0c;接下来的教程&#xff0c;将详细为你呈现 Everything搜索工具的下载及使用方法&#xff0c;助你开启高效文件搜索的便捷之旅 。…

LeetCode 解题思路 17(Hot 100)

解题思路&#xff1a; 找到链表中点&#xff1a; 使用快慢指针法&#xff0c;快指针每次移动两步&#xff0c;慢指针每次移动一步。当快指针到达末尾时&#xff0c;慢指针指向中点。递归分割与排序&#xff1a; 将链表从中点处分割为左右两个子链表&#xff0c;分别对这两个子…

Qt程序基于共享内存读写CodeSys的变量

文章目录 1.背景2.结构体从CodeSys导出后导入到C2.1.将结构体从CodeSys中导出2.2.将结构体从m4文件提取翻译成c格式 3.添加RTTR注册信息4.读取PLC变量值5.更改PLC变量值 1.背景 在文章【基于RTTR在C中实现结构体数据的多层级动态读写】中&#xff0c;我们实现了通过字符串读写…

7-12 关于堆的判断

输入样例&#xff1a; 5 4 46 23 26 24 10 24 is the root 26 and 23 are siblings 46 is the parent of 23 23 is a child of 10输出样例&#xff1a; F T F T 这题是建最小堆&#xff0c;数据结构牛老师讲过这个知识点&#xff0c;但是我给忘了&#xff0c;补题搜了一下才解…

STM32 HAL库实战:高效整合DMA与ADC开发指南

STM32 HAL库实战&#xff1a;高效整合DMA与ADC开发指南 一、DMA与ADC基础介绍 1. DMA&#xff1a;解放CPU的“数据搬运工” DMA&#xff08;Direct Memory Access&#xff09; 是STM32中用于在外设与内存之间直接传输数据的硬件模块。其核心优势在于无需CPU干预&#xff0c;…

正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-4 uboot目录分析

前言&#xff1a; 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用&#xff1a; …