- 小程序中使用webView组件内嵌的H5页面打开地图和摄像头时需要获取小程序的授权吗?
webView支持的JSSDK接口中,没有获取小程序位置和摄像头权限的方法,那从H5页面打开摄像头和地图就会直接打开。请问有解决方案吗,或者微信允许H5页面不获取权限直接打开吗
2023-11-30 - [开盖即食]利用“云函数”生成小程序码和将buffer流转化图片
[图片] 为什么要用云函数来做这个? 前端一条龙不求人(后端) 利用官方资源来快速解决问题,白piao不香吗? 之前也有不少人分享过云函数生成小程序码的方法,这里我为大家总结下不同方法的区别和优缺点~ [图片] 开盖食用思路: 小程序端请求 --> 云函数API小程序 --> 返回图片的buffer --> 把buffer转化成图片 1、云函数部分 [代码]// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { try { const result = await cloud.openapi.wxacode.get({ path: event.url, //传入需要配置的url,但是新版本不能传参param width: 300 }) console.log(result) return result } catch (err) { console.log(err) return err } } [代码] 新建一个云函数名字为getWxacode,示例是openapi.wxacode.get的方法,这个参数可以直接跳转小程序内部对应的page。 注意: 与 wxacode.createQRCode 总共生成的码数量限制为 100,000,如果你需要大量生成码,请谨慎调用。且新版本只能传path,不能传参param~ 2、页面部分 [代码]Page({ data: { imgUrl: "" //图片地址 }, getWxacode() { wx.cloud.init(); let self = this; wx.showLoading({ title: '请求云函数' }) // 调用云函数 获取 内容 wx.cloud.callFunction({ name: 'getWxacode', data: { url: "pages/home/index" }, success: res => { console.log('云函数调用成功', res); let bufferImg = "data:image/png;base64," + wx.arrayBufferToBase64(res.result.buffer); self.setData({ //imgUrl: res.result.fileID imgUrl: bufferImg }); wx.hideLoading(); }, fail: err => { console.error('云函数调用失败', err) } }) } }) [代码] [图片] 可以获得一个返回值,里面有个图片的buffer,转化buffer即可展示图片内容。 3、转化buffer流成图片的三种方法 3.1 直接将buffer转化Base64 [代码]console.log('云函数调用成功返回值:', res); let bufferImg = "data:image/png;base64," + wx.arrayBufferToBase64(res.result.buffer); self.setData({ imgUrl: bufferImg }); [代码] 这里用到的方法是 wx.arrayBufferToBase64(buffer)转化,加好base64头,即可食用~ 优点: 方便简单 确定: 阅后即焚,无法保存,个别场景可能需要缓存或者拼接canvas海报 3.2 在云函数直接将Buffer上传到云存储 [代码]await cloud.uploadFile({ cloudPath: 'test/' + event.userInfo.openId + '.jpg', //这里如果可以重复就用openId,如果不可能重复就用 fileContent: result.buffer, //处理buffer 二进制数据 success: res => { // 文件地址 console.log(res.fileID) }, fail: err =>{ console.log(err) } }) [代码] [图片] 将生成的小程序码上传到自带的云存储上,可以长期永久保存 优点: 长期保存,合适只要生成一次反复使用的场景 缺点: 生成量大的话,比较占用有限云存储资源 3.3 将图片转化保存在手机本地 [代码]let { buffer } = res.result; const wxFile = wx.getFileSystemManager(); const filePath = wx.env.USER_DATA_PATH + '/test.jpg'; //把图片写在本地 wxFile.writeFile({ filePath, encoding: "binary", data: buffer, success: res => { console.log(res); //writeFile:ok self.setData({ imgUrl: filePath }); } }) [代码] 这里用到的是wx.getFileSystemManager()的方法,将图片buffer转化后保存一个本地地址~ 优点: 生成实体地址,有时候图片太大,base64会出现一些诡异的BUG 缺点: 耗时 4、最终方案 经过综合考虑,这里使用的是不限次数的 openapi.wxacode.getUnlimited方法。 云函数部分: [代码]const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { try { const result = await cloud.openapi.wxacode.getUnlimited({ scene: event.scene }); console.log(result) return await cloud.uploadFile({ cloudPath: 'test/' + event.userInfo.openId + '.jpg', fileContent: result.buffer, //处理buffer 二进制数据 success: res => { // 文件地址 console.log(res.fileID) }, fail: console.error }) } catch (err) { console.log(err) return err } } [代码] 页面代码: [代码]Page({ data: { imgUrl: "" //图片地址 }, getWxacode() { wx.cloud.init(); let self = this; wx.showLoading({ title: '请求云函数' }) // 调用云函数 获取 内容 wx.cloud.callFunction({ name: 'getWxacode', data: { scene: "goTo:pages/home/index" }, success: res => { console.log('云函数调用成功', res); self.setData({ imgUrl: res.result.fileID }); wx.hideLoading(); }, fail: err => { console.error('云函数调用失败', err) } }) }, }) [代码] 5、注意事项 5.1 生成码一共有三种方法: openapi.wxacode.get 小程序码,可以直接生成path,但不能传参,有次数限制 openapi.wxacode.createQRCode 二维码,有次数限制 openapi.wxacode.getUnlimited 特定scene传参,无次数限制 (推荐使用) 1和2方法累积10w次限制 5.2 代码报错,跑不了等 [图片] 记得初始化 wx.cloud.init(); [图片] 记得部署云函数~ ctrl+s 是没用的~~~ [图片] 记得先本地调试好,再上传~~~ 官方文档地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.get.html 看完觉得有帮助记得点个赞哦~ 你的赞是我继续分享的最大动力!^-^
2021-09-13 - 使用threejs渲染视频
琢磨了很久,翻了很多相关文档,才实现了用threejs渲染视频的方法 思路如下 1 在wxml文件里写两个canvas <canvas type="webgl" class="myCanvas" id="myCanvas"></canvas> <canvas style="position: absolute;left: 0;top:300rpx;background-color: red;" type="2d" id="target1"></canvas> 2 实例threeJs相关实例和方法,具体参考,可以百度, 3 添加2d相关实例方法, export default class VideoPlayer { constructor(component){// component 是组件里的this, this.decoder = wx.createVideoDecoder() this.component = component const videoUrl = 'https://cdn2.h5no1.com/static-cdn/cpbz/v.mp4'; this.dataUriList = [] } getCanvasNode(id) { return new Promise((resolve) => { this.component.createSelectorQuery() .select('#' + id) .node(res => resolve(res.node)) .exec(); }); } async downLoad(url){ // 下载视频并压缩视频,如果不压缩可能会卡 return new Promise(resolve=>{ wx.downloadFile({ url, success:res=>{ wx.compressVideo({ quality:'low', // resolution:0.9, // fps:60, src:res.tempFilePath, success:result=>{ console.log(result) resolve(result.tempFilePath) } }) }, fail:()=>{ resolve(url) } }) }) } async playVideo(id,videoUrl,cb){ const canvas = await this.getCanvasNode(id) //获取2dcanvas节点 const path = await this.downLoad(videoUrl) // 下载视频并返回本地地址 const context = canvas.getContext('2d') // 2d上下文 const render = ({ data, width, height }) => { // 渲染2d时,返回DataURI数据,作为纹理数据 canvas.height = height canvas.width = width const imageData = canvas.createImageData(data, width, height) context.putImageData(imageData, 0, 0) if(canvas.toDataURL()){ cb && cb(canvas.toDataURL()) // cb回调方法 } } const decoder = wx.createVideoDecoder() // 创建视频解码器 await decoder.start({ // 开始解码 abortAudio: true, source:path || videoUrl // tempFilePath, }) return Promise.resolve({ decoder, stop(){ return decoder.remove() }, play:async ()=>{ let imageData = decoder.getFrameData() // 获取下一帧的解码数据 if (imageData){ render(imageData) } } }) } } 4 在threejs中引入上面的代码 import VideoPlayer from "./video.js" /* 省略前面的代码 */ this.videoPlayer = new VideoPlayer(this) this.vp = null var geometry = new THREE.PlaneGeometry( 520, 320, 1); var material = new THREE.MeshBasicMaterial( {side: THREE.DoubleSide} ); var plane3 = new THREE.Mesh( geometry, material ); plane3.position.set(0,rangeSize/2/2,-rangeSize/2) scence.add( plane3 ); this.videoPlayer.playVideo('target1','https://video-qn.51miz.com/preview/video/00/00/12/22/V-122260-B7D997DF.mp4',async (res)=>{ if(res){ textureLoader.load(res,texture=>{ // 加载datauri数据到纹理,一定要写在回调里,不然也看着卡顿 texture.minFilter = THREE.NearestFilter plane3.material.map = texture }); } }).then(res=>{ this.vp =res }) // 动画帧方法 this.wgbglCanvas.requestAnimationFrame(()=>{ if(this.vp && this.vp.play){ this.vp.play() } }) 5 视频解码器 文档 https://developers.weixin.qq.com/miniprogram/dev/api/media/video-decoder/wx.createVideoDecoder.html 这个方法很重要,没有这个方法,根本就不能实现webgl视频播放
2022-08-30 - xr-frame下 视频纹理可选参数 abortAudio 开启音频不生效
xr-frame下 视频纹理可选参数 abortAudio:false 开启音频不生效,同时循环播放效果也失效。 [图片] 控制台打印设置参数正常 https://developers.weixin.qq.com/miniprogram/dev/api/xr-frame/interfaces/IVideoTextureOptions.html
2023-02-10