html2canvas实现一键截图

        最近vue2项目里做一个生成海报的功能,需要用到html2canvas。

        html2canvas是纯js对浏览器端进行截图,允许直接在浏览器上拍摄网页或某一部分进行截图。但由于它的截图是基于DOM的,因此可能不会100%精确到真实的表示,因为它不会生成实际的屏幕截图,而是基于页面上可用的信息构建屏幕截图。

        附上官方网址:html2canvas - Screenshots with JavaScript

        官方网址里介绍比较简单,是通过获取DOM元素来进行截图,我这里是通过ref属性,所以实际使用过程中要根据情况选用,这里基于我项目中的实例做介绍。

1、安装

npm install html2canvas --save

2、在要使用的页面中引入

import html2canvas from "html2canvas";

3、使用

使用上分两部分来说,第一部分是基于<img>标签截取图片,第二部分是基于<div>标签截取全部内容。

(1)基于<img>标签截取

这里涉及到一个问题,截取<img>标签内容是通过自定义属性(这里指 :data-imgurl)实现的,但<img>标签绑定自定义属性的同时,动态绑定src属性,控制台会报错,目前不清楚具体因为什么,但解决方式是页面显示部分和实际截取区域分开,然后通过定位把实际截取区域隐藏,这部分要结合css 代码来理解。

直接上完整代码

<template>
    <div class="infoWap">
        <!-- 页面显示区域 -->
        <div class="loadView">
            <div class="course">
                <img :src="coverImg" alt="" >
            </div>
        </div>
        <div class="operateView">
            <van-button type="info" @click="saveImage" class="saveBtn">保存</van-button>
        </div>
        <!-- 实际截图区域,在页面中隐藏 -->
        <div class="outImg" ref="imageDown">
            <img src="" alt="" :data-imgurl="coverImg" ref="coverImgRef" >
        </div>
    </div>
</template>

<script>
import html2canvas from "html2canvas";
import { Button, Toast } from 'vant';

export default {
    data() {
        return {
            coverImg:'',  //从接口获取到的图片路径
        }
    },

    // 保存海报
    saveImage(){
        // 增加loading提示
        let saveLoading = Toast.loading({
            duration: 0,
            message: '海报生成中...',
            forbidClick: true,
         });
         let url = that.$refs.coverImgRef.dataset.imgurl;  //获取data-imgurl属性值
         let canvas = document.createElement('canvas');  //创建canvas元素
         let ctx = canvas.getContext('2d');
         let img = new Image();
         img.crossOrigin = 'Anonymous'; // 重点!设置image对象可跨域请求
         img.src = url + "?timeStamp=" + new Date().getTime(); //解决缓存引起访问失败需要添加时间戳
         img.onload = function () {
             canvas.height = img.height;
             canvas.width = img.width;
             ctx.drawImage(img, 0, 0);
             var dataURL = canvas.toDataURL('image/jpeg');
             // console.log(dataURL);
             that.$refs.coverImgRef.src = dataURL;
             html2canvas(that.$refs.coverImgRef, {
                 backgroundColor: null, //设置背景为透明色
                 useCORS: true, //支持图片跨域
                 scale: 2, // 处理模糊问题
                 dpi: 300, // 处理模糊问题
              }).then((canvas) => {
                  console.log(canvas)
                  // 把生成的base64位图片上传到服务器,生成在线图片地址
                  let url = canvas.toDataURL("image/png");
                  that.imgUrl = url;
                  //将图片下载到本地
                  let a = document.createElement("a"); // 生成一个a元素
                  let event = new MouseEvent("click", {
                      bubbles: true,
                      cancelable: true,
                      view: window
                  });// 创建一个单击事件
                  a.download =  "海报.png"; // 设置图片名称
                  a.href = that.imgUrl; // 将生成的URL设置为a.href属性
                  a.click();
                  // console.log(a)
                  a.setAttribute("target", "_blank");
                  a.dispatchEvent(event); // 触发a的单击事件
               }).finally(()=>{
                   saveLoading.clear();  //清除loading
               })
         }
    },
}
</script>

<style lang="scss" scoped>
.infoWap{
    height: 100vh;
    width: 100vw;
    overflow: hidden;
    position: relative;
    .outImg{
        position: absolute;  //子元素增加定位,在页面中隐藏
        left: 100%;
        top: 100%;
        height: 100vh;
        width: 100vw;
        padding: 0.2rem 0.5rem 1.7rem 0.5rem;
        box-sizing: border-box;
        img{
            width: 100%;
            height: 100%;
        }
    }
   .loadView{
        height: 100vh;
        width: 100vw;
        padding: 0.2rem 0.5rem 1.7rem 0.5rem;
        box-sizing: border-box;
        .course{
            width: 100%;
            height: 100%;
            img{
                width: 100%;
                height: 100%;
            }
        }
    }
    .operateView{
        width: 100vw;
        height: 1.5rem;
        position: fixed;
        bottom: 0;
        left: 0;
        background-color: #fff;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .saveBtn{
            flex: 1;
        }
    }
}

</style>

(2)截取<div>标签内容

<template>
    <div>
        <!-- 头部自定义菜单栏 -->
        <div class="topView">
            <p class="goBack" @click="goBack">返回</p>
            <p class="saveBtn" @click="handelSaves">保存</p>
        </div>
        <!-- 截取内容 -->
        <div>
            <div class="canvasView">
                <div class="canvasImg" ref="canvasImg">
                    <img :src="backgroundPicture" alt="" class="backImg">
                    <!-- 用户名称 -->
                    <div class="nameView">{{pageData.title ? pageData.title : '手动创建文字'}}</div>
                    <!-- 用户图片 -->
                    <div class="afterCropper">
                        <img :src="pageData.uploadPicImage ? pageData.uploadPicImage  : userImg" alt="" />
                    </div>
                    <!-- 用户二维码 -->
                    <img :src="pageData.qrCode ? pageData.qrCode : defaultQr" class="userQrImg" >
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import html2canvas from "html2canvas";
export default {    
    data() {
        return {
            pageData:{},  //所需数据
        }
    },
    methods:{
            let that = this;
            let imgHeight = that.$refs.canvasImg.offsetHeight; // 获取DOM高度
            let imgWidth = that.$refs.canvasImg.offsetWidth; // 获取DOM宽度
            let saveLoading = Toast.loading({
                message: '海报生成中...',
                forbidClick: true,
            });
            // 截取海报
            html2canvas(that.$refs.canvasImg, {
                useCORS: true, //允许跨域
                backgroundColor: '#ececec', //画布背景色,设置null为透明
                width: imgWidth,  //画布宽
                height: imgHeight,  //画布高
                scale: 2, // 处理模糊问题
                dpi: 300, // 处理模糊问题
            }).then((canvas) => {
                // 返回一个 canvas 对象,在dom中渲染 canvas 对象
                // 转化成 dataurL
                let url = canvas.toDataURL("image/png");
                that.imgUrl = url;
                //调用下载方法
                let a = document.createElement("a"); //创建一个a标签
                let event = new MouseEvent("click"); // 创建一个单击事件
                a.download = "海报"; // 设置图片名称
                a.href = that.imgUrl;   //指定下载文件名称
                a.dispatchEvent(event); // 触发a的单击事件
                // 这里可以获得截取到的base64格式的图片-url,可进行后续操作,比如传入接口等
            });
    }
}
</script>
<style lang="scss" scoped>
.editView{
    width: 100vw;
    height: 100vh;
    background-color: #333;
    .topView{
        width: 100%;
        height: 1rem;
        display: flex;
        justify-content: space-between;
        align-items: center;
        color: #fff;
        font-size: 0.3rem;
        padding: 0 0.5rem;
        box-sizing: border-box;
        .goBack{
            width: 20%;
            height: 1rem;
            text-align: center;
            line-height: 1rem;
        }
        .saveBtn{
            width: 20%;
            height: 1rem;
            text-align: center;
            line-height: 1rem;
        }
    }
    .canvasView{
        width: 100%;
        height: calc(100vh - 2rem);
        padding: 0.5rem 1rem;
        box-sizing: border-box;
        .canvasImg{
            width: 100%;
            height: 100%;
            // background: url('../../../assets/img/canvasBack.jpeg') no-repeat no-repeat center;
            background-repeat: no-repeat;
            background-size: 100% 100%;
            position: relative;
            .backImg{
                width: 100%;
                height: 100%;
            }
            .nameView{
                width: 45%;
                font-size: 0.38rem;
                color: #fff;
                position: absolute;
                top: 8%;
                right: 3%;
            }
            .afterCropper{
                width: 86%;
                height: 29%;
                position: absolute;
                top: 26%;
                left: 6%;
                -webkit-transform: rotate(-4deg);
                transform: rotate(-4deg);
                img{
                    width: 100%;
                    height: 100%;
                }
            }
            .userImg{
                width: 82%;
                height: 42%;
                position: absolute;
                top: 38%;
                left: 10%;
            }
            .userQrImg{
                width: 1rem;
                height: 1rem;
                position: absolute;
                bottom: 5%;
                right: 3%;
            }
        }
    }
}
</style>

(3)需要注意两点,一是截取后的图片是base64格式,如果需要转换其他形式,可以参考这些方法。

<1>图片转为base64格式

// 图片转为base64格式
getBase64Image(img) {
    let canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    let ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, img.width, img.height);
    let ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
    let dataURL = canvas.toDataURL("image/" + ext);
    return dataURL;
},

使用时:

if (imgUrl != "") {  // 判断一下要传入的图片是否存在
    let that = this;
    that.imgUrl = imgUrl;
    let image = new Image();
    image.src = imgUrl + "?v=" + Math.random(); // 处理缓存
    image.crossOrigin = "*"; // 支持跨域图片
    image.onload = function() {
        let base64 = that.getBase64Image(image); //调用函数并将其转为base64图片
        // console.log(base64)  // 可以打印一下验证
        that.backPicture=base64 // 赋值后可在页面进行使用
    };
}

<2>base64图片转文件流

// base64图片转文件流
base64toFile(dataurl,filename){
    let arr = dataurl.split(',');
    let mime = arr[0].match(/:(.*?);/)[1];
    let suffix = mime.split('/')[1];
    let bstr = atob(arr[1]);
    let n = bstr.length;
    let u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], `${filename}.${suffix}`, {
        type: mime
    });
},

使用时:

// 上传图片文件

uploadPoster(photo){
    let imgFile = this.base64toFile(photo);
    // 进行接口请求等操作
    // ...
}

还有一点需要注意的是,如果使用background-image属性动态设置背景图,截取后生成的图片会很模糊,所以使用<img>标签设置背景:

以上就是本次使用html2canvas的内容,欢迎大家点赞评论。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值