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 中的内容给我硬塞进去了

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

最后

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

更新

暂无

相关推荐
天天扭码7 小时前
如何实现流式输出?一篇文章手把手教你!
前端·aigc·ai编程
前端 贾公子8 小时前
vue移动端适配方案 === postcss-px-to-viewport
前端·javascript·html
GISer_Jing9 小时前
AI营销增长:4大核心能力+前端落地指南
前端·javascript·人工智能
明远湖之鱼9 小时前
一种基于 Service Worker 的渐进式渲染方案的基本原理
前端
前端小端长10 小时前
Vue 中 keep-alive 组件的原理与实践详解
前端·vue.js·spring
FeelTouch Labs10 小时前
Nginx核心架构设计
运维·前端·nginx
雪球工程师团队10 小时前
别再“苦力”写后台,Spec Coding “跑” 起来
前端·ai编程
m0_4711996310 小时前
【场景】前端怎么解决离线收银、数据同步异常等场景问题
前端·javascript
Curvatureflight10 小时前
前端性能优化实战:从3秒到300ms的加载速度提升
前端·人工智能·性能优化