html2canvas以及domtoimage的使用踩坑總結

前言

首先作個自我介紹,我是成都某企業的一名剛剛入行約一年的前端,在以前的開發過程當中,遇到了問題,也解決了問題,
可是在下一次解決相同問題的時候,只對這個問題有一絲絲的印象,還須要重新去查找,因而,我註冊了segmemtfault,
便於蒐集個人問題總結,以及將踩坑經驗分享給每個開發人員,好了,閒話很少說。

需求

需求:要求可以實現根據後端返回的數據生成一張image,便於用戶將圖片分享到朋友或者朋友圈,取得用戶的關注。

開始踩坑

一.html2canvas對於跨域圖片,轉換的時候會將跨域圖片識別爲空白。
問題分析:
既然是因爲跨域引發的問題,那咱們讓資源不跨域不就能夠訪問了嗎?
解決辦法:
將圖片放置服務器,經過nginx進行代理資源,前端訪問圖片便不涉及到跨域問題。javascript

二.html2canvas動態加載內容,經過canvas轉換出來的數據,圖片爲空
問題分析:
內容是動態加載進來的,轉換確定是在請求完畢以後再去轉換,可是在請求完畢以後去轉換,按理說所須要的全部數據都已經到達前端,應該能夠轉換,通過思考,發現圖片內容從後臺讀取須要必定時間去解析,纔可以完整的將圖片資源展現出來,html2canvas是將頁面上顯示的dom元素,通過解析將dom畫在canvas上在轉換爲image圖片格式。
解決辦法:
1.讓html2canvas轉換代碼等待必定時間,在進行轉換操做,可進行轉換。代碼以下圖所示css

clipboard.png

2.當所有的圖片數據都加載完畢以後,在執行轉換操做。(本人建議第二種,更保險)html

clipboard.png

三.html2canvas轉換的base64位圖不能被ios8以上版本所識別。會呈現出整個截圖頁面空白
問題分析:
這個問題的原由,應該是html2canvas對高版本的ios不支持(自我感受),這個問題我非常頭疼,當時根本沒有對ios進行測試。客戶使用的時候發現了這個問題,無法。想辦法解決。百度說是因爲ios不能識別base64的前綴,因而我試過將圖片的前綴去除,但發現沒反應。仍是無用。思來想去感受html2canvas坑太多了。填都填不完。因而。
解決辦法:
我採用了另外一款插件,dom-to-image,弄上去沒有問題了。前端

clipboard.png

四.dom-to-image運用上去,在ios上可以出現內容了,但發現存在一個問題,部分圖片內容,第一次進行公衆號網頁加載,沒有正確顯示,要在次進入纔會顯示,此bug一樣是ios8以上版本
問題分析:
這一個問題我沒有找到問題所在,一臉懵,不過最終仍是獲得瞭解決。
解決辦法:
運用dom-to-imagede toSvg方式完美解決問題。java

clipboard.png

五.離成功只有一步之遙了,使用了svg以後安卓手機不能將圖片分享給朋友。識別不了
問題分析:
安卓能識別jpeg但不能識別svg矢量圖片
解決辦法:
本身手寫咯。判斷手機爲安卓仍是ios。jquery

clipboard.png

六.全部的問題都已解決,我興奮的跑去借了個果5,拿來測試,發現網頁的背景圖片不見了。
問題分析:
我長按兩秒左右又是正常顯示了,故圖片是已經完美轉換成功,多是由於圖片在轉換過程當中,沒有完美適配到4.0寸的屏幕,
解決辦法:
模擬長按事件,解決bug,這個方式可能不太好,但也是一種解決方式。android

總結

躺過的坑都是個人經驗,分享的同時我又加固了一遍。解決實際問題的思路,在過了一遍,對我幫助很棒。ios

代碼參考nginx

//判斷手機爲安卓仍是ios  安卓html2canvas方法  ios系統dom-to-image方法        
$(".code").click(function() {
    var u = navigator.userAgent;
    var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android終端
    if(isiOS) {
        window.location.href = "mycodeios.html"
    } else if(isAndroid) {
        window.location.href = "mycode.html"
    }
})

安卓html2canvas方法ajax

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
        <title>分享</title>
        <link rel="stylesheet" type="text/css" href="css/reset.css" />
        <style type="text/css">
            /*頭部*/
            
            body {
                background: #FFFFFF;
                height: 0 !important;
            }
            
            .container {
                max-width: 750px;
                min-width: 32px;
                margin: 0 auto;
                background: #FFFFFF;
            }
            
            .zhe {
                position: fixed;
                max-width: 750px;
                min-width: 32px;
                width: 100%;
                height: 100%;
                background: #45A196;
                z-index: 9;
            }
            
            .imge {
                position: absolute;
                max-width: 750px;
                min-width: 32px;
                width: 90%;
                height: 100%;
                margin: 0% 5%;
                z-index: 99;
                /*background: url(codeimg/code.jpg) no-repeat;*/
                /*background-size: contain;*/
            }
            
            .left {
                position: absolute;
                left: 12%;
                top: 70%;
                color: #FFFFFF;
                font-size: 26px;
                letter-spacing: 5px;
            }
            
            .bottom {
                position: absolute;
                right: 38%;
                top: 65%;
            }
            
            .codebotom {
                position: absolute;
                padding: 10px;
                background: #FFFFFF;
                width: 90px;
                height: 90px;
            }
            
            .butright_img {
                position: absolute;
                width: 80px;
                height: 80px;
                margin: 5px;
                top: 0px;
                left: 0px;
            }
            
            .textbottom {
                position: absolute;
                width: 40px;
                letter-spacing: 5px;
                color: #FFFFFF;
                top: 20px;
                left: -45px;
            }
            
            .butright {
                position: absolute;
                bottom: 50px;
                right: 15%;
                color: #4BA59B;
                padding: 10px 20%;
                border-radius: 3px;
                z-index: 9999;
                color: #ffffff;
                text-align: center;
            }
            
            .image {
                display: block;
                max-width: 750px;
                min-width: 32px;
                width: 100%;
                position: absolute;
                top: 0px;
                left: 0px;
                background: #FFFFFF;
                z-index: 9999;
            }
        </style>
    </head>

    <body>
        <div class="container">
            <!--二維碼-->
            <div class="zhe"></div>
            <div class="imge">
                <div style="position: absolute; top: 0px; left: 0px;">
                    <img src="codeimg/code.jpg" />
                </div>
                <div style="width: 100%;height: 100%; position: relative;">
                    <div class="left state"></div>
                    <div class="bottom">
                        <div class="textbottom">掃碼當即註冊</div>
                        <div class="codebotom">
                            <div id="qrcode" class="butright_img"></div>
                        </div>
                    </div>
                </div>
                <div>
                    <div class="butright">長按保存圖片</div>
                </div>
            </div>
            <div class="image" style="display: block;">

            </div>

        </div>
    </body>
    <script src="js/config.js"></script>
    <script src="js/jquery-2.1.4.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/fenxiang.js" type="text/javascript" charset="utf-8"></script>
    <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
    <!--二維碼-->
    <script src="js/jquery.qrcode.logo.min.js" type="text/javascript" charset="utf-8"></script>
    <!--html2canvas圖片-->
    <script type="application/javascript" src="http://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
    <script type="text/javascript">
        //  倒計時  
        $(function() {
            var openid_list = eval(decodeURIComponent(localStorage.getItem("openid")))
            var openid = openid_list[1]
            var access_token = openid_list[0]

            window.history.pushState(null, null, "#");
            window.addEventListener('popstate', function(e) {
                window.location.href = 'my.html'
            }, false);

            //建立二維碼
            function createQRCode(id, url, width, height, src) {
                $('#' + id).empty();
                jQuery('#' + id).qrcode({
                    render: 'canvas',
                    text: url,
                    width: width, //二維碼的寬度  
                    height: height, //二維碼的高度  
                    imgWidth: width / 6, //圖片寬
                    imgHeight: height / 6, //圖片高
                    src: src //圖片中央的二維碼
                });
            }
            var url = 'https://api.gzkny.com/h5/aa.html?openid=' + openid;
            createQRCode("qrcode", url, 80, 80, "image/follow.jpg");

            // 使用html2canvas 轉換html爲canvas 安卓html2canvas方法
            function downloadForJS() {   
                html2canvas(document.body, {
                    useCORS: true,
                    logging: true
                }).then(function(canvas) {
                    var imgUri = canvas.toDataURL().replace("image/png", "image/octet-stream"); // 獲取生成的圖片的url  
                    //    $('.zhe').hide()
                    //    $('.imge').hide()
                    $('.image').html('<img src="' + imgUri + '"/>')
                });
            }

            // 獲取數據
            $.ajax({
                method: 'GET',
                url: window.BASE_URL + 'api/v1/member/get',
                contentType: 'application/x-www-form-urlencoded',
                async: true,
                dataType: "json",
                data: {
                    access_token: access_token,
                },
                success: function(data) {
                    console.log(data)
                    if(data.error == 'success') {
                        $('.state').html(data.data.username)
                        downloadForJS()
                    }
                }
            });

        })
    </script>

</html>

ios系統dom-to-image方法(css樣式必定要本身寫   避免圖片失效)

<!DOCTYPE html>
<html lang="zh">

    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>分享</title>
        <script src="js/jquery-2.1.4.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript" src="js/dom-to-image.js"></script>
        <script type="text/javascript" src="js/FileSaver.js"></script>
        <style type="text/css">
            /*頭部*/
            * {
                margin: 0px;
                padding: 0px;
            }
            
            body {
                background: #45A196;
                width: 100%;
                height: 100%;
            }
            
            .container {
                max-width: 750px;
                min-width: 32px;
                margin: 0 auto;
                position: relative;
            }
            
            .imge {
                position: relative;
                max-width: 750px;
                min-width: 32px;
                width: 100%;
                height: 100%;
                z-index: 99;
            }
            
            .left {
                position: absolute;
                left: 12%;
                margin-top: 116%;
                color: #FFFFFF;
                font-size: 26px;
                letter-spacing: 5px;
            }
            
            .bottom {
                position: absolute;
            }
            
            .codebotom {
                position: absolute;
                background: #FFFFFF;
                width: 90px;
                height: 90px;
            }
            
            .butright_img {
                position: absolute;
                width: 80px;
                height: 80px;
                margin: 5px;
                top: 0px;
                left: 0px;
            }
            
            .textbottom {
                position: absolute;
                width: 50px;
                letter-spacing: 5px;
                color: #FFFFFF;
                top: 15px;
                left: -45px;
            }
            
            .butright {
                position: fixed;
                bottom: 0px;
                right: 40%;
                z-index: 9999;
                color: #ffffff;
            }
            
            .image {
                display: block;
                max-width: 750px;
                min-width: 32px;
                width: 100%;
                position: absolute;
                top: 0px;
                left: 0px;
                background: #FFFFFF;
                z-index: 9999;
            }
        </style>
    </head>

    <body>
        <div id="container">
            <div class="container">
                <div class="imge">
                    <img style="width: 100% ; position: absolute;" src="codeimg/code.jpg" />
                    <div class="left state"></div>
                    <div style=" position: absolute;right: 38%; margin-top: 110%;">
                        <div class="bottom">
                            <div class="textbottom">掃碼當即註冊</div>
                            <div class="codebotom">
                                <div id="qrcode" class="butright_img"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="butright">長按保存圖片</div>
        </div>
        <div class="bot" style="position: fixed; z-index: 9999999999999999; background: #4BA59B;"></div>

    </body>
    <!--二維碼-->
    <script src="js/jquery.qrcode.logo.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/config.js"></script>
    <script type="text/javascript">
        $(function() {
            var openid_list = eval(decodeURIComponent(localStorage.getItem("openid")))
            var openid = openid_list[1]
            var access_token = openid_list[0]

            window.history.pushState(null, null, "#");
            window.addEventListener('popstate', function(e) {
                window.location.href = 'my.html'
            }, false);

            //建立二維碼
            function createQRCode(id, url, width, height, src) {
                $('#' + id).empty();
                jQuery('#' + id).qrcode({
                    render: 'canvas',
                    text: url,
                    width: width, //二維碼的寬度  
                    height: height, //二維碼的高度  
                    imgWidth: width / 6, //圖片寬
                    imgHeight: height / 6, //圖片高
                    src: src //圖片中央的二維碼
                });
            }
            var url = 'https://api.gzkny.com/h5/aa.html?openid=' + openid;
            createQRCode("qrcode", url, 80, 80, "image/follow.jpg");

            //            ios系統dom-to-image方法    
            function downloadForJS() {
                domtoimage.toSvg(document.getElementById('container'))
                    .then(function(dataUrl) {
                        /* do something */
                        var img = new Image();
                        img.src = dataUrl;
                        $('.container').hide()
                        //    console.log(dataUrl)
                        //    document.body.appendChild(img);
                        $('.bot').html(img)
                    });
            }

            //    禁止屏幕滑動
            function bodyScroll(event) {
                event.preventDefault();
            }
            document.body.addEventListener('touchmove', bodyScroll, false);
            $('body').css({
                'position': 'fixed',
                "width": "100%"
            });

            //  獲取數據
            $.ajax({
                method: 'GET',
                url: window.BASE_URL + 'api/v1/member/get',
                contentType: 'application/x-www-form-urlencoded',
                async: true,
                dataType: "json",
                data: {
                    access_token: access_token,
                },
                success: function(data) {
                    console.log(data)
                    if(data.error == 'success') {
                        $('.state').html(data.data.username)
                        downloadForJS()
                    }
                }
            });

        })
    </script>

</html>
相關文章
相關標籤/搜索