1. Introduction
-
为啥写了小程序?
- 一天,小股东过来说:"我要做个产品,模仿拼多多,超越好物满仓的电商平台,好物满仓商业运营模式不行,赚不到钱,拼多多都是假货更不行了,我们依托微信的5亿的人群流量,根本不愁卖!!!相信我,我去年做电商投了500万,我做了十年了"
- 我当时的内心OS是:"嗯,你说的都对,你去年赔了500万,今年还要赔500万!"
- 没办法临危受命,赶鸭子上架,临时学了简单的API加上以前的CSS基础就搞起来了小程序
-
关于小程序不开放分享到朋友圈的API的思考
- 我觉得张小龙真的是诡才,从他小程序不支持模糊搜索就能看出来他不会开放分享到朋友圈这个API,小程序的定位就不是你面向所有人的推广,只是好友内,同样爱好圈子内的小众轻量型应用
- 但是无奈大多产品真的有这个需求,大家各显神通,剑走偏锋
-
小程序分享到朋友圈的实现思路
- 分享到朋友圈现在的实现思路只有保存图片到系统相册,在让用户手动分享(可以通过分享领券或者折扣来刺激用户分享,已达到流量快速增加)
- 生成分享的小程序图片的方案我现在了解到有两种
A.后台根据需要的小程序码和介绍图片绘制成图片,客户端展示loading页面,然后下载图片,渲染,保存(后台绘制)
B. 前端绘制保存到相册,从服务器请求生成的小程序码的URL,再结合需要介绍图片下载图片,在客户端canvas绘制并保存(应该是现在较多的做法)
2. 实现
- 啰嗦了半天,直接上代码吧,第一次写小程序,有很多不足,欢迎随时指正,阿里嘎多
- 官方文档-有关于小程序码
https://developers.weixin.qq.com/miniprogram/dev/api/qrcode.html
-
实现效果如下,怕万一,打了点马
shareToFriendCircle.jpeg
2.1 .WXML文件
<!-- 分享到朋友圈,与需要显示的正常界面同层级即可 -->
<view wx:if="{{hideShareToFriendCircle}}" class='bgShadow' bindtap='clickShareFrinedCircleShadow' >
<canvas style="width:345px;height:482px;margin:0 auto;margin-top:38rpx" canvas-id="myCanvas"></canvas>
<view class="edit-footer">
<button class="button-done" bindtap="savePic" >保存后分享到朋友圈</button>
</view>
</view>
2.2 .WXSS文件
/* 分享到朋友圈 */
.bgShadow {
height: 1334rpx;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
position: fixed;
top: 0;
left: 0;
}
.edit-footer {
height: 88rpx;
width: 345px;
background-color:red;
display: flex;
margin: 0 auto;
}
.button-done {
width: 100%;
height: 88rpx;
text-align: center;
color: white;
font-size: 28rpx;
background-color: red;
line-height: 88rpx;
}
2.3 .JS文件
- 需要引入的
import util from '../../../utils/util'
var network = require("../../../utils/network.js")
var api = require("../../../utils/api.js")
var app = getApp()
- data相关属性:这里有点冗余,我忘记哪些是不需要的了
data: {
//是否显示分享到朋友圈
hideShareToFriendCircle: false,
//小程序码的临时路径
qrCodeTempPath: "",
topImagePath: "",
topImageURL: "",
//绘制小程序分朋友圈图片相关属性
windowWidth: 0,
windowHeight: 0,
contentHeight: 963,
thinkList: [],
lineHeight: 20,
firstImageSize: 345,
shareFriendCricleLeft: 15,
shareFriendCricleTop: 35,
qrCodeparam: {
scene: "",
page: "",
},
//这里是我分享到好友传递的参数,很多并不需要
shopId: -1,
couponGoodsId:"",
ticketPrice:"",
goodsPrice:'',
isUsed:'',
voucherPrice:'',
skuPrice:'',
color_title:'',
size_title:'',
},
- 点击事件
/**
* 分享到朋友圈
*/
shareToFriendsCircle: function () {
var that = this;
//显示背景半透明
that.setData({
hideShareToFriendCircle: true
});
//scene & page 这两个属性在文档有解释
//****特别注意1****: page的路径只能是已经发布的小程序的路径
let scene = "goods_details_id=" + this.data.id;
this.data.qrCodeparam = {
scene: scene,
page: "pages/shoper/shoper_detail/shoper_detail"
}
//请求小程序码URL
network.requestLoading(api.qrcodeCreate, this.data.qrCodeparam, "POST", '', function (res) {
let qrCodeURL = res.data.info.QRCodeUrl
//下载小程序码,因为canvas绘图必须先下载
//****特别注意2****: downloadFile的域名上线版本中需要配置下载URL,否则下载失败
wx.downloadFile({
url: qrCodeURL,
success: function (res) {
that.setData({
qrCodeTempPath: res.tempFilePath
});
wx.downloadFile({
url: that.data.topImageURL,
success: function (res) {
that.setData({
topImagePath: res.tempFilePath
});
wx.hideLoading();
that.getCanvasData();
},
fail: function () {
wx.showToast({
title: '绘制分享图片失败',
icon: 'none',
duration: 2000,
})
},
complete: function (res) {
}
});
},
fail: function () {
wx.showToast({
title: '下载分享图片失败',
icon: 'none',
duration: 2000,
})
},
complete: function (res) {
console.log(res);
}
})
}, function () {
wx.showToast({
icon: "none",
title: '生成小程序码失败',
})
})
},
/**
* 绘制Canvas
*/
getCanvasData: function () {
let that = this;
let i = 0;
let lineNum = 1;
let thinkStr = '';
let thinkList = [];
let titleName = "【圈集】" + that.data.goodsInfo.goodsName;
for (let item of titleName) {
if (item === '\n') {
thinkList.push(thinkStr);
thinkList.push('a');
i = 0;
thinkStr = '';
lineNum += 1;
} else if (i === 19) {
thinkList.push(thinkStr);
i = 1;
thinkStr = item;
lineNum += 1;
} else {
thinkStr += item;
i += 1;
}
}
thinkList.push(thinkStr);
that.setData({ thinkList: thinkList });
that.createNewImg(lineNum);
},
/**
* 绘制Image
*/
createNewImg: function (lineNum) {
let that = this;
let ctx = wx.createCanvasContext('myCanvas');
//first image(介绍图片)
ctx.drawImage(that.data.topImagePath, 0, 0, that.data.firstImageSize, that.data.firstImageSize);
//middle Info
that.drawFirstSquare(ctx, 140);
let firstTextY = 370;
for (let item of that.data.thinkList) {
if (item !== 'a') {
that.drawFont(ctx, item, 10, firstTextY);
firstTextY += that.data.lineHeight;
}
}
let marketPrice = "原价:¥" + that.data.goodsInfo.marketPrice;
that.drawGrayFont(ctx, marketPrice, 10, 417);
that.drawBlackFont(ctx, "券额:", 10, 449);
let ticketPrice = that.data.goodsInfo.ticketPrice;
that.drawRedFont(ctx, ticketPrice, 45, 449);
that.drawBlackFont(ctx, "券后价:", 84, 449);
let voucherPrice = that.data.goodsInfo.voucherPrice + "元";
that.drawRedFont(ctx, voucherPrice, 135, 449);
ctx.drawImage(that.data.qrCodeTempPath, 235, 360, 100, 100);
ctx.draw();
},
/**
* 绘制中间区域父控件
*/
drawFirstSquare: function (ctx, height) {
ctx.rect(0, this.data.firstImageSize, this.data.firstImageSize, height);
ctx.setFillStyle("#ffffff");
ctx.fill()
},
/**
* 绘制字体
*/
drawFont: function (ctx, content, x, y) {
ctx.setFontSize(14);
ctx.setFillStyle("#333333");
ctx.fillText(content, x, y, 200);
},
/**
* 绘制灰色字体
*/
drawGrayFont: function (ctx, content, x, y) {
ctx.setFontSize(14);
ctx.setFillStyle("#a6a6a6");
ctx.fillText(content, x, y, 70);
},
/**
* 绘制红色字体
*/
drawRedFont: function (ctx, content, x, y) {
ctx.setFontSize(18);
ctx.setFillStyle("#fc0327");
ctx.fillText(content, x, y, 40);
},
/**
* 绘制黑色字体
*/
drawBlackFont: function (ctx, content, x, y) {
ctx.setFontSize(14);
ctx.setFillStyle("#333333");
ctx.fillText(content, x, y);
},
/*
* 保存图片到相册
*/
savePic: function () {
let that = this;
wx.canvasToTempFilePath({
x: 0,
y: 50,
width: that.data.windowWidth,
height: that.data.contentHeight,
canvasId: 'myCanvas',
success: function (res) {
console.log()
util.savePicToAlbum(res.tempFilePath)
},
fail: function (err) {
console.log('失败')
console.log(err)
}
})
},
/*
* 点击分享朋友圈背景取消弹框
*/
clickShareFrinedCircleShadow: function () {
this.setData({
hideShareToFriendCircle: false
});
},
-
不满意的地方
- 代码垃圾重复太多,第一次写小程序,迭代周期短,先实现了功能,会慢慢优化代码
- 绘图canvas了解太少,其实官方文档中还有很多方法,可以借鉴学习
canvas 官方API : https://developers.weixin.qq.com/miniprogram/dev/api/canvas/create-canvas-context.html
-
踩的坑
- A. 生成小程序码的请求时候的参数严格按照文档上的去写 scene & page
- B . wx.downloadFile{} API的下载URL发布上线版本时要需要配置下载域名,否则下载失败
3. END
- 关于小程序的想法
- 小程序IDE不好用,离webstorm or sublime 差了好远(功能&界面)
- 小程序开发是真的低门槛(封装API简单,静态页面CSS保持基本一致),高难度完成一个性能好体验好的小程序(大厂除外,真的有技术在里面,想做好难)
- 前端语言有相同之处,把一门学精了,入手会快一些,自己要多想多做
- 欢迎指正和批评
- 虽然小老板想法很菜鸡,但是有钱啊!虽然产品瞎逼逼,但是得听啊!虽然项目写的很烂,但是自己学写了小程序啊!
- 最后希望所有iOS开发能找到新的方向
网友评论