先看看整个案例成效的效果
本案例是uniapp小程序,用到uview框架。
需求描述:
进入页面的时候循环生成多张,并以swiper的方式展示出来,以供使用。
下面我们进入正题
需要用到的插件:https://ext.dcloud.net.cn/plugin?id=1480
可以到插件市场去下载和看使用教程,作者非常贴心,插件还提供了海报样式代码生成的工具,
可以根据自己的需要布局样式生成相应的JSON样式,然后再稍微调整一下细节,简直不要太方便。
自己去看和使用我就不多说了。
生成海报页面代码
<template>
<view class="wrap">
<u-navbar :custom-back="backPage" title-size="36" title-color="#333" :titleBold="true" title="海报分享"></u-navbar>
<!-- 固定定位在看不见的地方用于canvas绘制 -->
<view class="canvas-box">
<canvas canvas-id="shareIndex" style="width:750px;height:1332px" />
</view>
<!-- 海报盒子 -->
<view class="poster-box" >
<swiper class="swiper" previous-margin='95rpx' v-if="showPoster" next-margin='95rpx' current="0" @change="changeSwiper">
<swiper-item class="swiper-item" v-for="(item,index) in posterLsit" :key="index">
<view class="img-box" :class="{'small':index!==activeIndex}">
<image v-if="item&&item!=''" class="img" :src='item' />
</view>
</swiper-item>
</swiper>
</view>
<!-- 分享工具栏 -->
<view class="u-flex u-row-between btn-box">
<view class="poster-btn u-reset-button u-flex u-col-center u-row-center" @click="savePoster">
<image src="../../static/img/userCenter/icon-share.png" style="width:26rpx;height:26rpx;"
mode="scaleToFill"></image>
<text class="mgl-5">保存海报</text>
</view>
<button class="share-btn u-reset-button u-flex u-col-center u-row-center" open-type="share">
<image src="../../static/img/userCenter/icon-link.png" style="width:26rpx;height:26rpx;"
mode="scaleToFill"></image>
<text class="mgl-5">分享好友</text>
</button>
</view>
</view>
</template>
登录状态和share.js混入函数可以先忽略,最主要的是看获取二维码之后的for循环await promise生成多张海报(注意不要用foreach,foreach中的await有问题),生成海报的样式可以自己去生成和调整
<script>
import { mapState } from 'vuex';
import {
SHARE_MIXIN
} from '@/utils/share.js'
export default {
mixins: [SHARE_MIXIN],
data() {
return {
list: [{
image: 'https://dmj-mall.oss-cn-shenzhen.aliyuncs.com/v70/shop/poster1.png',
}, {
image: 'https://dmj-mall.oss-cn-shenzhen.aliyuncs.com/v70/shop/poster2.png',
}],
shareData: false,
shareImg: '',
showShareImg: false,
choosePosterBgImg: '',
posterLsit: [],
activeIndex: 0, //轮播图索引
showPoster: false,
// 全屏loading動畫显示隐藏
pageLoading:true
}
},
onLoad() {
// 首页数据分享构造
this.SHARE_TO_FRIENDS_DATA = { //已经做了minxin函数,需要调用分享直接写在data里面
title: '萌宝计划,海量大牌母婴好货,超低折扣,每日上新,一起来抢购吧~',
path: 'H5/index?inviteCode=' + (this.USERINFO ? this.USERINFO.inviteCode : ''),
imageUrl: 'https://dmjmicro.oss-cn-shenzhen.aliyuncs.com/mengbao/share-cover.jpg',
desc: '萌宝计划,海量大牌母婴好货,超低折扣,每日上新,一起来抢购吧~',
content: '萌宝计划,海量大牌母婴好货,超低折扣,每日上新,一起来抢购吧~',
}
this.getQrCode()
},
computed: {
...mapState(['USERINFO'])
},
methods: {
changeSwiper(e) {
this.activeIndex = e.detail.current
this.circular1 = true
},
// 获取小程序二维码,下载之后再进行绘制
async getQrCode() {
let qrCode = await this.$api_pt.Goods.getQrcode({
page: 'H5/index',
scene: this.USERINFO.inviteCode,
IS_LOADING:false
}).then(res => {
return res.data
console.log('小程序码', qrCode);
})
let _this = this
uni.downloadFile({
url: qrCode,
async success(res) {
console.log('下载成功菊花码成功', res.tempFilePath);
for (let i = 0; i < _this.list.length; i++) {
await _this.drawPoster(_this.list[i].image, res.tempFilePath).then(
resPoster => {
console.log('绘制返回的海报', resPoster);
_this.posterLsit.push(resPoster)
})
}
_this.showPoster = true
// 隐藏加载动画
_this.pageLoading=false
},
fail(err) {
console.log('下载失败', err)
}
})
},
drawPoster(img, code) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: img,
success: res => {
const ctx = uni.createCanvasContext('shareIndex')
ctx.clearRect(0, 0, 750, 1332)
ctx.drawImage(res.tempFilePath, 0, 0, 750, 1332)
this.drawCircle({
ctx: ctx,
img: code,
avatarX: 750 / 2 - 129,
avatarY: 1000,
imgWidth: 240,
imgHeight: 240,
num: 18
})
ctx.draw(false, () => {
//分享图片
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: 750,
height: 1332,
destWidth: 1080,
destHeight: 1918,
fileType: 'jpg',
quality: 0.8,
canvasId: 'shareIndex',
success: (res) => {
// that.imageUrl[index] = res.tempFilePath
console.log('绘制成功', res.tempFilePath);
resolve(res.tempFilePath)
},
fail: (err) => {
reject(err)
}
})
})
},
fail(err) {
console.log(err)
console.log('绘制失败', err);
// this.app.loading(false)
}
})
})
},
drawCircle({ ctx, img, avatarX, avatarY, imgWidth, imgHeight, num = 0 }) {
//画布截取圆形区域,ctx canvas对象,img 需截取图像,avatarX 图像在画布的水平位置,avatarY 图像在画布的垂直位置,imgWidth 图像宽度,imgHeight 图像高度, num 多添加的空白填充
ctx.save()
ctx.beginPath() //开始绘制
ctx.fillStyle = '#fff'
ctx.arc(
(imgWidth + num) / 2 + avatarX,
(imgHeight + num) / 2 + avatarY,
(imgWidth + num) / 2, 0, Math.PI * 2, false)
ctx.fill()
ctx.clip()
ctx.drawImage(img, avatarX + num / 2, avatarY + num / 2, imgWidth, imgHeight)
ctx.closePath()
ctx.restore()
},
// 保存海报
savePoster() {
uni.getSetting({
success:(res)=> {
console.log(res.authSetting)
if(res.authSetting['scope.writePhotosAlbum']==false){
uni.openSetting({
success:(res)=> {
if(res.authSetting['scope.writePhotosAlbum']==true){
uni.saveImageToPhotosAlbum({
filePath: this.posterLsit[this.activeIndex],
success: res => {
console.log('保存成功', res)
this.showMsg('保存成功!')
},
fail: (err) => {
console.log('保存失败', err)
this.showMsg('保存失败,请重试!')
}
})
}
}
});
}else{
uni.saveImageToPhotosAlbum({
filePath: this.posterLsit[this.activeIndex],
success: res => {
console.log('保存成功', res)
this.showMsg('保存成功,去分享吧')
},
fail: (err) => {
console.log('保存失败', err)
this.showMsg('保存失败,请重试!')
}
})
}
}
})
},
}
}
```
<style lang="less" scoped>
.poster-box {
position: relative;
height: 929rpx;
width: 100%;
margin-top: 38rpx ;
&.poster-no {
padding-top: 360rpx;
background-color: #f2f2f2;
text-align: center;
.loadong-img {
width: 200rpx;
height: auto;
}
}
.swiper {
width: 100%;
height: 100%;
.swiper-item {
display: flex;
align-items: center;
justify-content: center;
width: 522rpx;
.img-box {
overflow: hidden;
width: 522rpx;
height: 929rpx;
background-color: #fff;
border-radius: 16rpx;
transition: 500ms;
&.small {
transform: scale(0.9);
}
.img {
width: 100%;
height: 100%;
}
}
}
}
}
.canvas-box {
position: fixed;
bottom: -3000rpx;
left: -4000rpx;
}
.btn-box {
width: 70%;
margin: 86rpx auto 0;
.poster-btn {
background-image: url(../../static/img/userCenter/poster-btn.png);
background-size: 100%;
color: #fff;
font-size: 26rpx;
width: 230rpx;
height: 88rpx;
}
.share-btn {
background-image: url(../../static/img/userCenter/share-btn.png);
background-size: 100%;
color: #fff;
font-size: 26rpx;
width: 230rpx;
height: 88rpx;
}
}
</style>