这是借鉴了qq_251025116大佬的解决方案并优化升级完成的,原文链接
1.安装依赖
npm install jspdf html2canvas
2.使用方法
import htmlToPdffrom './index.js' const suc = ( ) => { message. success ( 'success' ) ; } ; let dom = document. querySelector ( '#testPdf' ) ; let pdf = new htmlToPdf ( dom, '测试' , 'splitPages' , ',' , suc, 2 ) ; pdf. outPutPdfFn ( '测试' ) ;
3.使用说明
< SpeciesIdentification class = "splitPages" : baseData= "baseData" / > < SpeciesIdentificationSecond class = "splitPages" : baseData= "baseData" / > < RepetPic class = "splitPages" : baseData= "baseData" / > < RepetTable class = "splitPages" : baseData= "baseData" / > < GeneralAnnotation class = "splitPages" : baseData= "baseData" / >
导出效果:
具体代码 :
import jsPDF from "jspdf" ;
import html2canvas from "html2canvas" ; class htmlToPdf { constructor ( ele, pdfFileName, splitClassName = "itemClass" , breakClassName = "break_page" , sucCallback = ( ) => { } , scale = 2 ) { this . ele = ele; this . pdfFileName = pdfFileName; this . splitClassName = splitClassName; this . breakClassName = breakClassName; this . sucCallback = sucCallback; this . scale = scale; this . A4_WIDTH = 595 ; this . A4_HEIGHT = 842 ; this . pageHeight = 0 this . pageNum = 1 } ; async getPDF ( resolve ) { let ele = this . ele; let pdfFileName = this . pdfFileNamelet eleW = ele. offsetWidth let eleH = ele. scrollHeight let eleOffsetTop = ele. offsetTop let eleOffsetLeft = ele. offsetLeft let canvas = document. createElement ( "canvas" ) let abs = 0 let win_in = document. documentElement. clientWidth || document. body. clientWidth let win_out = window. innerWidth if ( win_out > win_in) { abs = ( win_out - win_in) / 2 } canvas. width = eleW * 2 canvas. height = eleH * 2 let context = canvas. getContext ( "2d" ) context. scale ( this . scale, this . scale) context. translate ( - eleOffsetLeft - abs, - eleOffsetTop) html2canvas ( ele, { useCORS : true } ) . then ( async canvas => { let contentWidth = canvas. widthlet contentHeight = canvas. heightthis . pageHeight = ( contentWidth / this . A4_WIDTH ) * this . A4_HEIGHT let leftHeight = contentHeightlet position = 0 let imgWidth = this . A4_WIDTH - 10 let imgHeight = ( this . A4_WIDTH / contentWidth) * contentHeightlet pageData = canvas. toDataURL ( "image/jpeg" , 1.0 ) let pdf = jsPDF ( "" , "pt" , "a4" ) ; if ( leftHeight < this . pageHeight) { pdf. addImage ( pageData, 'JPEG' , 6 , 40 , imgWidth - 12 , imgHeight - 80 ) ; } else { while ( leftHeight > 0 ) { pdf. addImage ( pageData, "JPEG" , 6 , position + 40 , imgWidth - 12 , imgHeight - 80 ) leftHeight -= this . pageHeightposition -= this . A4_HEIGHT if ( leftHeight > 0 ) { pdf. addPage ( ) } } } pdf. save ( pdfFileName + ".pdf" , { returnPromise : true } ) . then ( ( ) => { let doms = document. querySelectorAll ( '.emptyDiv' ) for ( let i = 0 ; i < doms. length; i++ ) { doms[ i] . remove ( ) ; } } ) ; this . ele. style. height = '' ; this . sucCallback ( ) resolve ( ) ; } ) } ; async outPutPdfFn ( pdfFileName ) { return new Promise ( ( resolve, reject ) => { let target = this . ele; this . pageHeight = target. scrollWidth / this . A4_WIDTH * this . A4_HEIGHT ; this . ele. style. height = 'initial' ; pdfFileName ? this . pdfFileName = pdfFileName : null ; this . pageNum = 1 ; this . domEach ( this . ele) this . getPDF ( resolve, reject) ; } ) } ; domEach ( dom ) { let childNodes = dom. childNodeschildNodes. forEach ( ( childDom, index ) => { if ( this . hasClass ( childDom, this . splitClassName) ) { let node = childDom; let eleBounding = this . ele. getBoundingClientRect ( ) ; let bound = node. getBoundingClientRect ( ) ; let offset2Ele = bound. top - eleBounding. toplet currentPage = Math. ceil ( ( bound. bottom - eleBounding. top) / this . pageHeight) ; if ( this . pageNum < currentPage) { this . pageNum++ let divParent = childDom. parentNode; let newNode = document. createElement ( 'div' ) ; newNode. className = 'emptyDiv' ; newNode. style. background = 'white' ; newNode. style. height = ( this . pageHeight * ( this . pageNum - 1 ) - offset2Ele + 30 ) + 'px' ; newNode. style. width = '100%' ; let next = childDom. nextSibling; if ( next) { divParent. insertBefore ( newNode, node) ; } else { divParent. appendChild ( newNode) ; } } } if ( this . hasClass ( childDom, this . breakClassName) ) { this . pageNum++ console. log ( 'break_page' ) ; let eleBounding = this . ele. getBoundingClientRect ( ) ; let bound = childDom. getBoundingClientRect ( ) ; let offset2Ele = bound. top - eleBounding. toplet alreadyHeight = offset2Ele % this . pageHeightlet remainingHeight = this . pageHeight - alreadyHeight + 20 childDom. style. height = remainingHeight + 'px' } if ( childDom. childNodes. length) { this . domEach ( childDom) } } ) } hasClass ( element, cls ) { return ( ` ` + element. className + ` ` ) . indexOf ( ` ` + cls + ` ` ) > - 1 ; }
} export default htmlToPdf;