palc-newyear2024/src/components/Result.vue
2025-04-23 14:47:51 +08:00

405 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { gsap } from "gsap";
import { debounceTap } from "@/plugins";
import { useMainStore } from "@/store";
import { Toast } from "vant";
import QRCode from "qrcode";
import { reactive } from "vue";
// 页面配置初始化
const emit = defineEmits(["ResultPage"]);
const userStore = useMainStore();
const posterId = ref(userStore.posterId); //海报背景id111
console.log('海报id', posterId.value);
// 二维码坐标
const eqcodePosition = [
{w:750,h:2107,x: 527, y: 1882},
{w:750,h:2111,x: 529, y: 1873},
{w:750,h:2194,x: 527, y: 1973},
{w:750,h:2045,x: 527, y: 1824},
{w:750,h:2194,x: 527, y: 1979},
]
const posterImgList = reactive([
new URL(`../assets/images/result/poster-1.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-2.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-3.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-4.jpg`, import.meta.url).href,
new URL(`../assets/images/result/poster-5.jpg`, import.meta.url).href,
])
// 生成二维码逻辑
const eqcodePic = ref();
onMounted(async () => {
// 执行任务队列
await executeTasks();
});
// 这是新加的函数封装异步任务
const executeTasks = async () => {
console.log("二维码生成中...");
// 生成二维码
const eqCodeUrl = import.meta.env.VITE_URL;
eqcodePic.value = await QRCode.toDataURL(eqCodeUrl);
console.log("生成海报中...");
// 生成海报
console.log('pid', posterImgList[posterId.value - 1]);
if (posterImgList[posterId.value - 1] && eqcodePic.value) {
posterCreate(
{ width: 750, height: eqcodePosition[posterId.value-1].h },
[
{ name: "bg", src: posterImgList[posterId.value - 1], pos: { w: 750, h: eqcodePosition[posterId.value-1].h, x: 0, y: 0 } },
{ name: "eqcode", src: eqcodePic.value, pos: { w: 187, h: 187, x: eqcodePosition[posterId.value-1].x, y: eqcodePosition[posterId.value-1].y } },
]
);
} else {
Toast.fail({ message: '生成失败' })
emit("ResultPage", { action: 'hide' })
}
};
const showPoster = () => {
gsap.to(".posterPop", {
duration: 0.3,
autoAlpha: 1,
});
gsap.from(".cls-btn-box", {
duration: 0.7,
scale: 1.2,
autoAlpha: 0,
});
gsap.from(".poster-box", {
duration: 0.7,
scale: 0.6,
autoAlpha: 0,
});
gsap.from(".save-tips", {
duration: 0.7,
scale: 0.7,
autoAlpha: 0,
delay: 0.3
});
gsap.from(".go-draw", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay: 0.5
});
gsap.from(".go-share", {
duration: 0.7,
y: -30,
autoAlpha: 0,
delay: 0.7
});
}
// 去抽奖
const goDraw = (event) => {
let e = event.target;
debounceTap(e, () => {
if (userStore.hasDraw) {
emit("ResultPage", { action: "showDraw" });
} else {
Toast("今日暂无抽奖机会");
}
});
};
// 隐藏海报弹窗
const hidePop = (event) => {
let e = event.target;
debounceTap(e, () => {
gsap.to(".posterPop", {
duration: 0.5, autoAlpha: 0,
onComplete: () => {
emit('ResultPage', { action: 'hide' })
}
});
});
};
const hide =(event)=>{
let e = event.target;
debounceTap(e, () => {
gsap.to(".posterPop", {
duration: 0.5, autoAlpha: 0,
onComplete: () => {
emit('ResultPage', { action: 'showQuestion' })
}
});
});
}
// 展示分享
const goShare = (event) => {
let e = event.target;
debounceTap(e, () => {
gsap.to(".sharePop", { duration: 0.5, autoAlpha: 1 });
});
};
// 隐藏分享提示
const hideShare = () => {
gsap.to(".sharePop", { duration: 0.5, autoAlpha: 0 });
};
// 海报生成
const posterCreate = (option, imageArr) => {
let posterUrl = ''
const { width, height } = option
Toast.loading({
message: '海报生成中',
duration: 0,
forbidClick: true
})
let mycanvas = document.createElement('canvas') // 创建一个canvas画布元素
let ctx = mycanvas.getContext('2d')
mycanvas.style.width = `${width}px`; //设置canvas的宽
mycanvas.style.height = `${height}px`; //设置canvas的高
mycanvas.width = width
mycanvas.height = height
//Promise对象加载资源
let loader_p = [];
imageArr.map((item) => {
const _p = new Promise(resolve => {
const img = new Image();
img.crossOrigin = 'Anonymous'
img.onload = () => {
resolve(img)
};
img.src = item.src;
});
loader_p.push(_p);
})
//Promise的.all方法当所有预加载的图像加载好的回调函数
Promise.all(loader_p)
.then(imgList => {
console.log('imgList', imgList);
// 图片素材遍历绘制
imgList.map((item, index) => {
ctx.drawImage(item, imageArr[index].pos.x, imageArr[index].pos.y, imageArr[index].pos.w, imageArr[index].pos.h); //原生canvas的绘制图片方法直接百度搜索 `js drawImage`查看方法的参数
})
//海报绘制完 ,转成图片对象
return mycanvas.toDataURL('image/jpeg', 1);
})
.then(baseURL => {
//返回的图片地址就是最后海报的地址可以放在DOM显示
let posterImg = document.querySelector('#posterSrc')
posterImg.src = baseURL
setTimeout(() => {
// 展示海报
showPoster();
Toast.success({ message: '生成成功!' })
}, 500)
})
.catch(error => {
console.error("生成海报失败");
gsap.to(".posterPop", {
duration: 0.5,
autoAlpha: 0,
onComplete: () => {
emit('ResultPage', { action: 'hide' })
}
});
Toast.fail({ message: '生成失败,请重试!' });
});
// return posterUrl
}
</script>
<template>
<div class="posterPop" @touchmove.prevent>
<div class="poster-bg"></div>
<div class="poster-container">
<div class="cls-btn-box">
<div class="cls-btn" @click="hidePop($event)"></div>
</div>
<div class="poster-box" :class="'poster-box-' + posterId">
<div class="poster" :class="'poster-' + posterId">
<img id="posterSrc" src="" alt="" srcset="">
</div>
<div class="poster-cls-btn" @click="hide($event)"></div>
</div>
<div class="save-tips">*长按保存海报</div>
<div class="btn-box">
<div class="go-draw" @click="goDraw($event)"></div>
<div class="go-share" @click="goShare($event)"></div>
</div>
</div>
</div>
<!-- 分享提示 -->
<div class="sharePop" @click="hideShare">
<div class="tips-pic"></div>
<div class="tips-text">点击右上角分享给你的好友</div>
</div>
</template>
<style lang="scss" scoped>
.posterPop {
@include pos(100%, 1624px, 0px, 0px);
overflow: hidden;
background: linear-gradient(135deg, #d6d1ca, #e5dccf);
visibility: hidden;
.poster-bg {
@include pos(750px, 1624px, 0px, 0px);
// transform: translateY(-50%);
@include bg_pos("index/bg.jpg");
}
.poster-container {
@include pos(750px, 1624px, 0px, 0px);
// transform: translateY(-50%);
@include flexCen();
background-color: rgba($color: #000000, $alpha: 0.3);
.cls-btn-box {
width: 617px;
display: flex;
justify-content: flex-end;
// .cls-btn {
// @include box(49px, 49px);
// @include bg_pos("question-list/cls-btn.png");
// margin-right: -20px;
// }
}
.save-tips {
font-size: 20px;
line-height: 20px;
margin-top: 20px;
color: #9e4b00;
letter-spacing: 2px;
}
.poster-box {
@include box(713px, 995px);
margin-top: 20px;
overflow: hidden;
position: relative;
.poster-cls-btn{
@include pos(53px, 53px,660px,10px);
@include bg_pos("result/cls-btn.png");
}
.poster {
@include box(100%, 100%);
overflow: hidden;
#posterSrc {
@include box(100%, 100%);
opacity: 0;
}
}
.poster-1 {
@include bg_pos("result/card-1.png");
}
.poster-2 {
@include bg_pos("result/card-2.png");
}
.poster-3 {
@include bg_pos("result/card-3.png");
}
.poster-4 {
@include bg_pos("result/card-4.png");
}
.poster-5 {
@include bg_pos("result/card-5.png");
}
}
.poster-box-1{
@include box(713px, 995px);
}
.poster-box-2{
@include box(711px, 1010px);
}
.poster-box-3{
@include box(713px, 995px);
}
.poster-box-4{
@include box(713px, 995px);
}
.poster-box-5{
@include box(713px, 995px);
}
.btn-box {
@include box(550px, 104px);
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
.go-draw {
@include box(257px, 104px);
@include bg_pos("result/go-draw-btn.png");
}
.go-share {
@include box(274px, 95px);
@include bg_pos("result/go-share-btn.png");
}
}
}
}
.sharePop {
@include fixed();
background-color: rgba($color: #000000, $alpha: 0.54);
visibility: hidden;
.tips-pic {
@include pos(100px, 100px, 600px, 180px);
@include bg_pos("result/share-tips.svg");
stroke: #ffffff;
}
.tips-text {
font-size: 25px;
@include pos(750px, 100px, 0px, 300px);
color: #ffffff;
text-align: right;
}
}
</style>