插件
- qrcode2
- html2canvas(修改版)
链接:https://pan.baidu.com/s/1MZLo8WEAjSoPg8iol7-a-A
提取码:ksvc
效果展示
安装qrcodejs2
yarn add qrcodejs2 -S
引入html2canvas
在项目js入口文件引入html2canvas,如下图
HTML部分
<template>
<div id="app">
<!-- 按钮 -->
<button @click="showDiglog">点我</button>
<!-- 海报模板 -->
<div ref="dialog" class="dialog">
<img
id="bg"
src="https://res.miaocode.com/dragon-boat/posterimgbg.jpg"
alt=""
/>
<img
id="head"
src="https://res.miaocode.com/54efb4cd-0d7a-4dd3-af8f-5e7f41d39158.jpg"
/>
<div id="qrcode" ref="qrcode"></div>
</div>
<!-- 生成的海报弹框和图片 -->
<div
v-show="dialogVisible"
class="dialog-layer"
@click="hideDialog($event)"
>
<img ref="saveImage" class="save-image" src="" alt="" />
</div>
</div>
</template>
Script部分
<script>
import QRCode from 'qrcodejs2';
export default {
name: 'SaveImage',
// eslint-disable-next-line vue/no-unused-components
components: { QRCode },
data() {
return {
dialogVisible: false,
link: 'https://www.baidu.com/',
};
},
mounted() {
// 清空二维码
this.$refs.qrcode.innerHTML = '';
// 生成二维码
this.$nextTick(function () {
// 根据html的fontSize动态计算二维码宽高
const htmlFontSize = getComputedStyle(window.document.documentElement)[
'font-size'
];
const w = parseInt(htmlFontSize) * 3;
const h = parseInt(htmlFontSize) * 3;
this.qrcode(w, h, this.link, 'canvas');
});
},
methods: {
/**
* @description 生成二维码
* @param {number} qWidth 宽度
* @param {number} qHeight 高度
* @param {string} qText 二维码内容(跳转连接)
* @param {string} qRender 渲染方式(有两种方式 table和canvas,默认是canvas)
*/
qrcode(qWidth, qHeight, qText, qRender) {
new QRCode(this.$refs.qrcode, {
width: qWidth,
height: qHeight,
text: qText,
render: qRender,
correctLevel: QRCode.CorrectLevel.L,
});
},
// 显示弹框
showDiglog() {
//二维码初始化 点击一次添加一个二维码
const dialog = this.$refs.dialog;
const saveImage = this.$refs.saveImage;
html2canvas(dialog, {
useCORS: true,
logging: true,
width: dialog.offsetWidth,
height: dialog.offsetHeight,
scale: window.devicePixelRatio || 1,
}).then(canvas => {
const dataUrl = canvas.toDataURL('image/png', 1.0);
console.log('dataUrl', dataUrl);
saveImage.setAttribute('src', dataUrl);
this.dialogVisible = true;
});
},
// 隐藏弹框
hideDialog(e) {
const saveImage = this.$refs.saveImage;
if (saveImage) {
//判断如果不是当前节点就隐藏弹窗
if (!saveImage.contains(e.target)) {
this.dialogVisible = false;
}
}
},
},
};
</script>
Style部分
<style scoped lang="scss">
.dialog {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 15rem;
height: 26.68rem;
opacity: 0;
#bg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
#head {
width: 3.2rem;
height: 3.2rem;
position: absolute;
left: 50%;
margin-left: -1.6rem;
bottom: 11rem;
border-radius: 1.5rem;
}
#qrcode {
position: absolute;
bottom: 2rem;
right: 1.8rem;
border-radius: 0.2rem;
padding: 0.2rem;
background: white;
display: flex;
align-items: center;
justify-content: center;
transform: scale(0.8);
}
}
.dialog-layer {
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
background: rgba(0, 0, 0, 0.75);
z-index: 10;
.save-image {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 15rem;
height: 26.68rem;
z-index: 100;
}
}
</style>
注意事项
- 模板不能使用背景图片
- 定位元素居中使用transform无效,居中可以使用margin-left: -50%