This commit is contained in:
唐明明
2021-09-29 15:40:50 +08:00
4 changed files with 584 additions and 69 deletions

View File

@@ -0,0 +1,267 @@
<template>
<view>
<canvas
class="my-canvas"
canvas-id="myCanvas"
id="myCanvas"
:style="{'width': `${poster.width}px`, 'height': `${poster.height}px`}"/>
<view v-if="state">
<view class="posterBack"></view>
<view class="poster">
<view class="poster-img">
<image class="img" :src="invite.cover" mode="widthFix" />
</view>
<view class="poster-btn">
<view class="operate" @tap="saveImage">保存到相册</view>
<view class="operate operate-cancel" @tap="close">取消</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { saveImageToPhotosAlbum, showToast, downloadFile } from '@/uni_modules/sakura-canvas/js_sdk/util'
import Draw from '@/uni_modules/sakura-canvas/js_sdk/draw'
let draw = null
export default {
name:"poster",
props:{
state: '',
invite: ''
},
// data() {
// return {
// state: false,
// poster: {},
// posterImg: '',
// canvasId: 'myCanvas',
// img: 'https://cdn2.xxkucun.com/xxkucun/xiangmu/20210628/593f6211-189b-4df4-9e9c-56ad02ff3352.jpg',
// title: '[东鑫记港式茶餐厅]南京东路|魔都新晋爆款茶餐厅来袭99元抢门',
// price: 148,
// tips: '这是\n一款非常好用的\n绘图插件',
// head: 'https://shop.napi.cc/public/upload/2021/0630/2021063017503669.png',
// big: '',
// }
// },
created() {
console.log(this.$props.state)
console.log(this.$props.invite)
},
// async created(e) {
// console.log(e)
// },
methods: {
// 生成分享图
async createdPoster() {
let { img, title, price, head, tips } = this.$props.invite
draw = new Draw({
width: 375,
height: 590,
canvasId:'myCanvas',
_this: this,
background: {
type: 'color',
color: 'white',
w: 375,
h: 590,
},
})
let res = await draw.createdSharePoster(({ bgObj }) => {
let { width, height } = bgObj
this.poster = bgObj
// 绘制内容
return [
// 大图
{
type: 'image',
x: 0,
y: 0,
src: img,
w: width,
h: width
},
// 标题
{
type: 'text',
w: width - (20 * 2),
text: title,
color: '#333333',
font: {
size: 16
},
line: {
num: 1
},
callBack: (before) => {
let { sx, ex, sy, ey } = before
return {
x: sx + 20,
y: ey + 20,
}
}
},
// 价格
{
type: 'text',
text: `${price}`,
color: '#fe4755',
font: {
size: 24
},
callBack: (before) => {
let { sx, ex, sy, ey } = before
return {
x: sx,
w: width - (sx * 2),
y: ey + 15,
}
}
},
// 虚线
{
type: 'line',
x: 0,
w: width,
color: '#ff875f',
lineType: 'dashed',
callBack: (before) => {
let { sx, ex, sy, ey } = before
return {
y: ey + 10,
}
}
},
// 二维码
{
type: 'qrcode',
x: 20,
size: 100,
text: 'https://ext.dcloud.net.cn/plugin?id=5291',
image: {
src: head,
size: 30,
r: 10,
borderWidth: 7,
borderColor: '#ffffff'
},
callBack: (before) => {
let { sx, ex, sy, ey } = before
return {
y: ey + 15,
}
}
},
{
type: 'text',
w: 200,
text: tips,
color: '#333333',
font: {
size: 17,
},
line: {
height: 22
},
callBack: (before, all) => {
let { sx, ex, sy, ey, w } = before
return {
x: sx + w + 30,
y: sy + 20,
}
}
}
]
})
console.log('res', res)
if (!res.success) return
this.posterImg = res.data
this.isShow = true
},
// 保存图片
async saveImage() {
let { posterImg } = this
let res = await saveImageToPhotosAlbum(posterImg)
if (!res.success) return
showToast('保存成功')
this.isShow = false
},
close() {
this.isShow = false
}
}
}
</script>
<style lang="scss" scoped>
.demo{
width: 700rpx;
height: 400rpx;
background-color: pink;
}
view, image{
box-sizing: border-box;
}
.my-canvas{
position: fixed;
top: -99999999999rpx;
left: -99999999999rpx;
z-index: -99999999999;
opacity: 0;
}
.posterBack {
width: 100%;
height: 100%;
position: fixed;
background-color: rgba(0,0,0,.7);
left: 0;
top: 0;
}
.poster{
width: 100vw;
height: 100vh;
display: flex;
flex-flow: column nowrap;
justify-content: center;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
z-index: 9;
&-img{
width: 580rpx;
position: relative;
margin: 70rpx auto 20rpx;
background-color: #fff;
.img{
width: 100%;
}
}
&-btn{
display: flex;
padding: $padding $padding * 2;
.operate {
width: calc(50% - 30rpx);
margin: 0 15rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
display: inline-block;
text-align: center;
color: #fff;
background-color: $text-price;
&-cancel{
background-color: #e4e4e4;
color: #333;
}
}
}
}
</style>

View File

@@ -1,88 +1,89 @@
<template> <template>
<!-- v-if="loaded" --> <view class="content" v-if="loaded">
<view class="content">
<view class="code"> <view class="code">
<swiper class="code-swiper" previous-margin="70rpx" next-margin="70rpx"> <swiper class="code-swiper" previous-margin="70rpx" next-margin="70rpx" @change="swiperChange">
<swiper-item> <swiper-item v-for="(item, index) in inviteData" :key="index">
<view class="code-item"> <view class="code-item">
<image class="code-back-image" src="@/static/dev/WechatIMG9663.png" mode="aspectFill"></image> <image class="code-back-image" :src="item.cover" mode="aspectFill"></image>
<view class="codDate"> <view class="codDate">
<view class="codDate-year"> <view class="codDate-year">
2020.09 {{item.date.solar.month}}
</view> </view>
<view class="codDate-day"> <view class="codDate-day">
02 {{item.date.solar.day}}
</view> </view>
<view class="codDate-lunar"> <view class="codDate-lunar">
农历八月二十 {{item.date.lunar}}
</view> </view>
</view> </view>
<view class="codeCont"> <view class="codeCont">
<image class="codeCont-avatar" src="@/static/user/user-portrait.png" mode="aspectFill"></image> <image class="codeCont-avatar" :src="item.user_info.avatar ? item.user_info.avatar : '/static/user/user-portrait.png'" mode="aspectFill"></image>
<view class="codeCont-text"> <view class="codeCont-text">
<view class="codeCont-name"> <view class="codeCont-name">
唐明明 {{item.user_info.nickname}}
</view> </view>
<view class="codeCont-number"> <view class="codeCont-number">
邀请码 邀请码{{item.invite}}
<view class="codeBack-number" @click="copyCenter(inviteData.invite)">
21321321
</view> </view>
</view> </view>
<image class="codeCont-img" :src="item.code" mode="widthFix"></image>
</view> </view>
</view> </view>
<view class="codeImg">
<image class="codeImg-code" mode="widthFix"></image>
<view class="codeImg-name">长按识别</view>
</view>
</view>
</swiper-item>
<swiper-item>
<view class="code-item">
<image class="code-back-image" src="@/static/dev/WechatIMG9663.png" mode="aspectFill"></image>
</view>
</swiper-item>
<swiper-item>
<view class="code-item">
<image class="code-back-image" src="@/static/dev/WechatIMG9663.png" mode="aspectFill"></image>
</view>
</swiper-item> </swiper-item>
</swiper> </swiper>
</view> </view>
<view class="footer"> <view class="footer">
<view class="hith">朋友通过你的邀请注册成功后将与您绑定好友关系通过成为平台用户你都可以获得能量碎片奖励</view> <view class="hith">朋友通过你的邀请注册成功后将与您绑定好友关系通过成为平台用户你都可以获得能量碎片奖励</view>
<view class="number"> <view class="number">
<view class="title">邀请码</view> <view class="title">邀请码 : {{inviteData[0].invite}}</view>
<view class="value">2173978217389729</view> <view class="value" @click="copyCenter(inviteData[0].invite)">复制邀请码</view>
</view>
<view class="button" @click="coverCode">生成分享海报</view>
</view>
<canvas class="my-canvas" canvas-id="myCanvas" id="myCanvas"/>
<view v-if="posterShow">
<view class="posterBack"></view>
<view class="poster">
<view class="poster-img">
<image class="img" :src="posterImg" mode="widthFix" />
</view>
<view class="poster-btn">
<view class="operate">长按图片保存</view>
<view class="operate operate-cancel" @tap="posterShow = false">确定</view>
</view> </view>
<view class="button">
<view class="title" @click="coverCode">生成分享海报</view>
</view> </view>
</view> </view>
<canvas canvas-id="myCanvas"></canvas>
</view> </view>
</template> </template>
<script> <script>
import { userInvite } from '@/apis/interfaces/user' import { userInvite } from '@/apis/interfaces/user'
import { saveImageToPhotosAlbum, showToast, downloadFile } from '@/uni_modules/sakura-canvas/js_sdk/util'
import Draw from '@/uni_modules/sakura-canvas/js_sdk/draw' import Draw from '@/uni_modules/sakura-canvas/js_sdk/draw'
let draw = null
export default { export default {
data() { data() {
return { return {
inviteData: {} ,//二维码信息 Popinvite : {}, //下载海报数据
loaded : false inviteData: [] ,//二维码信息
codeIndex : 0,
posterImg : '',
defaultImg: '/static/dev/WechatIMG9663.png',
loaded : false,
posterShow: false
}; };
}, },
onLoad() { onLoad() {
// 获取二维码 // 获取二维码
// this.inviteInfo() this.inviteInfo()
}, },
async created() {},
methods:{ methods:{
// 二维码 // 二维码
inviteInfo(){ inviteInfo(){
userInvite().then(res => { userInvite().then(res => {
this.inviteData = res
this.loaded = true this.loaded = true
this.inviteData = res
}).catch(err => { }).catch(err => {
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
@@ -92,23 +93,178 @@
}, },
// 生成海报 // 生成海报
coverCode(){ async coverCode(){
let canvas = new Draw({ // let { img, title, price, head, tips } = this
width: '375', let img = this.inviteData[this.codeIndex].code
height: '745', let back = this.defaultImg
let name = this.inviteData[this.codeIndex].user_info.nickname
let invite = this.inviteData[this.codeIndex].invite
let avatar = this.inviteData[this.codeIndex].user_info.avatar || '/static/user/user-portrait.png'
let date = this.inviteData[this.codeIndex].date
draw = new Draw({
width: 375,
height: 745,
canvasId:'myCanvas', canvasId:'myCanvas',
_this: this, _this: this,
background: { background: {
type: 'color', type: 'color',
color: '#fffff' color: 'white',
w: 375,
h: 745,
}, },
quality: 1, // 导出图片的质量, 默认1 值范围0~1, 大于一都为1处理
drawTipsText: '绘制中...'
}) })
// await draw.createdSharePoster(() => { let res = await draw.createdSharePoster(({ bgObj }) => {
let { width, height } = bgObj
this.Popinvite = bgObj
// 绘制内容
return [
// 背景
{
type: 'image',
x: 0,
y: 0,
src: back,
w: 375,
h: 745,
zIndex: 0,
},
// return textArray // 日历-边框
// }) {
type: 'rect',
x: 280,
y: 20,
w: 60, // 宽度 必填
h: 80, // 高度 必填
zIndex: 99,
isFill: false, // 是否是填充矩形, false: 线性矩形
lineWidth: 1 ,// 当矩形为线性时,矩形的边框宽度
color: '#ffffff',
},
// 日历-线条
{
type: 'line',
zIndex: 99,
x: 280,
y: 74,
w: 60, // 宽度 默认整个画布的宽度 - x轴的距离
color: '#ffffff', // 颜色 默认#000000 在不考虑字节跳动小程序的前提下可简写(#000)
alpha: 1, // 透明度 默认1 取值范围 0~1
lineType: 'solid', // 线条类型 默认 solid: 实线 可选 dashed: 虚线
lineWidth: 1, // 线条高度
lineCap: 'butt' // 线条端点样式 默认 butt 可选 round, square
},
// 日历-年月
{
type: 'text',
x: 284,
y: 28,
zIndex: 99,
w: width - (20 * 2),
text: date.solar.month,
color: '#ffffff',
font: {
size: 14
}
},
// 日历-日
{
type: 'text',
x: 296,
y: 50,
zIndex: 99,
w: width - (20 * 2),
text: date.solar.day,
color: '#ffffff',
font: {
size: 20,
weight: 'bold'
}
},
// 日历-农历日期
{
type: 'text',
x: 282,
y: 80,
zIndex: 99,
w: width - (20 * 2),
text: date.lunar,
color: '#ffffff',
font: {
size: 14
}
},
// 用户昵称
{
type: 'text',
x: 90,
y: 650,
zIndex: 99,
w: width - (20 * 2),
text: name,
color: '#ffffff',
font: {
size: 18
}
},
// 邀请码
{
type: 'text',
x: 90,
y: 685,
zIndex: 99,
w: width - (20 * 2),
text: '邀请码:' + invite,
color: '#c4a1cb',
font: {
size: 16
}
},
// 用户头像
{
type: 'image',
x: 20,
y: 650,
src: avatar,
w: 54,
h: 54,
drawType: 'arc',
zIndex: 99,
borderWidth: 5, // 图片边框大小 默认0
borderColor: '#ffffff' // 图片边框颜色 默认无颜色
},
// 二维码
{
type: 'image',
x: 270,
y: 630,
w: 90,
h: 90,
zIndex: 99,
src: img
}
]
})
if (!res.success) return
this.posterImg = res.data
this.posterShow = true
},
// 保存图片
async saveImage() {
let { posterImg } = this
let res = await saveImageToPhotosAlbum(posterImg)
if (!res.success) return
showToast('保存成功')
this.posterShow = false
}, },
// 复制邀请码 // 复制邀请码
@@ -128,6 +284,11 @@
}) })
} }
}) })
},
// 切换海报背景index
swiperChange(e) {
this.codeIndex = e.detail.current
} }
} }
} }
@@ -137,6 +298,7 @@
.content{ .content{
background: white; background: white;
padding: $padding 0; padding: $padding 0;
box-sizing: border-box;
min-height: 100vh; min-height: 100vh;
@extend .vertical; @extend .vertical;
} }
@@ -165,11 +327,36 @@
// 提示信息 // 提示信息
.footer{ .footer{
padding: $padding ($padding*2); padding: 0 $padding + 10;
text-align: center;
.hith{ .hith{
color: $text-gray; color: $text-gray;
font-size: $title-size-sm; font-size: $title-size-sm;
padding-top: $padding + 10;
}
.number {
background-color: $border-color-lg;
padding: $padding - 5;
margin: $margin + 20 0;
font-size: $title-size-lg;
border-radius: 8rpx;
display: flex;
.title {
flex: 1;
}
.value {
font-size: $title-size-m;
color: $text-price;
}
}
.button {
background: $mian-color-deep;
border-radius: 0;
height: 90rpx;
line-height: 90rpx;
font-size: $title-size;
color: white;
text-align: center;
border-radius: 8rpx;
} }
// number // number
// title // title
@@ -182,37 +369,43 @@
.codeCont { .codeCont {
position: absolute; position: absolute;
left: 0; left: 0;
bottom: 140rpx; bottom: 0;
width: 100%; width: 100%;
bottom: 100rpx;
left: 0; left: 0;
padding: 40rpx; padding: 10rpx 30rpx 50rpx;
box-sizing: border-box; box-sizing: border-box;
z-index: 9; z-index: 9;
.codeCont-avatar { .codeCont-avatar {
width: 100rpx; width: 80rpx;
height: 100rpx; height: 80rpx;
border-radius: 50%; border-radius: 50%;
border: 6rpx solid #FFFFFF; border: 4rpx solid #FFFFFF;
} }
.codeCont-text { .codeCont-text {
position: absolute; position: absolute;
width: 100%; width: 100%;
left: 0; left: 0;
top: 0; top: 0;
padding: 50rpx 40rpx 0 180rpx; padding: 10rpx 40rpx 0 150rpx;
box-sizing: border-box; box-sizing: border-box;
.codeCont-name { .codeCont-name {
color: #FFFFFF; color: #FFFFFF;
font-size: 34rpx; font-size: $title-size;
margin-bottom: 10rpx; margin-bottom: 10rpx;
} }
.codeCont-number { .codeCont-number {
font-size: 28rpx; font-size: $title-size-sm;
display: flex; display: flex;
color: #c4a1cb; color: #c4a1cb;
} }
} }
.codeCont-img {
width: 140rpx;
height: 140rpx;
position: absolute;
right: 30rpx;
bottom: 30rpx;
}
} }
// 日历 // 日历
.codDate { .codDate {
@@ -235,8 +428,63 @@
} }
.codDate-lunar { .codDate-lunar {
font-size: 24rpx; font-size: 24rpx;
transform: scale(.8); transform: scale(.9);
padding: 4rpx 0; padding: 4rpx 0;
} }
} }
// canvas
.my-canvas{
width: 375px;
height: 745px;
position: fixed;
top: -99999999999rpx;
left: -99999999999rpx;
z-index: -99999999999;
opacity: 0;
}
.posterBack {
width: 100%;
height: 100%;
position: fixed;
background-color: rgba(0,0,0,.7);
left: 0;
top: 0;
}
.poster{
width: 100vw;
height: 100vh;
display: flex;
flex-flow: column nowrap;
justify-content: center;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
z-index: 9;
&-img{
width: 580rpx;
position: relative;
margin: 70rpx auto 20rpx;
.img{
width: 100%;
}
}
&-btn{
padding: 0 $padding * 2;
.operate {
width: 100%;
margin-bottom: 20rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
display: inline-block;
text-align: center;
color: #fff;
&-cancel{
background-color: $text-price;
}
}
}
}
</style> </style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 114 KiB

BIN
static/dev/wallet-code.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB