html2canvas.js實現前端將頁面轉化爲圖片並長按下載

1.需求

因爲在最近在作的項目須要用到在前端把頁面生成圖片並保存到手機中,在技術調用過程當中本身寫了一個demo,沒有采用vue-cli腳手架,可是大同小異,這個demo也採用了vue2.js開發頁面,qrcode.js來生成二維碼,原理比較簡單。該demo項目:github地址 ,以爲有幫助的給一個星,萬分感謝。該項目不能直接打開index.html進行訪問,會出現報錯。請用 http-server 打開,不明白怎麼配置可參考http-server開啓本地服務css

在線預覽

image.png

具體的需求以下:
  1. 獲取後臺信息,得出排名和用戶圖像
  2. 點擊保存按鈕,把改頁面生成圖片
  3. 長按保存圖片或掃描二維碼

image.png
image.png
image.png

2.思路

  1. html2canvas.js:可將 htmldom 轉爲 canvas 元素。
  2. canvasAPI:toDataUrl() 可將 canvas 轉爲 base64 格式
  3. 在微信瀏覽器中,長按img,會彈起actionsheet,能夠進行保存、發送、識別二維碼等操做

3.代碼分析

解決圖片模糊

在pc端開發時生成圖片沒有問題,可是在移動端會出現模糊的狀況,主要緣由是像素比的問題。html

設備像素比 (簡稱 dpr) 定義了物理像素和設備獨立像素的對應關係,它的值能夠按以下的公式的獲得: 設備像素比 = 物理像素 / 設備獨立像素 // 在某一方向上,x方向或者y方向前端

解決代碼:vue

/**
         * 根據 window.devicePixelRatio 獲取像素比
         * @returns {number}
         */
        changeDpr: function() {
            if (window.devicePixelRatio && window.devicePixelRatio > 1) {
                return window.devicePixelRatio;
            }
            return 1;
        },
複製代碼

####解決圖片不顯示問題 若是引用沒有跨域配置的圖片地址會出現一下報錯git

Uncaught (in promise) DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
複製代碼

儘管不經過 CORS 就能夠在畫布中使用圖片,可是這會污染畫布。一旦畫布被污染,你就沒法讀取其數據。例如,你不能再使用畫布的 toBlob(), toDataURL() 或 getImageData() 方法,調用它們會拋出安全錯誤。 HTML 規範中圖片有一個 [crossorigin](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img#attr-crossorigin) 屬性,結合合適的 CORS 響應頭,就能夠實如今畫布中使用跨域 <img> 元素的圖像。github

解決代碼以下:vue-cli

// 將圖片轉爲base64格式
        imgTobase64: function(url, crossOrigin) {
            return new Promise(resolve => {
                const img = new Image();

                img.onload = () => {
                    const c = document.createElement('canvas');

                    c.width = img.naturalWidth;
                    c.height = img.naturalHeight;

                    const cxt = c.getContext('2d');

                    cxt.drawImage(img, 0, 0);

                    // 獲得圖片的base64編碼數據
                    resolve(c.toDataURL('image/png'));
                };

                // 結合合適的CORS響應頭,實如今畫布中使用跨域<img>元素的圖像
                crossOrigin && img.setAttribute('crossOrigin', crossOrigin);
                img.src = url;
            });
        }
複製代碼

####生成圖片 圖片生成是利用canvas來進行獲取並生成圖片,有些需求須要導出長圖,能夠改動一下代碼canvas

// 設置須要生成的圖片的大小,不限於可視區域(便可保存長圖)
            var w = dom.style.width;
            var h = dom.style.height;
複製代碼

因爲部分需求並不須要顯示個別的元素,能夠利用 data-html2canvas-ignore來進行忽略。若是在開始渲染不顯示,能夠把它的透明度進行變化,在轉化以前設置爲1便可。 下載後的圖片會覆蓋整個頁面,即長按就能夠調用actionsheet進行操做。 代碼以下:跨域

/**
         * 生成圖片
         */
        createImage: function() {
            var _this = this;

            // 獲取想要轉換的dom節點
            // var dom = document.getElementById('app');
            var dom = _this.$refs.app;
            var box = window.getComputedStyle(dom);

            // 顯示導出須要樣式
            _this.$refs.scanText.style.opacity = '1'

            // dom節點計算後寬高,轉爲整數
            var width = parseInt(box.width, 10);
            var height = parseInt(box.height, 10);

            // 獲取像素比
            var scaleBy = _this.changeDpr();

            // 建立自定義的canvas元素
            var canvas = document.createElement('canvas');

            // 設置canvas元素屬性寬高爲 DOM 節點寬高 * 像素比
            canvas.width = width * scaleBy;
            canvas.height = height * scaleBy;

            // 設置canvas css 寬高爲DOM節點寬高
            canvas.style.width = width + 'px';
            canvas.style.height = height + 'px';

            // 獲取畫筆
            var context = canvas.getContext('2d');

            // 將全部繪製內容放大像素比倍
            context.scale(scaleBy, scaleBy);

            // 設置須要生成的圖片的大小,不限於可視區域(便可保存長圖)
            var w = dom.style.width;
            var h = dom.style.height;

            html2canvas(dom, {
                allowTaint: true,
                width: w,
                height: h,
                useCORS: true
            }).then(function(canvas) {
                // 將canvas轉換成圖片渲染到頁面上
                var url = canvas.toDataURL('image/png');// base64數據
                var image = new Image();
                image.src = url;
                document.getElementById('shareImg').appendChild(image);
                // 隱藏按鈕
                _this.CanvasImageHide = false;
                // 給渲染後圖片大小全屏
                var shareImgElem = document.getElementById('shareImg');
                shareImgElem.style.height = '100%'
            });
        }
複製代碼
相關文章
相關標籤/搜索