VUE中:printJS使用,附带JsBarcode条码生成器,网页转图片html2canvas,base64上传保存处理,二维码生成库qrcode,二维码/条码扫描识别,domtoimage

本文介绍了在Vue项目中使用printJS进行网页打印,结合JsBarcode生成条码,以及如何处理html2canvas的跨域和CSS样式问题。在遇到html2canvas限制时,转向使用domtoimage转换网页为图片,并讨论了二维码生成库qrcode和扫描识别库Quagga的使用方法。同时,文章提供了解决打印背景色丢失问题的方案。

官网
JsBarcode官网
JsBarcode的GitHub-WIKI
我的项目需求只需要将配置好的HTML与CSS样式传入进去就好,较为简单。

九个月后html2canvas出现线上问题 设置了跨域但依然出现跨域问题,尝试解决失败,换用domtoimage

安装: npm install print-js --save
使用: import print from 'print-js'

printJS函数封装:

print (ref, title, style, type, jsonData, borderHeadStyle, gridStyle, css) {
         printJS({
            printable: ref,// 要打印内容的id
            type: type || 'html', // 可以打印html,img详细的可以在官方文档
            style: style || '@page{size:auto;margin: 0cm 1cm 0cm 1cm;}', // 打印的内容是没有css样式的,此处需要string类型的css样式
            header: title || null,https://printjs.crabbly.com/中查询
            headerStyle: 'font-size:6px;font-weight:600;text-align:center;padding:15px 0 10px 0;', // 标题设置
            properties: jsonData || [], // json数据元
            gridHeaderStyle: borderHeadStyle || 'font-size:6px;font-weight:400;height:40px;line-height:40px;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', // json格式表头样式
            gridStyle: gridStyle || 'font-size:1px;font-weight:200;border: 1px solid #ccc;padding:3px 5px 3px 5px;text-align:center;', // json各式表哥央视
            scanStyles: false, // 不适用默认样式
           repeatTableHeader: false, // 打印json表头只显示在第一页
            css: css || null // css url
        });
     },

但在实际开发过程中遇到了:直接传入DOM节点 CSS样式全部失效的问题,由于显示内容多,自己手写JS会非常麻烦。故引入第二个库,网页转图片:
安装:npm install --save html2canvas
使用:import html2canvas from 'html2canvas';
使用代码:

html2canvas(this.$refs.printContent).then(canvas => {
            let dataURL = canvas.toDataURL('image/png');
            this.imgUrl = dataURL;
            printJS({
                printable: dataURL,
                type: 'image'
            });
        });

若打印的图片不清晰请戳这里
或这里
🔺🔺html2canvas只适用于页面截图,若是需要将元素隐藏再父元素中点击按钮打印而不是跳转新页面的话,隐藏元素会导致不能转换图片
🔺🔺且不支持部分CSS样式(例如float浮动样式)。当元素内容打印不出来时注意在这里插入图片描述也可以选择生成二维码而不是条码:qrcode下载源:参考案例在项目文件夹内执行:npm install --save qrcode全局安装:npm install -g qrcode在需要的页面引入 import QRcode from "qrcode";使用:

//canvas是HTML的绘图标签,省略返回新绘图
//sample text:输入你需要转换为二维码的字符串,可以是网址链接
//function在执行完成时的回调函数
QRCode.toCanvas(canvas, 'sample text', function (error) {
  if (error) console.error(error)
  console.log('success!');
})

开发代码实例:


        async createImg(){
            await this.$nextTick();// this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
            this.imgUrl = await this.makeImg();
            printJS({
                printable: this.imgUrl,
                type: 'image'
            });
            console.log(this.imgUrl);
        },
       makeImg(){
            return new Promise(resolve=>{
                html2canvas(this.$refs.tab1, {
                    scale: 2,
                    dpi: 2000,
                    height: this.$refs.tab1.clientHeight + 5, // dom 原始宽度
                    width: this.$refs.tab1.clientWidth + 5, // dom 原始宽度
                    scrollY: 0, // 偏移值
                    scrollX: 0,
                    useCORS: true// 跨域
                }
                ).then(canvas => {
                    let dataURL = canvas.toDataURL('image/png');
                    resolve(dataURL);
                }).catch(err => {
                    console.log(err);
                });
            })
        },

开发代码实例2:(获取UeEditor富文本编辑器-即iframe标签,中的内容并保存为图片,且将base64转为file对象并fromData后保存)

        //找到DOM创建图片
        async createImg(whichOne){
            return new Promise(resolve=>{
                let view = document.getElementById(whichOne);
                let iframe = view.children[0].children[0].getElementsByClassName('edui-editor-iframeholder edui-default')[0].children[0].contentWindow.document;
                // await this.$nextTick();// this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
                resolve(this.makeImg(iframe.getElementsByClassName('view')[0].children[1].children[0]))  
            })
        },
        //html2canvas生成图片
       makeImg(printContent){
            return new Promise(resolve=>{
                html2canvas(printContent, {
                    scale: 2,
                    dpi: 2000,
                    height: printContent.clientHeight + 5, // dom 原始宽度
                    width: printContent.clientWidth + 5, // dom 原始宽度
                    scrollY: 0, // 偏移值
                    scrollX: 0,
                    useCORS: true// 跨域
                }).then(canvas => {
                    let dataURL = canvas.toDataURL('image/png');
                    console.log(dataURL);
                    resolve(dataURL);
                }).catch(err => {
                    console.log(err);
                });
            })
        },       
        //将生成的图片转为可上传服务器的fromdata对象
        async base64ImgtoFile(data) {
            return new Promise(resolve=>{
        	//新建formData对象
	            var form=document.forms[0];  
	            var formData = new FormData(form);
	
				//将base64图片数据转二进制后保存为file对象
	            let filename = this.revtimeToString(new Date)+'.png'
	            var arr = data.split(','), mime = arr[0].match(/:(.*?);/)[1],
	                bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
	            while(n--){
	                u8arr[n] = bstr.charCodeAt(n);
	            }
	            let file = new File([u8arr], filename, {type:mime});
	
				//包装file对象用于上传
	            formData.append("uploadFile",file)
	            resolve(res.data)   
            })
        },
        //保存对应图片并上传的按钮触发方法  一键保存上传  
        saveImg(){
        	//printContent  要保存的图片DOM
			let data = await this.base64ImgtoFile(await this.createImg('printContent')));
			//接口上传代码省略
			.....
		}
        

二维码、条码扫描识别(拍照或上传图片,非实时扫描)
可直接使用:

<template>
    <div class="mt46 input-cells">
        <div class="flex l-center a-left">
            <div
                class="qr-item mr5 ml5"
                v-show="false">
                <img
                    src="#"
                    width="20"
                    height="20"
                    alt="">
                <input
                    v-if="isUploadBarCode"
                    class="qr-item-input"
                    @change="toQR"
                    type="file"
                    accept="image/*"
                    capture="camera">
            </div>
        </div>
    </div>
</template>
<script type="text/ecmascript-6">
import Quagga from 'quagga';
export default {
    name: '',
    data () {
        return {
            queryParams: {
                vin: null
            },
            isUploadBarCode: true // 控制销毁
        };
    },
    mounted () {
    },
    methods: {
        // 图片 识别 条形码
        toQR (e) {
            const that = this;
            const file0 = e.target.files[0];
            // console.log('toQR()-file0', file0)
            this.isUploadBarCode = false;
            Quagga.decodeSingle({
                inputStream: {
                    name: 'image',
                    type: 'ImageStream',
                    // size: 1600, // 这里指定图片的大小,需要自己测试一下
                    singleChannel: false
                },
                locator: {
                    patchSize: 'medium',
                    halfSample: false
                },
                numOfWorkers: 1,
                decoder: { // ean_reader 这里指定ean条形码,就是国际13位的条形码   code39    code_128
                    readers: ['code_128_reader']
                },
                // readers: ['code_128_reader'],
                locate: true,
                src: URL.createObjectURL(file0)
            }, (result) => {
                console.log('Quagga()-result', result);
                // let code = result.codeResult.code
                if (result && result.codeResult) {
                    that.queryParams.vin = result.codeResult.code;
                    // 执行 页面请求刷新
                } else {
                    that.queryParams.vin = null;
                    console.warn('识别失败,请手动输入');
                }
                this.isUploadBarCode = true;
            });
        }
    }
};
</script>

<style scoped>
  .input-cells{
    display: flex;
    justify-content:space-between;
    align-items: center;
    position: relative;
    background-color: #fff;
    overflow: hidden;
    padding: .06rem .15rem;
    height: .32rem;
    line-height: .32rem;
    font-size: .14rem;
  }
  .input-label{
    margin-left: 0;
    font-size: .14rem;
    width: .9rem;
  }
  .input-cells>input{
    font-size: .14rem;
    text-align: right;
  }
  .input-cells>img{
    width: .06rem;
    height: .1rem;
    margin-right: .03rem;
  }
  .qr-item{
    width: .3rem;
    height: 100%;
    background-size: 120%;
    position: relative;
    overflow: hidden;
    border: 1px solid #dae7f6;
    background-color: #f5f5f5;
  }
  .qr-item-input{
    opacity: 0;
    width: 100%;
    height: 100%;
    background-size: 100%;
    position: absolute;
    top: 0;
    left: 0;
  }
  /*common*/
  .flex{
    display: flex;
  }
  .a-center{
    align-items: center;
  }
  .f-fl{
    float: left;
  }
  .ml5{
    margin-left: .05rem;
  }
  .mr10{
    margin-right: .1rem;
  }
</style>

实际开发踩坑:
注意使用Quagga库,调用摄像头拍照扫描时,最好将二维码下方的文字清除,否则会非常影响识别率
在这里插入图片描述
html2canvas踩坑:

完美解决html导出且分页 解决图片显示不全问题
https://blog.youkuaiyun.com/qq_40044912/article/details/108319294

普通的打印方式

//curPrint是要打印html元素内容的id
        let subOutputRankPrint = document.getElementById('curPrint');
        let newContent = subOutputRankPrint.innerHTML;
        let oldContent = document.body.innerHTML;
        document.body.innerHTML = newContent;
        window.print();
        document.body.innerHTML = oldContent;
        // window.location.reload();

解决打印背景色丢失问题

		//解决内容分页问题
		page-break-before:always;
		//解决火狐浏览器打印
		print-color-adjust: exact;
		color-adjust: exact;
		//webkit 为Google Chrome、Safari等浏览器内核
		-webkit-print-color-adjust: exact;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

跳动的世界线

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值