• 记一次react-hooks项目获取图表图片集合并生成pdf的需求


    需求: 获取子组件中所有图片的dom元素并生成图片,再把生成的图片转化为pdf下载

    • 难点

      1. 众所周知,react是单向数据流,倡导f(data)⇒ UI的哲学, 并不建议过多直接操作dom,但是生成图片的base64格式时使用的ant design charts 要求必须获取ref才可以

      2. 逻辑流转如下图, 兄弟组件b发出按钮click事件后告知a组件去收集自身组件内图标的ref,由于是兄弟组件通信,此处借助了react-redux

      3. a组件获取所有图标ref

        const myRef = useRef()
        
        //每个组件类似于此:
        <BoxPlot ref={handleRefCallback}/>
        
        const handleRefCallback = React.useCallback((dom) => {
              handleRefs(dom)
        }, [])   //此处通过回调来获取ref
        				// 之前,每个charts子组件通过memo浅比较,但是使用了ref之后,memo不再生效,所有此处要通过useCallback来缓存回调函数来实现memo的效果
        // charts子组件: 
        const child = React.forwardRef((props,ref) =>{
        		<Box {...config} chartRef={ref} />
        })
        
      4. a通过react-redux获得b组件点击指令后,开始按照3步骤收集dom到ref的current中,存在storage中,由于生成base64的过程是异步的,所以在PageB中无法获取实时的storage. 所以需要在PageB中通过状态锁让页面在跳转的过程中只刷新一次

        兄弟组件b点击时同时生成一个同步的sessionStorage的标记作为在PageB中执行状态锁的依据
        
      5. 生成pdf的代码: html2canvas 和 jspdf
        1.

      import html2canvas from 'html2canvas'
      import {jsPDF} from 'jspdf'
      
      const printDocument = async () => {
              await html2canvas(pdfRef.current, {
                  allowTaint: true,
                  scrollY: 0,
                  scrollX: 0,
                  useCORS: true,
                  width: 1040,
                  height: pdfRef.current.offsetHeight,
              }).then(function (canvas) {
                  var contentWidth = 900
                  var contentHeight = 5060
                  var pageHeight = (contentWidth / 592.28) * 841.89
                  var leftHeight = contentHeight
                  var position = 0
                  var imgWidth = 595.28
                  var imgHeight = 3400
                  var pageData = canvas.toDataURL('image/jpeg', 1.0)
                  var pdf = new jsPDF('', 'pt', 'a4')
                  if (leftHeight < pageHeight) {
                      pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
                  } else {
                      while (leftHeight > 0) {
                          pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
                          leftHeight -= pageHeight
                          position -= 841.89
                          if (leftHeight > 0) {
                              pdf.addPage()
                          }
                      }
                  }
                  window.open(pdf.output('bloburl', {filename: 'new_file.pdf'}), '_blank')
              })
          }
      
      
      折叠
      2. 
      
      import html2canvas from 'html2canvas'
      import {jsPDF} from 'jspdf'
      
      const printDocument = async () => {
               await html2canvas(pdfRef.current, {scrollY: -window.scrollY, scale: 1}).then((canvas) => {
                   const contentDataURL = canvas.toDataURL('image/png', 1.0)
                   let pdf = new jsPDF('l', 'mm', 'a4')
                   let imgWidth = 300
                   let pageHeight = pdf.internal.pageSize.height
                   let imgHeight = (canvas.height * imgWidth) / canvas.width
                   let heightLeft = imgHeight
                   let position = 0
      
                   pdf.addImage(contentDataURL, 'PNG', 0, position, imgWidth, imgHeight)
                   heightLeft -= pageHeight
      
                   while (heightLeft >= 0) {
                       position = heightLeft - imgHeight
                       pdf.addPage()
                       pdf.addImage(contentDataURL, 'PNG', 0, position, imgWidth, imgHeight)
                       heightLeft -= pageHeight
                   }
                //直接保存   // pdf.save('download.pdf') 
                //在线预览  // window.open(pdf.output('bloburl', {filename: 'new_file.pdf'}), '_blank')
               })
      
          }
      
      
      折叠
  • 相关阅读:
    Ubuntu搭建FTP服务
    17、监测数据采集物联网应用开发步骤(12.2)
    宝塔自建bitwarden密码管理器
    【分布式压测】遇到的坑以及解决的办法,亲测可行
    XV6操作系统调试
    4.0 SDK Workshop 纪实:一起体验多人、多屏幕共享新功能
    UKP3d的excel汇总表
    mt4量化交易接口:分享日常量化选股方法
    华为数通方向HCIP-DataCom H12-831题库(单选题:241-260)
    Vue源码阅读:createApp的过程(三)
  • 原文地址:https://www.cnblogs.com/web-zs/p/16485219.html