核心是在html2canvas執行前先替換所有圖片轉換為Blob,這種方式不會出現圖片缺失的情況
/** * @description 替換 去全部圖片真實地址為blob 渲染 截圖 * @param {element} el 截圖的dom區域 * @param {function} success 成功 * @param {function} error 錯誤 */ function getHandle({ el, success, error } = {}) { let imgArr = el.querySelectorAll('img') imgArr = Array.from(imgArr) let i = 0 if (imgArr[0]) { let timer = setInterval(() => { clearInterval(timer) if (imgArr.length !== i) { error && error('超時') } }, 10000); [...imgArr].forEach((dom) => { dom.src = `${dom.src}?${Math.random()}`; getUrlBlob(dom.src, ((blob) => { if (blob !== false) { dom.src = blob } i++ // 校驗是否全部替換完畢 if ((imgArr.length) === i) { clearInterval(timer) IsRender.call(this, el, success, error) } })) }) return } IsRender.call(this, el, success, error) }
/** * @description blob轉換處理 * @param {string} url 傳 url 和 一個回調 * @param {function} callback false 說明已是blob 或者 當前img 無 src * 返回值 轉成的blob臨時地址(成功) * 原圖的img src (轉換失敗 返回原圖) */ const getUrlBlob = (url, callback) => { const str = url.substring(0, 50) // 避免重復加載 if (str.includes('blob:')) { return callback(false) } // 避免img未有src屬性的情況,導致未返回 if (!str) { return callback(false) } let canvas = document.createElement("canvas") let ctx = canvas.getContext("2d") let img = new Image img.crossOrigin = 'Anonymous' img.src = url img.onload = function () { canvas.height = img.height canvas.width = img.width ctx.drawImage(img, 0, 0) try { canvas.toBlob((blob) => { callback(URL.createObjectURL(blob)) }) } catch (err) { callback(img.src) console.error('轉換失敗,使用原圖', err) } canvas = null } // img.error = function () { // callback(img.src) // console.error('轉換失敗,使用原圖', img.error) // } }
/** * @description 截圖操作 * @param {element} el 截圖的dom區域 * @param {function} success 成功 返回完整的base64 * @param {function} error 錯誤 返回err信息 */ function IsRender(el, success, error) { setTimeout(() => { var width = el.offsetWidth; //獲取dom 寬度 var height = el.offsetHeight; //獲取dom 高度 var canvas = document.createElement("canvas"); //創建一個canvas節點 // 兼容清晰度 const scale = window.devicePixelRatio; //定義任意放大倍數 支持小數 canvas.width = width * scale; //定義canvas 寬度 * 縮放 canvas.height = height * scale; //定義canvas高度 *縮放 var context = canvas.getContext('2d'); // 去圖片鋸齒 官網 context.mozImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false; context.msImageSmoothingEnabled = false; context.imageSmoothingEnabled = false; // options配置 var opts = { scale: scale, canvas: canvas, logging: false, width: width, height: height, dpi: 300, useCORS: true, backgroundColor: "transparent", allowTaint: false, }; // 進行截圖 html2canvas(el, opts) .then(canvas => { try { const base64 = canvas.toDataURL('image/png'); success && success.call(this, base64) } catch (err) { error && error(err) } }) .catch(err => { error && error(err) }) }, 500) }
// 調用方法 getHandle.call(this, { el: document.querySelector('.card_jt'), // 成功回調 async success(val) { // val就是拿到的 base64 }, error(err) { console.error(err) } })