小程序海报生成
保存图片及权限获取
分享海报带参及接收
·························
分享小程序图片处理
·························
获取用户信息登录(包括openid和session_key)
获取状态栏高度
获取右上角分享关闭胶囊的信息
小程序更新
授权获取手机号(最新)
多个视频播放器,同一时间只允许一个视频在播放,播放一个关闭一个
效果图
wxml页面
<!--index.wxml-->
<button type="primary" bindtap="canvasShow">生成海报</button>
<view wx:if="{{isshow}}" style="position: absolute;top:0;left:0;width: 100%;height: 100%;z-index: 1;background: rgba(0, 0, 0, 0.5);display: flex;justify-content: center;align-items: center;overflow: hidden;" catchtap="close">
<view style="width: 90%;height: 80%;" catchtap="isfalse">
<canvas type="2d" id="myCanvas" style="width: 100%;height: 90%;"></canvas>
<view style="display: flex;align-items: center;justify-content: space-between;margin-top: 30rpx;">
<button type="primary" open-type="share" size="mini">分享好友</button>
<button type="warn" size="mini" bindtap="saveSetting">保存海报</button>
</view>
</view>
</view>
js页面
// index.js
// 获取应用实例
const app = getApp()
Page({
data: {
isshow:false,
posterUrl:'',//海报路径
ss:'',
},
onLoad(e){
console.log(e.id)//获取通过分享进来带的参数
},
//关闭弹窗
close(){
this.setData({
isshow:false
})
},
isfalse(){},//防止冒泡
//打开弹窗
canvasShow(){
this.setData({
isshow:!this.data.isshow
})
// if(this.data.isshow){
// this.action();
// }
this.imageInfo();
},
//获取网络图片的本地路径,本地图片不需要走这一步
//网络图片需要配置download域名
async imageInfo(){
wx.showLoading({
title: '正在绘制...',
})
var arr = [
{name:'bb',url:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fhbimg.b0.upaiyun.com%2F003bba6c74ce151d3ce31aaa6cb7c6ecb72683e917605-ekncjt_fw658&refer=http%3A%2F%2Fhbimg.b0.upaiyun.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639712725&t=217f30d12387f925457525c8cfefa92e'},
{name:'cod',url:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fremote.yunnan.cn%2Fqr%2Fphp%2Fqr.php%3Fd%3Dhttps%3A%2F%2Fyn.yunnan.cn%2Fsystem%2F2021%2F09%2F26%2F031685403.shtml&refer=http%3A%2F%2Fremote.yunnan.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639712676&t=16e84291c62147906672078ce4fbd2eb'}
]
for(let i=0;i<arr.length;i++){
//获取网络图片的本地路径
let data = await this.getlocal(arr[i].url);
arr[i].localpath = data;
}
wx.hideLoading()
this.action(arr);
},
//获取网络图片的本地路径并返回
getlocal(e){
return new Promise((rel,rej) =>{
wx.getImageInfo({
src: e,
success(res){
rel(res.path);
},
fail(res){
rej()
}
})
})
},
//绘制海报
action(e){
console.log(e)
const userName = '名字';
const userInfo = '阿巴阿巴阿巴巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴阿巴';
const that = this;
//选取canvas
wx.createSelectorQuery()
.select('#myCanvas')
.fields({node:true,size:true})
.exec(res =>{
const canvas = res[0].node;
const ctx = canvas.getContext('2d');
const dpr = wx.getSystemInfoSync().pixelRatio;//设备像素比
//虽然页面canvas上写了宽高,但这几句话还是要写,不然里面的图片显示不全
canvas.width = res[0].width * dpr;//canvas宽
canvas.height = res[0].height * dpr;//canvas高
ctx.scale(dpr,dpr)
//文字和图片的位置都是px的,需要好好调控
//文字和图片的位置都是px的,需要好好调控
//文字和图片的位置都是px的,需要好好调控
const img1 = canvas.createImage();//创建图片对象
//图片地址要本地路径的,如果是网络图片就用getImageInfo获取
img1.src = e[0].localpath;
//图片加载完后执行
img1.onload = () => {
//绘制图像到画布
ctx.drawImage(img1,0,0,res[0].width,res[0].height);//坐标0,0,铺满整个canvas
const img2 = canvas.createImage();//创建图片对象
//图片地址要本地路径的,如果是网络图片就用getImageInfo获取
img2.src = e[1].localpath;
//图片加载完后执行
img2.onload = () =>{
ctx.drawImage(img2,220,260,60,60);
//在图片加载完后再加文字,这样文字才能在图片上显示
ctx.fillStyle = '#000000';//颜色
ctx.font = '18px sans-serif';//文字大小和字体,一定填两个,不然无效
ctx.fillText(userName,10,230)//填充文字以及文字位置
//截取文字,然后通过循环来多次绘制,从而达到文字换行
//如果文字之间有逗号等符号分开,也可以通过splite来截取
const w = parseInt(userInfo.length/10);//根据文字长度来决定截取多少次
const arr = [];
for(let i=0;i<w+1;i++){
arr.push(userInfo.slice(i*10,(i*10)+10))//每次截取10个字符,然后放进数组
}
//循环绘制文字
for(let i=0;i<arr.length;i++){
ctx.fillStyle = '#000000';
ctx.font = '16px sans-serif';
ctx.fillText(arr[i],10,260+(i*20))//每绘制一次就让y加20px
}
//将画布生成图片
wx.canvasToTempFilePath({
canvas: canvas,
success(ite){
that.data.posterUrl = ite.tempFilePath
},
fail(ite){
wx.showToast({
title: '海报生成失败',
icon:'none'
})
}
})
}
}
});
},
//查看权限以及授权
saveSetting(){
const that = this;
//查看是否拥有保存图片到手机的权限
wx.getSetting({
success(res){
//没有权限
if(!res.authSetting['scope.writePhotosAlbum']){
//授权
wx.authorize({
scope: 'scope.writePhotosAlbum',
success(){
that.savePoster();
},
fail(){
//授权失败弹出弹窗引导开启权限
wx.showModal({
title:'授权',
content:'请开启存储图片权限',
confirmText:'去开启',
success(va){
if(va.confirm){
//打开权限面板
wx.openSetting({
success(open){
if(open.authSetting["scope.writePhotosAlbum"]){
that.savePoster()
}
}
});
}
}
})
}
})
}else{
that.savePoster();
}
}
})
},
// 保存图片到相册
savePoster(){
wx.showLoading({
title: '',
})
wx.saveImageToPhotosAlbum({
filePath: this.data.posterUrl,
success() {
wx.hideLoading();
wx.showToast({
title: '保存成功',
icon:'none'
})
},
fail() {
wx.hideLoading();
wx.showToast({
title: '保存失败',
icon:'none'
})
}
});
},
//分享朋友圈
onShareTimeline() {
return{
title:'名字',
query:'/pages/index/index',
imageUrl:'/assets/logo.png'
}
},
//分享
onShareAppMessage(res){
// if(res.from == 'button'){
// //通过按钮触发的分享
// }else if(res.from == 'menu'){
// //通过右上角触发的分享
// }
return{
path:'/pages/index/index?id=111',//分享带参,通过onload拿取
imageUrl:this.data.posterUrl
}
}
})
·················
分享小程序图片处理,分享小程序时图片会显示不完全,只有5:4的图片能完全显示,这时要用canvas处理一下才行
<!--分享图转为5:4 -->
<canvas style="position:absolute;top:-9999px;left:-9999px;width: 750px; height: 600px; background: #fff;" type="2d" id="myCanvas"></canvas>
//将顶部图片转为宽高比5:4,成为分享图片
dealShare(){
const that = this;
//选取canvas
wx.createSelectorQuery()
.select('#myCanvas')
.fields({node:true,size:true})
.exec(r =>{
const canvas = r[0].node;
const ctx = canvas.getContext('2d');
const dpr = wx.getSystemInfoSync().pixelRatio;//设备像素比
//虽然页面canvas上写了宽高,但这几句话还是要写,不然里面的图片显示不全
canvas.width = r[0].width * dpr;//canvas宽
canvas.height = r[0].height * dpr;//canvas高
wx.getImageInfo({
src: that.data.detailobj.images[0], // 原图路径,网络图片需要这样,本地图不需要
success: (res) => {
const img1 = canvas.createImage();//创建图片对象
//图片地址要本地路径的,如果是网络图片就用getImageInfo获取
img1.src = res.path;
img1.onload = () => {
ctx.drawImage(img1,0,0,r[0].width * dpr,r[0].height * dpr)//图片画到画布,将画布铺满
//生成图片
wx.canvasToTempFilePath({
width:0,
height:0,
destWidth:r[0].width,
destHeight:r[0].height,
canvas: canvas,
fileType:'png',
success(ite){
console.log(ite.tempFilePath)
},
fail(ite){
console.log('失败')
}
})
}
}
})
})
},
·················
获取用户信息,状态栏高度,右上角分享关闭胶囊信息
data: {
code:'',
},
onLoad() {
//先获取code,不然有问题
let that = this;
wx.login({
success:async (info)=> {
that.data.code = info.code;
}
});
},
//用户信息获取
getUserInfo(){
let that = this;
//获取用户信息
wx.getUserProfile({
desc: '用于登录',
success(res){
//验证code值是否过期
wx.checkSession({
success: async (val)=>{
if(val.errMsg == 'checkSession:ok'){
//获取sessionkey,opneid
let obj = {code:that.data.code}
let data = await app.rq.getSessionkey(obj);//获取sessionkey和openid的接口
if(data.code == 1){
wx.setStorageSync('openid', data.data.openid);//将openid缓存
let para = {
session_key:data.data.session_key,
encryptedData:res.encryptedData,
iv:res.iv,
signature:res.signature
}
that.login(para,res.userInfo);
}else{
wx.showToast({
title: 'sessionkey',
icon:'none'
})
}
}else{
wx.login({
success:async (info)=> {
let code = info.code;
//获取sessionkey,opneid
let obj = {code,autoLogin:true}
let data = await app.rq.getSessionkey(obj);//获取sessionkey和openid的接口
if(data.code == 1){
wx.setStorageSync('openid', data.data.openid);//将openid缓存
let para = {
session_key:data.data.session_key,
encryptedData:res.encryptedData,
iv:res.iv,
signature:res.signature
}
that.login(para,res.userInfo);//将拿到的用户信息用去登录
}else{
wx.showToast({
title: 'sessionkey',
icon:'none'
})
}
}
});
}
}
})
}
})
},
//登录
async login(e,userInfo){
let data = await app.rq.login(e);//登录接口
if(data.code == 1){
wx.showToast({
title: '登录成功',
icon:'success'
})
app.globalData.userInfo = userInfo;
let info = JSON.stringify(userInfo);
wx.setStorageSync('userInfo', info);//缓存用户信息
setTimeout(()=>{
wx.navigateBack();
},800)
}
},
//下面为获取右上角胶囊的
//下面为获取右上角胶囊的
wx.getSystemInfo({
success: (res) => {
//状态栏高度
that.globalData.statusBarHeight = res.statusBarHeight;
},
})
//右上角分享关闭胶囊的高度
const menubtnH = wx.getMenuButtonBoundingClientRect().height;
授权获取手机号(注意开发工具基础库版本号)
<button open-type="getPhoneNumber" bindgetphonenumber="getphone">手机号一键获取</button>
//获取手机号
async getphone(e){
console.log(e)
//后台接口拿手机号
let data = await app.rq.getPhone({code:e.detail.code});
if(data.code == 1){
console.log('获取手机号成功')
}else{
wx.showToast({
title: '手机号获取失败',
})
}
},
小程序更新
//小程序更新
appletUpdate(){
// 获取小程序更新机制兼容
if (wx.canIUse('getUpdateManager')) {
const updateManager = wx.getUpdateManager()
//1. 检查小程序是否有新版本发布
updateManager.onCheckForUpdate((res) => {
// 请求完新版本信息的回调
if (res.hasUpdate) {
updateManager.onUpdateReady(() => {
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
confirmText: "更新", //只保留确定更新按钮
success(res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
}
})
} else {
// 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: '提示',
content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
})
}
},
多个视频播放器,同一时间只允许一个视频播放
<view wx:for="{{list}}" wx:key="index" class="bigHousing">
<video
src="{{item.videos_url}}"
id="homeVideo{{item.id}}"
poster="{{item.poster}}"
show-center-play-btn
enable-progress-gesture
enable-play-gesture
style="width: 100%;"
binderror="videoError"
bindpause="videoStop"
bindplay="videoPlay"
data-id="{{item.id}}"
></video>
</view>
data: {
videoId:'',//当前播放视频的id
},
//视频播放出错
videoError(e){
wx.showToast({
title: '视频播放出错',
icon:'none'
})
this.data.videoId = '';
},
//暂停播放
videoStop(e){
this.data.videoId = '';
},
//视频播放
videoPlay(e){
let id = 'homeVideo'+e.currentTarget.dataset.id;
//同一时间只允许一个视频在播放
if (!this.data.videoId) {
this.data.videoId = id;
var videoContext = wx.createVideoContext(id,this) //这里对应的视频id
videoContext.play()
} else { // 有播放时先将prev暂停,再播放当前点击的current
var videoContextPrev = wx.createVideoContext(this.data.videoId,this)//this是在自定义组件下,当前组件实例的this,以操作组件内 video 组件(在自定义组件中药加上this,如果是普通页面即不需要加)
if (this.data.videoId != id) {
videoContextPrev.pause()//视频暂停
this.data.videoId = id;
var videoContextCurrent = wx.createVideoContext(id,this)
videoContextCurrent.play()
}
}
}