Problems encountered
In the project development, there was a requirement that the user upload a timeline data and visualize the timeline data by selecting different templates. When the user saves the file, the template preview image is captured as the cover of the file.
Ideas of implementation
The end result is that the corresponding DOM is converted into an image and sent back to the background. The key difficulty is how to convert the DOM to an image. However, the most difficult part already has a mature framework html2Canvas. The project is pressed for time, so we will first use the third-party plug-in to encapsulate the Canvas method to take screenshots by ourselves, and then try again.
- Gets the DOM structure of an iframe
- Pass the acquired DOM directly to HTML2Canvas and convert canvas
- Call toDataURL to convert canvas to image Base64 format
html
The page display
Implementation steps
- Gets the DOM structure of an iframe
Const iframeHtml = this. $refs. TimeLineDom. ContentWindow / / get the iframe content const iframeBody = iframeHtml.document.getElementsByTagName('body')[0]Copy the code
- Convert the DOM to Canvas and base64
ImgBase64 is a captured image in base64 format
Html2canvas (iframeBody).then(canvas => {// convert to image, ImgBase64 = canvas. ToDataURL ('image/ PNG ') if (imgBase64) {resolve(imgBase64)} else {reject(new Error(' Image conversion Error ') }})Copy the code
The conversion is performed when the file is saved. We want to save the image after the successful conversion. So the code needs to be modified slightly:
HandleSaveImg () {let imgBase64 = null var iframeHtml = this. $refs. TimeLineDom. ContentWindow / / get the iframe content const iframeBody = iframeHtml.document.getElementsByTagName('body')[0] return new Promise(function (resolve, Reject) {html2canvas(iframeBody). Then (canvas => {// convert to image, ImgBase64 = canvas. ToDataURL ('image/ PNG ') if (imgBase64) {resolve(imgBase64)} else {reject(new) Error(this.globleMessage.errorImgTransform)) } }) }) },Copy the code
Done! Let’s see what happens
. Obviously this defeats the purpose, because the image is so long that you can’t see anything at all
Going over the requirements again, we want the cover image to look exactly like the preview window.
We also need to do some processing, namely, get the scroll distance of the template inside the iframe, and calculate and intercept the same view area as the preview window.
- Gets the scrolling distance of iframe
const iframeScrollY = iframeHtml.document.documentElement.scrollTop
const iframeScrollX = iframeHtml.document.documentElement.scrollLeft
Copy the code
- Pass the scrolling distance and the width and height to be captured to HTML2Canvas
Html2canvas (iframeBody, {allowTaint: true, useCORS: true, width: 812, // TODO screenshot with 1920*1080 resolution preview window width height: 661, x: iframeScrollX, y: iframeScrollY })Copy the code
Let’s see what happensThat’s it. Take a look at the other templates:
Preview:
Cover:
Preview Figure 2:
The cover 2:
Preview Figure 3:
Cover 3:
The final code
HandleSaveImg () {let imgBase64 = null var iframeHtml = this. $refs. TimeLineDom. ContentWindow / / get the iframe content const iframeBody = iframeHtml.document.getElementsByTagName('body')[0] const iframeScrollY = iframeHtml.document.documentElement.scrollTop const iframeScrollX = iframeHtml.document.documentElement.scrollLeft return new Promise((resolve, reject) => { html2canvas(iframeBody, { allowTaint: true, useCORS: true, width: Height: 661, x: iframeScrollX, y: IframeScrollY}). Then (canvas => {// convert to picture, ImgBase64 = canvas. ToDataURL ('image/ PNG ') if (imgBase64) {resolve(imgBase64)} else {reject(new) Error(this.globleMessage.errorImgTransform)) } }) }) },Copy the code