利用canvas将html页面截成图片——问题已成功解决

现在需要做一个功能:

一个html页面有多个div,每个div里面都含有用echarts画的图表,现在要对这个html页面进行自动截图

我在网上找到了一个方法:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>htmltopic</title>
    <script type="text/javascript" src="js/jquery-2.2.1.min.js"></script>
    <script type="text/javascript" src="js/html2canvas.min.js"></script>
    <style>
        * {
            margin: 0;
        }
        .main{
            height: 100%;
            width: 100%;
        }

        body{
            background-color: #2e6da4;
        }
        .test1 {
            width: 50%;
            height: 100%;
            text-align: center;
            line-height: 100px;
            /*background-color: #87CEEB;*/
            display: inline-block;
            vertical-align: top;
        }
        
        canvas {
            /*margin-right: 5px;*/
        }


        .down {
            float: left;
            margin: 40px 10px;
        }
        .down2 {
            float: left;
            margin: 40px 30px;
        }
    </style>
</head>
<body id="test">

<div class="main">
<div class="test1" >测试</div>
<div class="test1" >测试</div>
<!--<div class="test1" id="test1">测试</div>-->
</div>
<div><a class="down" href="" download="downImg">下载</a>
</div>
<div><a class="down2" href="" download="downImg">下载2</a></div>
<script>
    //直接选择要截图的dom,就能截图,但是因为canvas的原因,生成的图片模糊
    //html2canvas(document.querySelector('div')).then(function(canvas) {
    //    document.body.appendChild(canvas);
    //});
    //创建一个新的canvas
    var canvas2 = document.createElement("canvas");
    let
        _canvas = document.querySelector('#test');
    var w = parseInt(window.getComputedStyle(_canvas).width);
    var h = parseInt(window.getComputedStyle(_canvas).height);
    //将canvas画布放大若干倍,然后盛放在较小的容器内,就显得不模糊了
    canvas2.width = w * 2;
    canvas2.height = h * 2;
    canvas2.style.width = w + "px";
    canvas2.style.height = h + "px";
    //可以按照自己的需求,对context的参数修改,translate指的是偏移量
    //  var context = canvas.getContext("2d");
    //  context.translate(0,0);
    var context = canvas2.getContext("2d");
    context.scale(2, 2);
    html2canvas(document.querySelector('#test'), { canvas: canvas2 }).then(function(canvas) {
        //document.body.appendChild(canvas);
        //canvas转换成url,然后利用a标签的download属性,直接下载,绕过上传服务器再下载
        document.querySelector(".down").setAttribute('href', canvas.toDataURL());
    });
</script>


<script language="javascript">
    //这是另一种写法
    $(function () {
        $(".down2").click(function () {
            html2canvas($("#test")).then(function (canvas) {
                var imgUri = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); // 获取生成的图片的url
                window.location.href = imgUri; // 下载图片
            });


            //html2canvas($('.tongxingzheng_bg'), {
            //    onrendered: function (canvas) {
            //        var data = canvas.toDataURL("image/png");//生成的格式
            //        //data就是生成的base64码啦
            //        alert(data);
            //    }
            //});
        });
    });
</script>
</body>
</html>

截的图如下:

问题来了,上面只是简单地html页面,当我在html页面放echarts时,就出现问题了
html代码

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">   <!-- 在IE运行最新的渲染模式 -->
    <meta name="viewport" content="width=device-width, initial-scale=1">    <!-- 初始化移动浏览显示  -->
    <meta name="Author" content="Dreamer-1.">

    <script src="js/jquery.min.js"></script>
    <script  src="js/echarts-all.js"></script>
    <script type="text/javascript" src="js/jquery-2.2.1.min.js">
    </script><script type="text/javascript" src="js/html2canvas.min.js"></script>
    <!-- <script  src="js/echarts.min.js"></script> -->
    <title>生成图片测试2</title>
    <style>
        body{
            background-color: #2e6da4;
        }
    </style>
</head>


<body>
<div><a class="down" href="" download="downImg">下载</a></div>
<div><a class="down2" href="" download="downImg">下载2</a></div>
<!-- 显示Echarts图表 -->
<div style="height:410px;min-height:100px;margin:0 auto;" id="main"></div>


<script type="text/javascript">
    var data = ["9","19","29","39","49","59"];
    var barText = "初始化完毕";
    var barSubtext = "副标题";
    var xData = ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"];
    var legendValue = ['销量','销量2'];
    var seriesName1 = '销量';
    var seriesName2 = '销量2';

    var worldMapContainer = document.getElementById('main')
    var resizeWorldMapContainer = function () {
        worldMapContainer.style.width = window.innerWidth+'px';
        worldMapContainer.style.height = window.innerHeight+'px';
    };

    //设置容器高宽
    // resizeWorldMapContainer();


    // 基于准备好的dom,初始化echarts实例
    var myChart = echarts.init(worldMapContainer);

    var option = {
        title : {
            text : barText,
            subtext: barSubtext
        },
        tooltip : {},
        legend : {
            data : legendValue
        },
        xAxis : {
            data : xData,
            type : 'category'
        },
        yAxis : {},

        color: ['#ddffee', '#00ffff'],
        series : [ {
            name : seriesName1,
            type : 'bar',
            data : data ,           //该位置放的是一个数组
            barWidth: 50,
            /* itemStyle:{
                normal:{
                    color:'#ddffee'
                }
            },  */
            label:{
                normal:{
                    show:true,
                    position:'top'
                }
            },
        } ,
            {
                name : seriesName2,
                type : 'bar',
                data : data  ,          //该位置放的是一个数组
                barWidth: 50,
                /* itemStyle:{
                    normal:{
                        color:'#00ffff'
                    }
                }, */
                label:{
                    normal:{
                        show:true,
                        position:'top'
                    }
                },
            }]
    };

    myChart.setOption(option);    //载入图表
    //用于使chart自适应高度和宽度
    window.onresize = function () {
        //重置容器高宽
        resizeWorldMapContainer();
        myChart.resize();
    };
    window.onload = addSaveImageUrl;

    function addSaveImageUrl() {
            var canvas2 = document.createElement("canvas");           //创建一个新的canvas
            let _canvas = document.querySelector('#main');      //这里面填写 你需要截图的div
            var w = parseInt(window.getComputedStyle(_canvas).width);
            var h = parseInt(window.getComputedStyle(_canvas).height);
            canvas2.width = w * 2;
            canvas2.height = h * 2;              //将canvas画布放大2倍或者更多,然后盛放在较小的容器内,就显得不模糊了
            canvas2.style.width = w + "px";
            canvas2.style.height = h + "px";
            var context = canvas2.getContext("2d");
            context.scale(2, 2);       //指图片偏移
            html2canvas(document.querySelector('#main'), {    //写需要截图的div
                taintTest: false,
                useCORS: true,
                allowTaint: false,   //这三串代码解决跨域问题
                canvas: canvas2
            }).then(
                function (canvas) {
                    document.querySelector(".down").setAttribute('href', canvas.toDataURL());      //down设置为你的点击键
                });

        }
</script>


</body>
</html>

页面效果:

截的图如下:

先不考虑后面马赛克的问题,发现用echarts时,截的图片只是一部分,其余部分是空白

然后我用谷歌浏览器、火狐浏览器都试了,谷歌从始至终截的图都如上图所示,火狐第一次加载页面截图如下所示,但是刷信页面之后截的图和谷歌截的图一样了。

在网上找了一下原因,这是因为跨域问题

因为我的网页里面的图表不是来自我的服务器,而是来自echarts组件的。那么这些图表就和这个网页不是同域,那么html2canvas就无法对这个网页进行进图。如果我的网页所有的东西都放在单独的服务器上,那么用html2canvas对整个网页进行截图就会发现所有的图片的地方都是空白。


问题先记录下来,解决问题之后进行更更新


折腾了三天左右的时间,中间有请教大神,大神还不相信我会做出来,结果让他失望了,哈哈哈

下面详细说一下怎么解决的

我的html页面放了多个echarts图,我要将该页面生成一个图片,现在的思路是

1、将所有图表放在一个大的div里面

2、在echarts的渲染结束事件中将画布的url赋给页面中没有src值得img标签

实现的代码如下:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <link href="css/bootstrap.css" rel="stylesheet">
    <link rel="stylesheet" href="css/base.css">
    <link rel="stylesheet" href="css/index.css">
    <script type="text/javascript" src="js/html2canvas.min.js"></script>
    <style>
    .t_title {
        width: 100%;
        height: 100%;
        text-align: center;
        font-size: 2.5em;
        line-height: 80px;
        color: #fff;
    }

    #chart_map {
        cursor: pointer;
    }

    .t_show {
        position: absolute;
        top: 0;
        right: 0;
        border-radius: 2px;
        background: #2C58A6;
        padding: 2px 5px;
        color: #fff;
        cursor: pointer;
    }
    </style>
</head>

<body>
<div id="main">
    <!--header-->
    <div class="header">
        <div class="bg_header">
            <div class="header_nav fl t_title">
               
            </div>
        </div>
    </div>
    <!--main-->
    <div class="data_content">
        <div class="data_time">
            
        </div>
        <div class="data_main">
        	<!-- 左侧部分 -->
            <div class="main_left fl">
                <div class="left_1 t_btn6" style="cursor: pointer;">
                    <!--左上边框-->
                    <div class="t_line_box">
                        <i class="t_l_line"></i>
                        <i class="l_t_line"></i>
                    </div>
                    <!--右上边框-->
                    <div class="t_line_box">
                        <i class="t_r_line"></i>
                        <i class="r_t_line"></i>
                    </div>
                    <!--左下边框-->
                    <div class="t_line_box">
                        <i class="l_b_line"></i>
                        <i class="b_l_line"></i>
                    </div>
                    <!--右下边框-->
                    <div class="t_line_box">
					
                        <i class="r_b_line"></i>
                        <i class="b_r_line"></i>
                    </div>
                    <div class="main_title" id="title_1" >
                        <!-- <img src="images/t_1.png" alt="">&nbsp; -->

                    </div>
                    <div id="char_bar" class="chart" style="width:100%;height: 280px;"></div>
                </div>
                <div class="left_2" style="cursor: pointer;">
                    <!--左上边框-->
                    <div class="t_line_box">
                        <i class="t_l_line"></i>
                        <i class="l_t_line"></i>
                    </div>
                    <!--右上边框-->
                    <div class="t_line_box">
                        <i class="t_r_line"></i>
                        <i class="r_t_line"></i>
                    </div>
                    <!--左下边框-->
                    <div class="t_line_box">
                        <i class="l_b_line"></i>
                        <i class="b_l_line"></i>
                    </div>
                    <!--右下边框-->
                    <div class="t_line_box">
                        <i class="r_b_line"></i>
                        <i class="b_r_line"></i>
                    </div>
                    <div class="main_title" id="title_2">
                        <!-- <img src="images/t_2.png" alt="">&nbsp; -->
                    </div>
                    <div id="chart_2" class="chart t_btn9" style="width:100%;height: 280px;"></div>
                </div>
            </div>
            <!-- 中间部分 -->
            <div class="main_center fl">
                <div class="center_text">
                    <!--左上边框-->
                    <div class="t_line_box">
                        <i class="t_l_line"></i>
                        <i class="l_t_line"></i>
                    </div>
                    <!--右上边框-->
                    <div class="t_line_box">
                        <i class="t_r_line"></i>
                        <i class="r_t_line"></i>
                    </div>
                    <!--左下边框-->
                    <div class="t_line_box">
                        <i class="l_b_line"></i>
                        <i class="b_l_line"></i>
                    </div>
                    <!--右下边框-->
                    <div class="t_line_box">
                        <i class="r_b_line"></i>
                        <i class="b_r_line"></i>
                    </div>
                    <div class="main_title" id="title_3">
                        <!-- <img src="images/t_3.png" alt="">&nbsp; -->
                    </div>
                    <div id="chart_map" style="width:100%;height:610px;"></div>
                </div>
            </div>
            <!-- 右侧部分 -->
            <div class="main_right fr">
                <div class="right_1">
                    <!--左上边框-->
                    <div class="t_line_box">
                        <i class="t_l_line"></i>
                        <i class="l_t_line"></i>
                    </div>
                    <!--右上边框-->
                    <div class="t_line_box">
                        <i class="t_r_line"></i>
                        <i class="r_t_line"></i>
                    </div>
                    <!--左下边框-->
                    <div class="t_line_box">
                        <i class="l_b_line"></i>
                        <i class="b_l_line"></i>
                    </div>
                    <!--右下边框-->
                    <div class="t_line_box">
                        <i class="r_b_line"></i>
                        <i class="b_r_line"></i>
                    </div>
                    <div class="main_title" id="title_4">
                        <!-- <img src="images/t_4.png" alt="">&nbsp; -->
                    </div>
                    <div id="chart_4" class="echart t_btn7" style="width:100%;height: 280px;"></div>
                </div>
                <div class="right_2">
                    <!--左上边框-->
                    <div class="t_line_box">
                        <i class="t_l_line"></i>
                        <i class="l_t_line"></i>
                    </div>
                    <!--右上边框-->
                    <div class="t_line_box">
                        <i class="t_r_line"></i>
                        <i class="r_t_line"></i>
                    </div>
                    <!--左下边框-->
                    <div class="t_line_box">
                        <i class="l_b_line"></i>
                        <i class="b_l_line"></i>
                    </div>
                    <!--右下边框-->
                    <div class="t_line_box">
                        <i class="r_b_line"></i>
                        <i class="b_r_line"></i>
                    </div>
                    <div class="main_title" id="title_5">
                        <!-- <img src="images/t_7.png" alt="">&nbsp; -->
                    </div>
                    <div id="chart_5" class="echart fl t_btn4" style="width:100%;height: 280px;cursor: pointer;"></div>
                </div>
            </div>
        </div>
    </div>
    </div>
     <img alt="" src="" id="testImage">
</body>
<script src="js/jquery-2.2.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/common.js"></script>
<script src="js/echarts.min.js"></script>
<script src="template/bar.js"></script>
<script src="template/line.js"></script>
<script src="template/pie.js"></script>
<script type="text/javascript">

myChart.on('rendered', function () {
	/* console.log($("canvas")[0].toDataURL());
    document.querySelector("#testImage").setAttribute('src', $("canvas")[0].toDataURL()); */
	var canvas2 = document.createElement("canvas");           //创建一个新的canvas
    let _canvas = document.querySelector('#main');      //这里面填写 你需要截图的div
    var w = parseInt(window.getComputedStyle(_canvas).width);
    var h = parseInt(window.getComputedStyle(_canvas).height);
    canvas2.width = w;
    canvas2.height = h;              //将canvas画布放大2倍或者更多,然后盛放在较小的容器内,就显得不模糊了
    canvas2.style.width = w + "px";
    canvas2.style.height = h + "px";
    
//  canvas.width = parseInt(canvas.style.width)*2;
//  canvas.height = parseInt(canvas.style.height)*2;
//  canvas.style.height = canvas.height/2 + "px";
//  canvas.style.width = canvas.width/2 + "px";
    
    var context = canvas2.getContext("2d");
    context.scale(1, 1);       //指图片偏移
    html2canvas(document.querySelector('#main'), {    //写需要截图的div
        taintTest: false,
       useCORS: true,
        allowTaint: false,   //这三串代码解决跨域问题
        canvas: canvas2
    }).then(
        function (canvas) {
           console.log(canvas.toDataURL());
            document.querySelector("#testImage").setAttribute('src', canvas.toDataURL());
        });
    
});


</script>
<!-- <script src="js/dataTool.js"></script>
<script src="js/index.js"></script>
<script src="js/china.js"></script> -->
</html>

图片生成实现了,现在想想项目的业务是要在后台生成图片,我的思路是  

既然将canvas.toDataURL()赋给一个img标签的src,它就可以展示成一个图片,那我可以将这个值存到后台,将来展示的时候拿到前台放到img标签里面就可以了

参考:

https://www.jb51.net/article/150740.htm

猜你喜欢

转载自blog.csdn.net/Sun_of_Rainy/article/details/85160732