实现效果
Poster.vue
<template>
<div class="content-item">
<div class="player-bottom-panel">
<!-- 要生成海报的 -->
<div
class="creat-give-poster"
ref="creatGivePoster"
:style="{ backgroundImage: 'url(' + posterList.currentBg + ')' }"
>
<div class="poster-info">
<div class="poster-avatar">
<van-image :src="posterList.imageUrl" />
</div>
<div class="qr-icon">
<vue-qr
:logo-src="config.logo"
:text="config.value"
:margin="0"
:size="90"
class="player-bottom-panel-qrcode"
style="opacity: 0"
/>
<p class="poster-more">{{ posterList.pintitle }}</p>
<p class="poster-more">{{ posterList.name }}</p>
</div>
</div>
<!-- <i class="van-icon van-icon-close" @click="hideImg"></i> -->
</div>
<!-- 海报图片 -->
<div v-if="isMargin" class="share-give-poster">
<img class="poster-img" :src="imgUrl" alt="poster" />
<!-- 保存海报按钮 -->
<div class="saveBtn-box-m">
<van-button
v-if="isShow"
type="primary"
size="mini"
@click="saveImg"
class="save-btn"
>
{{ $t("scan.the.qr.code.press") }}
</van-button>
<div
@click="saveImgLauch"
v-if="posterList.showLauch"
class="imgLauch"
>
<img src="../../assets/images/baocun_icon@2x.png" alt="" />Save
</div>
<div
class="link imgLauch"
v-if="posterList.showLauch"
@click="copyWebsite"
>
<img src="../../assets/images/daochu_icon@2x.png" alt="" />Link
</div>
</div>
<i class="van-icon van-icon-close" @click="hideImg"></i>
</div>
<!-- 遮罩 -->
<div class="shadow-box"></div>
</div>
</div>
</template>
<script>
import VueQr from "vue-qr";
import html2canvas from "html2canvas";
import {
saveSponsorPersonInfo,
getSysConfig,
base64ToMultipartBody,
} from "@/api/member";
export default {
name: "Poster",
components: { VueQr },
props: {
posterList: {
type: Object,
default: () => ({
avatarImgUrl: "",
currentBg: "",
pintitle: "",
checked: null,
imageUrl: "",
name: "",
radio: "",
showLauch: "",
}),
},
},
data() {
return {
//二维码参数
config: {
value: window.location.href, //显示的值、跳转的地址
logo: "", //中间logo的地址
},
imgUrl: "", //最后转化出来的图片base64地址
isMargin: false,
isShow: false, //阴影和下载按钮的控制
isLoading: false,
coverImgUrl: "",
vcardDistributor: {},
website: "",
websitePrefix: "",
};
},
watch: {},
created() {},
mounted() {
this.getPoster();
this.vcardDistributor = JSON.parse(
localStorage.getItem("vcardDistributor")
);
this.website = this.vcardDistributor.website;
this.getShareLink();
},
activated() {},
methods: {
hideImg() {
this.isMargin = false;
this.isShow = false;
this.$emit("update:isPosterLoading", false);
this.$emit("update:isPoster", false);
window.location.reload();
},
getShareLink() {
let cc = this.$store.state.user.distributorInfo.companyCode,
key = "vip.share.website.url";
getSysConfig(key, cc).then((res) => {
if (res.code === 0) {
this.websitePrefix = res.data[key];
}
});
},
getPoster() {
if (!this.websitePrefix || !this.website) {
this.getShareLink();
if (!this.vcardDistributor) {
this.vcardDistributor = JSON.parse(
localStorage.getItem("vcardDistributor")
);
}
this.website = this.vcardDistributor.website;
// 使用 setTimeout 确保异步操作完成后再执行 getPoster
setTimeout(this.getPoster, 100);
return;
}
this.isLoading = true;
if (this.posterList.showLauch) {
if (this.posterList.radio === "1") {
this.config.value = this.websitePrefix + this.website;
} else if (this.posterList.radio === "2") {
this.config.value =
this.websitePrefix + this.website + "&redirectPage=mypage";
}
}
setTimeout(() => {
//插件只能解决当前可视区域的 因此截图生成前需要先滚动到顶部 解决浏览器出现滚动条时截图不全bug
window.pageYoffset = 0;
document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
let shareContent = this.$refs.creatGivePoster; // 需要截图的包裹的(原生的)DOM 对象
let width = shareContent.offsetWidth; // 获取dom 宽度
let height = shareContent.offsetHeight; // 获取dom 高度
let canvas = document.createElement("canvas"); // 创建一个canvas节点
let scale = 1; //定义任意放大倍数 支持小数
canvas.width = width * scale; // 定义canvas 宽度 * 缩放
canvas.height = height * scale; // 定义canvas高度 *缩放
canvas.getContext("2d").scale(scale, scale); // 获取context,设置scale
let opts = {
scale: scale, // 添加的scale 参数
canvas: canvas, // 自定义 canvas
// logging: true, // 日志开关,便于查看html2canvas的内部执行流程
width: width, // dom 原始宽度
height: height,
windowWidth: document.body.scrollWidth, // 解决浏览器出现滚动条时截图不全bug
windowHeight: document.body.scrollHeight, // 解决浏览器出现滚动条时截图不全bug
useCORS: false, // 【重要】开启跨域配置
backgroundColor: null,
removeContainer: false,
};
this.$emit("update:isPosterLoading", true);
this.$nextTick(() => {
html2canvas(shareContent, opts)
.then((canvas) => {
this.$emit("update:isPosterLoading", false);
let context = canvas.getContext("2d");
// 【重要】关闭抗锯齿
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
// 【重要】默认转化的格式为png,也可设置为其他格式
this.imgUrl = canvas.toDataURL("image/png");
const formData = {
base64: this.imgUrl,
};
// base64转图片
base64ToMultipartBody(formData).then((res) => {
if (res.code === 0) {
this.coverImgUrl = res.data;
}
});
})
.catch(() => {
this.$emit("update:isPosterLoading", false);
});
});
this.isMargin = true;
this.isShow = true;
this.isLoading = false;
}, 0);
},
saveImg() {
// 移动端不进行保存操作
// 引入插件
if (!this.is_mobile) {
let FileSaver = require("file-saver");
// 保存base64图片 也有保存canvas方法 详情看文档
FileSaver.saveAs(this.imgUrl, "poster");
}
const infoList = {
coverUrl: this.imgUrl,
storeName: this.vcardDistributor.storeName,
website: this.vcardDistributor.website,
};
saveSponsorPersonInfo(infoList)
.then((res) => {
console.log(res);
if (res.code == 0) {
this.$toast.success("保存成功");
this.vcardDistributor.coverUrl = this.imgUrl;
localStorage.setItem(
"vcardDistributor",
JSON.stringify(this.vcardDistributor)
);
this.$store.dispatch(
"user/setVcardDistributorData",
this.vcardDistributor
);
} else {
this.$toast.fail("保存失败");
}
})
.catch((err) => {
this.$toast.fail("保存失败");
});
},
saveImgLauch() {
if (!this.is_mobile) {
let FileSaver = require("file-saver");
// 保存base64图片 也有保存canvas方法 详情看文档
FileSaver.saveAs(this.imgUrl, "poster");
}
},
copyWebsite() {
console.log(this.coverImgUrl);
window.location.href = this.coverImgUrl;
},
},
updated() {},
};
</script>
<style lang="scss" scoped>
.content-item {
.creat-give-poster {
background: url("../../assets/images/bg_photo@2x.png") no-repeat;
background-size: cover;
width: 6.5rem;
height: 10rem;
color: #fff;
text-align: center;
position: absolute; /* 不能fixed 否则就挂了 */
top: 1rem;
left: 0;
right: 0;
margin: auto;
z-index: -200;
.poster-avatar {
margin: 0 auto;
text-align: center;
.van-image {
height: 6.5rem;
margin-top: 0.5rem;
}
}
.qr-icon {
display: flex;
align-items: center;
padding: 0.3rem;
box-sizing: border-box;
justify-content: space-between;
position: absolute;
bottom: 0;
.poster-more {
font-size: 0.6rem;
padding: 0.2rem;
word-break: break-all;
max-height: 2.5rem;
overflow: hidden;
}
.player-bottom-panel-qrcode {
border: 0.1rem solid #fff;
box-sizing: border-box;
}
}
}
.share-give-poster {
width: 100%;
height: 100%;
margin-top: 1rem;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 500;
img {
display: block;
width: 6.5rem;
height: 10rem;
margin: 0 auto;
margin-top: 0.6rem;
}
.van-icon-close {
position: absolute;
top: 0rem;
right: 0rem;
text-align: center;
font-size: 24px;
color: #fff;
}
}
.saveBtn-box {
position: absolute;
right: -3.85rem;
bottom: 0;
}
.saveBtn-box-m {
position: absolute;
bottom: 1rem;
left: 50%;
transform: translate(-50%, 0);
.imgLauch {
display: flex;
width: 3.21rem;
height: 0.97rem;
border-radius: 0.3rem;
border: 1px solid #000;
justify-content: center;
align-items: center;
font-size: 0.34rem;
margin: 0.03rem;
img {
width: 0.41rem;
height: 0.41rem;
margin: 0.24rem;
}
}
.link {
background-color: #0554b8;
color: #fff;
border: none;
padding: 0.01rem;
}
}
.el-button--medium {
margin: 0 auto;
display: block;
padding: 0.1rem 0.385rem;
font-size: 0.25rem;
}
.shadow-box {
background: rgba(0, 0, 0, 0.7);
position: fixed;
width: 100%;
height: 100vh;
left: 0;
top: 0;
z-index: 66;
}
}
</style>
使用
<template>
<Poster
:isPosterLoading.sync="isPosterLoading"
:is_mobile="is_mobile"
:posterList="posterList"
:isPoster.sync="isPoster"
v-if="isPoster"
/>
</template>
<script>
import Poster from "@/components/Poster";
export default {
data() {
return {
posterList: {
avatarImgUrl: "",
currentBg: "",
pintitle: "",
checked: "",
imageUrl: "",
},
}
}
components: {
Poster
}
}
</script>