React(2): 使用 html2canvas 生成图片

使用 html2canvas 生成图片

需求

  1. 将所需的内容生成图片
  2. div 中包括 svg

前置准备

js 复制代码
 "react": "^18.2.0",
 "react-dom": "^18.2.0",
 "html2canvas": "^1.4.1",

实现

html 复制代码
<div ref={payRef}></div>
js 复制代码
const payRef = useRef<HTMLDivElement>(null);

function generateImg() {
    if (orderRef.current) {
      html2canvas(orderRef.current, {
        useCORS: true,
        allowTaint: true, //开启跨域
      }).then((canvas) => {
        Toast.show('生成图片成功');
        const link = document.createElement('a');
        link.href = canvas.toDataURL();
        link.setAttribute('download', '订单详情.png');
        link.style.display = 'none';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      });
    }
}

生成的图片

出现的问题

svg 导不出来

百度了下发现都是用 canvg,但是发现不生效,查看了下 结构, 发现我用的是 vite-plugin-svg-icons 这个 vite 插件,你会发现 svg 里面的东西引用都在外面...

结构是这样的

不在同个 div 下面根本拿不到,然后我脑里突然想: 那我把它怼进去不就行了

更改

这里用 any 纯属无奈 ╮(╯▽╰)╭,因为 USEElementSymbolElement 定义就报错...,有大佬可以给我支下招

js 复制代码
export function changeToCanvas(element: HTMLDivElement) {
  const svgElems = element.querySelectorAll('svg');
  let elems: SVGElement[] = [...svgElems];
  elems.forEach((node: SVGElement) => {
    // 拿到 symbol 的 use 属性
    const childNodes: any = node.childNodes[0];
    // 除去 # 这个属性 拿到对应值
    const id = childNodes.href.baseVal.slice(1);
    // 拿到 Symbol 标签
    let symbol: any = document.getElementById(id)?.cloneNode(true);
    // 获取填充颜色
    let fill = window.getComputedStyle(node)['fill'];
    // 填充颜色
    symbol.style.fill = fill;
    // 直接把他塞到 use 中
    childNodes.appendChild(symbol);
  });
}

使用

html 复制代码
<div ref={payRef}></div>
js 复制代码
const payRef = useRef<HTMLDivElement>(null);
  function generateImg() {
    if (orderRef.current) {
      changeToCanvas(orderRef.current);
      html2canvas(orderRef.current, {
        useCORS: true,
        allowTaint: true, //开启跨域
      }).then((canvas) => {
        Toast.show('生成图片成功');
        const link = document.createElement('a');
        link.href = canvas.toDataURL();
        link.setAttribute('download', '订单详情.png');
        link.style.display = 'none';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      });
    }
  }

然后点击生成,打开控制台发现 use 中的内容给我硬塞进去了

然后生成的图片也没有问题

最后

如果大佬们有更好的建议可以私信我一下 ()

更新

暂无

相关推荐
阿猫的故乡39 分钟前
Vue过渡动画从入门到装X:淡入淡出、滑动、列表动画、第三方库全搞定
前端·javascript·vue.js
IManiy1 小时前
总结之Vibe Coding前端骨架
前端
JS菌1 小时前
AI Agent 沙箱双层防护体系:从权限过滤到内核隔离的完整实现
前端·人工智能·后端
Aphasia3111 小时前
从输入URL到页面展示全流程
前端·面试
我叫黑大帅2 小时前
前端如何竖屏固定视口背景
前端·javascript·面试
abcy0712132 小时前
python pandas csv异步后台清洗前端优先返回成功信息
前端·python·pandas
IT_陈寒2 小时前
Vite这个坑我帮你踩了,动态导入居然这样才生效
前端·人工智能·后端
swipe2 小时前
Mem0 x Agent 实战系列:分层记忆 + 三路召回,搭建真正可用的长期记忆层
前端·javascript·面试
鹤鸣的日常2 小时前
前端运行时动态环境变量方案
前端·react.js·docker·前端框架·vue·gitlab
Lee川2 小时前
Event Loop 面试通关:从原理到口述再到实战
前端·面试