uniapp小程序生成名片海报
<template>
<view class="view">
<view class="post" @click.stop.prevent="change">
<view class="canvas" v-show="hasPost">
<canvas id="firstCanvas" :style="{ 'margin-top':cansHeight/10 + 'px',width: cansWidth + 'px', height: cansHeight + 'px'}" canvas-id="firstCanvas"></canvas>
<view class="bottom">
<view @click="saveCans(1)">保存到手机相册</view>
<view @click="saveCans(2)">保存并预览</view>
</view>
<view class="iconfont icon-closewhite" @click.stop.prevent="close"></view>
</view>
<image :src="imgsrc" :show-menu-by-longpress="1" mode="" v-if="showImg" class="coverImg" @click.stop.prevent></image>
<view class="tip" v-if="showImg">
长按图片可发送好友
</view>
</view>
</view>
</template>
<script>
var that
var rpx
import urlConfig from '../../common/util/config.js'
import { mapState, mapActions, mapMutations } from 'vuex'
export default {
data() {
return {
showImg: false,
hasPost: false,
cansWidth: 690, //海报宽度
cansHeight: 800, //海报高度
realName: 'xxx',//名字
headImg: 'https://dev-commerce.oss-cn-beijing.aliyuncs.com/file/wechat-static/head.jpg',//头像
phone: 'xxxxxxxxxxx',//电话
jobName: 'xxx',//公司职位
industryName: 'xxxx',//行业
companyName: 'xxxx',//公司名称
companyId: -1,
qrCode: '',//小程序码
str: '长按识别小程序码,马上认识我',
imgsrc: "",//保存图片的路径
}
},
onLoad:function(option){
that=this
console.log(option,'00000000000')
this.realName = option.realName ? option.realName:'xxx'
this.headImg = option.headImg ? option.headImg:'https://dev-commerce.oss-cn-beijing.aliyuncs.com/file/wechat-static/head.jpg'
this.phone = option.phone ? option.phone:'xxxxxxxxxxx'
this.jobName = option.jobName ? option.jobName:'xxx'
this.industryName = option.industryName ? option.industryName:'xxxx'
this.companyName = option.companyName ? option.companyName:'xxxx'
this.companyId = option.companyId ? option.companyId:-1
this.qrCode = 'https://dev-commerce.oss-cn-beijing.aliyuncs.com/file/wechat-static/qrcode.jpg'
wx.getSystemInfo({
success: function(res) {
rpx = res.windowWidth/750;
that.cansWidth = that.cansWidth*rpx
that.cansHeight = that.cansHeight*rpx
},
})
console.log(123);
that.huizhihaibao() //请求海报数据
},
computed:{
...mapState({
id: state => state.user.id,
token: state => state.user.token
})
},
methods: {
change(){
this.showImg = false
this.hasPost = true
},
close(){
uni.navigateBack()
},
huizhihaibao(){
uni.showLoading({
title: '加载中'
});
uni.hideLoading();
//数据请求结束
setTimeout(function(){
//定时器,海报方法不能立即执行,等页面渲染完成
that.selseimg()
},2000);
},
roundRect(ctx, x, y, w, h, r, c,direction) {
//圆的直径必然要小于矩形的宽高
if (2 * r > w || 2 * r > h) { return false; }
ctx.save();
ctx.translate(x, y);
//绘制圆角矩形的各个边
that.drawRoundRectPath(ctx, w, h, r,direction);
ctx.fillStyle = c || "#000"; //若是给定了值就用给定的值否则给予默认值
ctx.fill();
ctx.restore();
},
// 生成圆角
drawRoundRectPath(ctx, width, height, radius,direction) {
ctx.beginPath(0);
if(direction == 'all'){
//从右下角顺时针绘制,弧度从0到1/2PI
ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
//矩形下边线
ctx.lineTo(radius, height);
//左下角圆弧,弧度从1/2PI到PI
ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
//矩形左边线
ctx.lineTo(0, radius);
//左上角圆弧,弧度从PI到3/2PI
ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
//上边线
ctx.lineTo(width - radius, 0);
//右上角圆弧
ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
ctx.lineTo(width, height - radius);
}
if(direction == 'bottom'){ //上圆角
//从右下角顺时针绘制,弧度从0到1/2PI
ctx.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
//矩形下边线
ctx.lineTo(radius, height);
//左下角圆弧,弧度从1/2PI到PI
ctx.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
//矩形左边线
ctx.lineTo(0, 0);
//上边线
ctx.lineTo(width, 0);
ctx.lineTo(width, height);
}
if(direction == 'top'){ //下圆角
ctx.lineTo(0, height);
//左下角圆弧,弧度从1/2PI到PI
ctx.lineTo(0, 0);
//左上角圆弧,弧度从PI到3/2PI
ctx.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
//上边线
ctx.lineTo(width - radius, 0);
//右上角圆弧
ctx.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
ctx.lineTo(width, height)
}
ctx.closePath();
},
selseimg(){ //绘制海报
// if(that.userdata.text.length>3){ //昵称太长加省略号
// that.userdata.text=that.userdata.text.slice(0,3)+"..."
// }
let image = this.headImg;//图片地址
let qrcode = this.qrCode;//小程序码址址
let filePath = '';
uni.showLoading({
title: '生成海报中'
});
const context = uni.createCanvasContext('firstCanvas')
this.roundRect(context, 0, 0, that.cansWidth, that.cansHeight, 10, '#fff','all')
console.log('1');
uni.downloadFile({//将图片保存为本地临时文件
url: image,
success(res) {
console.log('2');
console.log(res,123);
// 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容
if (res.statusCode === 200) {
context.drawImage(res.tempFilePath,580*rpx,30*rpx,80*rpx,80*rpx) //海报背景
uni.downloadFile({
url: qrcode,
success(ress) {
if (ress.statusCode === 200) {
//绘制图形
that.roundRect(context, 0,380*rpx,690*rpx,420*rpx, 10, '#f7f7f7','bottom')
context.drawImage(ress.tempFilePath,200*rpx,420*rpx,290*rpx,290*rpx) //个人信息背景
context.setFillStyle('#333333')
context.setFontSize(22*rpx)
context.fillText(that.str, (that.cansWidth - context.measureText(that.str).width) / 2, 750*rpx)
context.setFontSize(28*rpx)
context.fillText(that.companyName,30*rpx,60*rpx)
context.setFillStyle('#000')
context.setFontSize(32*rpx)
context.font = `normal bolder ${32*rpx}px Arial,sans-serif`
context.fillText(that.realName,30*rpx,140*rpx)
context.setFillStyle('#999')
context.setFontSize(24*rpx)
context.fillText(that.jobName,30*rpx,180*rpx)
context.setFillStyle('#666')
context.setFontSize(22*rpx)
context.fillText(that.industryName,30*rpx,260*rpx)
context.fillText(that.phone,30*rpx,300*rpx)
context.draw()
that.hasPost = true
uni.hideLoading();
}
}
})
}
},
fail(err) {
uni.showToast({
title: err.errMsg,
icon: 'none',
duration: 2000
})
uni.hideLoading();
}
})
},
cancel(){
this.$emit('cancelPost')
},
saveCans(e){ //保存海报
uni.showLoading({
title: '保存海报中'
});
console.log('保存');
let tempRatio = 1.5;
// #ifdef H5 || APP-PLUS
tempRatio = 1;
// #endif
uni.canvasToTempFilePath({
x: 0,
y: 0,
width:that.cansWidth*tempRatio,
height:that.cansHeight*tempRatio,
destWidth:that.cansWidth*tempRatio*5,
destHeight:that.cansHeight*tempRatio*5,
canvasId:'firstCanvas',
success: function(res){
uni.hideLoading()
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function (red) {
uni.showToast({
title:'保存相册成功'
})
that.imgsrc=res.tempFilePath
if(e==2){
that.showImg = true
that.hasPost = false
}
},
fail(res) {
if(res.errMsg == "saveImageToPhotosAlbum:fail auth deny") {
uni.showModal({
title:'您需要授权相册权限',
success(res) {
if(res.confirm){
uni.openSetting({
success(res) {
},
fail(res) {
console.log(res)
}
})
}
}
})
}
}
});
},
fail(res) {
uni.hideLoading()
}
},this)
}
}
}
</script>
<style lang="scss">
.coverImg{
display: block;
width: 690rpx;
height: 800rpx;
margin: 0 auto;
margin-top: 70px;
}
.tip{
margin-top: 40rpx;
color: $uni-text-color-inverse;
font-size: 28rpx;
text-align: center;
}
.view{
width: 100vh;
height: 100vh;
background: $uni-bg-color;
}
.post{
background: $uni-bg-color-mask;
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 10;
}
.canvas{
width: 690rpx;
margin: 0 auto;
display: flex;
flex-direction: column;
}
.icon-closewhite{
width: 100vw;
position: fixed;
left: 0;
bottom: 40rpx;
text-align: center;
font-size: 80rpx;
color: $uni-bg-color;
}
.bottom{
margin-top: 40rpx;
width: 100%;
display: flex;
justify-content: space-around;
}
.bottom view{
width:310rpx;
height: 80rpx;
font-size:30rpx;
border-radius: 40rpx;
line-height: 80rpx;
text-align: center;
border: 1px solid $uni-bg-color;
}
.bottom view:first-child{
background: $uni-bg-color;
color: $uni-text-color;
}
.bottom view:last-child{
color:#FFFFFF;
}
.imglist{
width:100%;
padding: 20rpx 0;
overflow:auto;
/* background-color: #ffffff; */
}
.imglist view{
display:flex;
justify-content:space-around;
}
.imglist image{
width:200rpx;
height:200rpx;
border-radius: 10rpx;
}
.tishi-box{
display: flex;
align-items: center;
justify-content: space-around;
background-color: #FFFFFF;
position: fixed;
bottom: 0;
width: 100%;
height:260rpx;
background:#FFFFFF;
border-radius:20rpx 20rpx 0rpx 0rpx;
text-align: center;
}
.tishi-box view{
font-size:28rpx;
font-family:PingFang SC;
font-weight:500;
color:#333333;
line-height:50rpx;
}
.tishi-box image{
width:100rpx;
height:100rpx;
border-radius:50%;
}
</style>
:show-menu-by-longpress="1" //image的属性,按住图片后出现保存和转发的按钮,用于小程序转发图片
@click.stop.prevent //阻止默认行为和冒泡
roundRect(ctx, x, y, w, h, r, c,direction) //圆角矩形
//ctx:canvas对象 x:起始水平位置 y:起始垂直位置 w:宽度 h:高度 r:圆角半径 c:矩形背景 direction:圆角位置
drawRoundRectPath(ctx, width, height, radius,direction) //生成圆角
//ctx:canvas对象 width:宽度 height:高度 radius:圆角半径 direction:圆角位置
direction = 'all'(上下四角都为圆角)
direction = 'top'(上面两个角为圆角)
direction = 'bottom'(下面两个角为圆角)
uni.canvasToTempFilePath //canvas生成图片 *5是生产5倍像素的图片
只要把option里面接收的参数补充完就能看到效果: