包括有功能:多张商品图排版、保存海报到本地、预览转发海报、转发小程序
wxml文件
<!-- 分享海报弹窗 -->
<view class="mask" bindtap='formatHide' wx:if="{{showPostersStatus}}"></view>
<view class="share_con" animation="{{animationData}}" wx:if="{{showPostersStatus}}">
<!-- 海报区域 -->
<view class="poster_area" style="height:{{ctxh}}rpx">
<view class='dialog-close2' bindtap='formatHide'><image src='{{dialogClose2}}'></image></view>
<image src="{{shareImgPath}}" wx:if='{{drawposters}}'></image>
</view>
<!-- 按钮区域 -->
<view class="btn_area">
<view class='dialog-close' bindtap='formatHide'><image src='{{dialogClose}}'></image></view>
<view class="set_type">
<text>选择排版</text>
<view class="{{tabobj.tabbool==1?'picTabs':''}}" data-tab='1' data-imgnum="0" data-ctxdiff="0" bindtap="picTab">单张图</view>
<view wx:if="{{goods.imgs.length>1}}" class="{{tabobj.tabbool==2?'picTabs':''}}" data-tab='2' data-imgnum="4" data-ctxdiff="115" bindtap="picTab">四张图</view>
</view>
<view class="posters_btn">
<button wx:if="{{!openset}}" class="posters_btn1" bindtap="savePosters"><image src="{{posters_icon1}}"></image> 保存海报</button>
<button wx:if="{{openset}}" class="posters_btn1" bindtap="openSet" bindopensetting="openSet"><image src="{{posters_icon1}}"></image> 保存海报</button>
<button class="posters_btn2" open-type="share"><image src="{{posters_icon2}}}"></image> 转发小程序</button>
<view class="posters_btn3" bindtap='imgYu' data-src="{{shareImgPath}}}"><image src="{{posters_icon3}}}"></image> 转发海报</view>
</view>
<view class="bottom_tip">※专属链接,转发可锁粉</view>
</view>
</view>
<canvas canvas-id='share' style="width:{{ctxw}}px;height:{{ctxh}}px;position:fixed;left: -10000px;background:#fff;" hidden='{{canvasHidden}}'></canvas>
<!-- 分享海报弹窗end -->
js文件
const wxGetImageInfo = promisify(wx.getImageInfo)
function promisify( api){
return (options, ...params) => {
return new Promise((resolve, reject) => {
const extras = {
success: resolve,
fail: reject
}
api({ ...options, ...extras }, ...params)
})
}
}
Page({
data: {
showModalStatus: false,
showParaModalStatus: false,
showShareStatus: false,
showPlaybillStatus: false,
scrollStatus: true,
userInfo:{},
goods_item: {},
goods: {},
goods_list: {},
animationData: {},
dialogClose: app.globalData.Domain + 'img/common/dialog_close.png?' + random,
dialogClose2: app.globalData.Domain + 'img/common/dialog_close2.png?' + random,
share_icons: app.globalData.Domain + 'img/common/share_icon.png?' + random,
posters_icon1: app.globalData.Domain + 'img/common/posters_icon1.png?' + random,
posters_icon2: app.globalData.Domain + 'img/common/posters_icon2.png?' + random,
posters_icon3: app.globalData.Domain + 'img/common/posters_icon3.png?' + random,
posters_pic1: app.globalData.Domain + 'img/goods/posters_pic1.png?' + random,
posters_pic2: app.globalData.Domain + 'img/goods/posters_pic2.png?' + random,
avatarUrl_default: app.globalData.Domain + 'img/goods/post_logo.png?' + random,
qrcode_default: app.globalData.Domain + 'img/goods/codeImg.jpg?' + random,
is_show_service: false,
canvasHidden: true,
tabobj: {
tabbool: 1,
imgnum: 0,
ctxdiff: 0
},
ctxw: 483,
ctxh: 755,
shareImgPath: '',
backIndex: false,
drawposters: false,
openset: false,
showPostersStatus: false, //分享海报
userInfos: "",
},
/**
* 展示海报
*/
sharePosters(e) {
this.setData({
scrollStatus: false,
shareImgPath: ''
})
var animation = wx.createAnimation({
duration: 300,
timingFunction: "linear",
delay: 0
})
this.animation = animation
animation.translateY(500).step()
this.setData({
animationData: animation.export(),
showPostersStatus: true
})
setTimeout(function () {
animation.translateY(0).step()
this.setData({
animationData: animation.export(),
showPostersStatus: true
})
}.bind(this), 100)
this.saveImg(this.data.tabobj);
},
/**
* 隐藏海报
*/
formatHide: function (e) {
this.setData({
showPostersStatus: false, //分享海报
})
},
// 选择排版切换
picTab(e) {
let tabbool = e.currentTarget.dataset.tab;
let imgnum = e.currentTarget.dataset.imgnum;
let ctxdiff = e.currentTarget.dataset.ctxdiff;
let tabobj = {
tabbool,
imgnum,
ctxdiff
}
this.saveImg(tabobj)
},
// 图片预览
imgYu() {
if (this.data.shareImgPath) {
Promise.all(
[wxGetImageInfo({
src: this.data.shareImgPath
})]
).then((res)=>{
//图片预览
wx.previewImage({
current: res[0].path, // 当前显示图片的http链接
urls: [res[0].path],
success() {
// wx.showToast({
// title: '长按发送给朋友',
// })
}
})
})
} else {
util.showErrorToast('请等绘制完成')
}
},
/**
* 分享
*/
onShareAppMessage(res) {
wx.showShareMenu({
withShareTicket: true
})
let userInfo = wx.getStorageSync('userInfo');
let sellerId = userInfo.seller_id || 0;
let path = `/pages/goods/detail/detail?item_id=${this.data.item_id}&goods_id=${this.data.goods_id}&backIndex=true&share_seller_id=${sellerId}`;
return {
title: this.data.goods_item.title,
path: path,
imageUrl: this.data.goods.imgs[0].big,
success(shareTickets) {
console.log(path)
}
}
},
/**
* 查看是否授权&&获取用户信息
*/
getUserInfo() {
let _this = this
return new Promise((resolve, reject) => {
// 查看是否授权
wx.getSetting({
success(res) {
if (res.authSetting['scope.userInfo']) {
wx.getUserInfo({
success(res){
let userInfos = res.userInfo
_this.setData({
userInfos
})
_this.sharePosters()
return resolve(res)
},
fail(res){
util.showErrorToast('信息获取失败!')
}
})
} else {
util.showErrorToast('请先授权!!')
}
},
fail(err){
util.showErrorToast('请先授权!!')
return false
}
})
})
},
// 获取图片信息
getImageInfo(img) {
var imgarr = [];
wx.getImageInfo({
src: img,
success: (res)=>{
imgarr = [res.width, res.height]
return imgarr
},
fail: (res)=>{
console.log(res)
}
})
},
/**
* 文字处理
*/
fillTextLineBreak(ctx, text, y, lw, lh, lineNum, ellipsis) {
let i = 0;
let n = 0;
let r = -1;
while (i < text.length) {
while (ctx.measureText(text.substring(n, i)).width < lw && i < text.length) {
i++
}
r++
if(lineNum == r) {
let texts = text.substring(n, i)
let measureW = ctx.measureText(text.substring(n, i)).width
let obj = {
text: ellipsis ? measureW > lw ? texts + '...':texts : texts,
y: y + lh * r
}
return obj
}
n = i
}
},
product_imgs(imgnums, product_img) {
let product_img_arr = [];
for(let i = 1; i< imgnums; i++) {
if (product_img[i]) {
product_img_arr.push(
wxGetImageInfo({
src: product_img[i].big
})
)
}
}
return product_img_arr
},
/**
* 获取图片
*/
getImg(callback, tabobj) {
let imgnums = tabobj ? tabobj.imgnum || 0 : 0
Promise.all([
wxGetImageInfo({
src: this.data.posters_pic1
}),
wxGetImageInfo({
src: this.data.posters_pic2
}),
wxGetImageInfo({
src: this.data.userInfos.avatarUrl || this.data.avatarUrl_default
}),
wxGetImageInfo({
src: this.data.qrcode_default
}),
wxGetImageInfo({
src: this.data.goods.imgs[0].big
}),
...(this.product_imgs(imgnums, this.data.goods.imgs)),
]).then(res=>{
wx.showLoading({
title: '绘制中......',
})
callback && callback(res)
}).catch(err=>{
console.log(`报错${err}`);
})
},
/**
* 画图
*/
drawImages(ctx, imgInfos, tabobj, scale_img){
let [
{ path: plantsImg1 },
{ path: plantsImg2 },
{ path: avatarUrl },
{ path: qrcode_default },
{ path: product_img0 }
] = imgInfos
let tabbool = tabobj ? tabobj.tabbool || 1 : 1
let imgnums = tabobj ? tabobj.imgnum || 0 : 0
let ctxdiff = tabobj ? tabobj.ctxdiff || 0 : 0
ctx.drawImage(plantsImg1, 0, 0, ctx.width, 544 / scale_img);
ctx.drawImage(plantsImg2, 33 / scale_img, ctx.height - 80, 690 / scale_img, 62 / scale_img);
ctx.drawImage(qrcode_default, 380, 480 + (ctxdiff | 0), 85, 85);
ctx.drawImage(product_img0, 20, 160, 690 / scale_img, 460 / scale_img);
if (tabbool == 2) {
for (let i = 1; i < imgnums; i++) {
imgInfos[i + 4] && ctx.drawImage(imgInfos[i + 4].path, 20 + (220 / scale_img + 10) * (i - 1), 470, 220 / scale_img, 147 / scale_img)
}
};
ctx.arc(60, 95, 40, 0, 2 * Math.PI, false);
ctx.clip();
ctx.drawImage(avatarUrl, 20, 55, 80, 80);
ctx.restore();
},
saveImg(tabobj) {
this.getImg(res=>{
let imgInfos = res;
let ctxdiff = tabobj ? tabobj.ctxdiff || 0 : 0
let ctxh = 755 + (ctxdiff|0);
let ctxw = this.data.ctxw
var that = this;
let goodsname = this.data.goods_item.title;
let nickName = this.data.userInfos.nickName;
// let product_img = this.data.goods.imgs;
// let qrcode_default = this.data.qrcode_default; // 二维码
let oldprize = '¥' + this.data.shop_price;
let nowprize = '¥'+ this.data.price;
this.setData({
canvasHidden: false,
drawposters: false
})
let timers = setTimeout((res)=>{
if (this.data.shareImgPath) {
return false
} else {
wx.hideLoading()
util.showErrorToast('网络不好,重绘!')
}
}, 5500)
let ctx = wx.createCanvasContext('share');
this.setData({
ctxh,
tabobj
})
ctx.height = ctxh;
ctx.width = ctxw;
let scale_img = 1.55; //缩放比例
ctx.save();
ctx.beginPath();
ctx.setFillStyle('#fff')
ctx.fillRect(0, 0, ctxw, ctxh);
this.drawImages(ctx, imgInfos, tabobj, scale_img);
ctx.setFontSize(25);
ctx.setFillStyle('white');
ctx.fillText(nickName || '你好大象', 110, 90);
ctx.setFontSize(18);
ctx.fillText('邀请您享受大象居家优惠', 110, 115);
ctx.setFontSize(20);
ctx.setFillStyle('black');
let fillTextObj1 = this.fillTextLineBreak(ctx, goodsname, 495 + (ctxdiff|0), 285, 25, 0);
let fillTextObj2 = this.fillTextLineBreak(ctx, goodsname, 495 + (ctxdiff|0), 275, 25, 1, 1);
ctx.fillText(fillTextObj1.text, 20, fillTextObj1.y);
fillTextObj2 && ctx.fillText(fillTextObj2.text, 20, fillTextObj2.y);
ctx.setFillStyle('#ff2323');
ctx.fillText(nowprize, 20, 575+(ctxdiff|0));
let nowprizeW = ctx.measureText(nowprize).width;
if (oldprize != nowprize && nowprize < oldprize) {
ctx.setFillStyle('#a8a8a8');
ctx.setFontSize(16);
ctx.fillText(oldprize, 30 + nowprizeW, 575 + (ctxdiff|0));
let oldprizeW = ctx.measureText(oldprize).width;
ctx.moveTo(30 + nowprizeW, 570 + (ctxdiff | 0));
ctx.lineTo(30 + nowprizeW + oldprizeW, 570 + (ctxdiff | 0));
ctx.setStrokeStyle('#a8a8a8')
ctx.stroke();
}
ctx.setFontSize(14);
ctx.setFillStyle('#111');
ctx.fillText('长按识别二维码', 365, 585 + (ctxdiff|0));
ctx.restore();
//把画板内容绘制成图片,并回调 画板图片路径
ctx.draw(false, () => {
setTimeout(() => {
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: ctx.width,
height: ctx.height,
destWidth: ctx.width * 2,
destHeight: ctx.height * 2,
fileType: 'jpg',
canvasId: 'share',
success: (res) => {
if (!res.tempFilePath) {
wx.showModal({
title: '提示',
content: '图片绘制中,请稍后重试',
showCancel: false
})
}
this.setData({
shareImgPath: res.tempFilePath,
ctxh,
tabobj,
drawposters: true
})
wx.hideLoading()
},
fail: (err) => {
console.log(`${new Date} 报错${err}`)
wx.hideLoading()
}
})
timers && clearTimeout(timers)
}, 800)
})
}, tabobj)
},
// 保存分享海报
//画板路径保存成功后,调用方法吧图片保存到用户相册
savePosters() {
wx.saveImageToPhotosAlbum({
filePath: this.data.shareImgPath,
//保存成功失败之后,都要隐藏画板,否则影响界面显示。
success: (res) => {
wx.hideLoading();
this.setData({
canvasHidden: true
})
wx.showModal({
content: '保存成功',
showCancel: false
})
},
fail: (res) => {
console.log(res)
if (res.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || res.errMsg === "saveImageToPhotosAlbum:fail auth deny"){
console.log("打开设置窗口");
util.showErrorToast('请打开设置授权相册')
this.setData({
openset: true
})
}
}
})
},
openSet() {
this.setData({ openset:false })
wx.openSetting({
success(settingdata) {
if (settingdata.authSetting["scope.writePhotosAlbum"]) {
console.log("获取权限成功,再次点击图片保存到相册")
} else {
console.log("获取权限失败")
}
},
fail(err) {
console.log(`报错${new Date}:${err}`)
util.showErrorToast('请打开设置授权相册')
}
})
},
getShareCode() {
let that = this;
//获取分享码
let page = 'pages/goods/detail/detail';
let userInfo = wx.getStorageSync('userInfo');
let sellerId = userInfo.seller_id || 0;
//scene可自定义规则,注意长度微信有限制
let scene = `${that.data.item_id},${that.data.goods_id},${sellerId}`;
util.request(api.WxacodeUnlimited, {
'page': page, 'scene': scene
}, 'POST').then((res) => {
if (res.code == 200) {
that.setData({
qrcode_default: res.data.qrcode
});
}
});
},
onLoad: function (options) {
var that = this;
wx.getSystemInfo({
success: function (res) {
that.setData({
scrollHeight: res.windowHeight
});
}
});
wx.showLoading({
title: '加载中...',
});
let item_id = parseInt(options.item_id);
let goods_id = parseInt(options.goods_id);
let backIndex = options.backIndex || false;
let share_seller_id = parseInt(options.share_seller_id) || 0;
if (options.scene != undefined) {//扫码进入
let scene = decodeURIComponent(options.scene);
backIndex = true;
let param = scene.split(',');
item_id = param[0] || 0;
goods_id = param[1] || 0;
share_seller_id = param[2] || 0;
}
if (share_seller_id > 0) {
app.globalData.userInfo.share_seller_id = share_seller_id;
}
this.setData({
'item_id': item_id,
'goods_id': goods_id,
'backIndex':backIndex,
});
this.getGoodsInfo();
this.getShareCode();
// .then(()=>{
// this.saveImg();
// });
// this.getUserInfo()
wx.hideLoading();
},
onShow: function () {
// 分享
let userInfo = wx.getStorageSync('userInfo');
let token = wx.getStorageSync('token');
// 页面显示
if (userInfo && token) {
app.globalData.userInfo = userInfo;
app.globalData.token = token;
}
this.setData({
userInfo: app.globalData.userInfo,
});
},
})
wxss文件
/* 分享海报 */
.share_btn {
position: absolute;
width: 80rpx;
height: 80rpx;
top: 10rpx;
right: 0rpx;
border-radius: 50%;
box-shadow: 0 0 25rpx -5rpx rgb(0, 0, 0, 0.35);
background: transparent;
line-height: 100%;
padding: 0;
margin: 0;
}
.share_con {
position: fixed;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 101;
}
.btn_area {
position: absolute;
bottom: env(safe-area-inset-bottom);
width: 100%;
height: 360rpx;
background-color: #fff;
z-index: 101;
}
.set_type {
width: 485rpx;
height: 60rpx;
margin: 40rpx auto 40rpx;
}
.set_type text {
float: left;
line-height: 60rpx;
font-size: 20rpx;
color: #666;
}
.set_type view {
float: left;
margin-left: 30rpx;
padding: 10rpx 25rpx;
font-size: 32rpx;
border: 1px solid #ccc;
border-radius: 30rpx;
}
.set_type .picTabs {
border: 1px solid #333;
color: #333;
}
.posters_btn {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
width: 500rpx;
margin: 0 auto 40rpx;
}
.posters_btn::after {
position: absolute;
content: "";
bottom: -20rpx;
width: 100%;
height: 1px;
background-color: #ccc;
}
.posters_btn view,.posters_btn button {
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column;
height: 140rpx;
}
.posters_btn button {
font-size: 24rpx;
color:#333;
background: transparent;
line-height: 100%;
padding: 0;
margin: 0;
}
.posters_btn view image,.posters_btn button image {
width: 80rpx;
height: 80rpx;
}
.bottom_tip {
width: 100%;
color: #333;
text-align: center;
}
.poster_area {
position: absolute;
bottom: 360rpx;
left: 50%;
transform: translateX(-50%);
width: 483rpx;
height: 755rpx;
}