在本文 微信小程序相机组件wx.createCameraContext()的使用模拟微信拍照之前需要看看
微信小程序-获取用户session_key,openid,unionid - 后端为nodejs
代码封装是在上文添加的。
本文知识点:
1、微信小程序相机组件wx.createCameraContext()使用
2、微信小程序拍照,录视频实现
3、微信小程序上传文件接口wx.uploadFile()的使用
4、微信小程序wx:if的使用
5、nodejs上传文件multer模块的使用
6、camera组件使用
效果
在笔记本上,没有前后置翻转效果,真机上是有的;在微信开发工具里camera组件是透明的,真机上没问题;在微信开发工具里上传的视频格式为webm,真机上为mp4。
小程序代码
1、在utils下的wechat.js文件里添加代码 /** * 将本地资源上传到开发者服务器,客户端发起一个 HTTPS POST 请求 * @param {string} url 开发者服务器 url * @param {string} filePath 要上传文件资源的路径 * @param {string} name * @param {object} formData HTTP 请求中其他额外的 form data */ static uploadFile(url, filePath, name, formData = { openid: "test" }) { return new Promise((resolve, reject) = { let opts = { url, filePath, name, formData, header: { 'Content-Type': "multipart/form-data" }, success: resolve, fail: reject }; wx.uploadFile(opts); }); }
js//index.js//获取应用实例let app = getApp();let wechat = require("../../utils/wechat");Page({ data: { device: true, tempImagePath: "", // 拍照的临时图片地址 tempThumbPath: "", // 录制视频的临时缩略图地址 tempVideoPath: "", // 录制视频的临时视频地址 camera: false, ctx: {}, type: "takePhoto", startRecord: false, time: 0, timeLoop: "", }, onLoad() { this.setData({ ctx: wx.createCameraContext() }) }, // 切换相机前后置摄像头 devicePosition() { this.setData({ device: !this.data.device, }) console.log("当前相机摄像头为:", this.data.device ? "后置" : "前置"); }, camera() { let { ctx, type, startRecord } = this.data; // 拍照 if (type == "takePhoto") { console.log("拍照"); ctx.takePhoto({ quality: "normal", success: (res) = { // console.log(res); this.setData({ tempImagePath: res.tempImagePath, camera: false, }); wechat.uploadFile("https://xx.xxxxxx.cn/api/upload", res.tempImagePath, "upload") .then(d = { console.log(d); }) .catch(e = { console.log(e); }) }, fail: (e) = { console.log(e); } }) } // 录视频 else if (type == "startRecord") { if (!startRecord) { console.log("开始录视频"); this.setData({ startRecord: true }); // 30秒倒计时 let t1 = 0; let timeLoop = setInterval(() = { t1++; this.setData({ time: t1, }) // 最长录制30秒 if (t1 == 30) { clearInterval(timeLoop); this.stopRecord(ctx); } }, 1000); this.setData({ timeLoop }) // 开始录制 ctx.startRecord({ success: (res) = { console.log(res); }, fail: (e) = { console.log(e); } }) } else { this.stopRecord(ctx); } } }, // 停止录制 stopRecord(ctx) { console.log("停止录视频"); clearInterval(this.data.timeLoop); ctx.stopRecord({ success: (res) = { this.setData({ tempThumbPath: res.tempThumbPath, tempVideoPath: res.tempVideoPath, camera: false, startRecord: false, time: 0 }); wechat.uploadFile("https://xx.xxxxxx.cn/api/upload", res.tempThumbPath, "tempThumbPath") .then(d = { console.log(d); return wechat.uploadFile("https://xx.xxxxxx.cn/api/upload", res.tempVideoPath, "tempVideoPath") }) .then(d = { console.log(d); }) .catch(e = { console.log(e); }) }, fail: (e) = { console.log(e); } }) }, // 打开模拟的相机界面 open(e) { let { type } = e.target.dataset; console.log("开启相机准备", type == "takePhoto" ? "拍照" : "录视频"); this.setData({ camera: true, type }) }, // 关闭模拟的相机界面 close() { console.log("关闭相机"); this.setData({ camera: false }) }})
html
view class="view" view class="window" image class="cover-9" src="{{tempImagePath}}" bindtap="img" wx:if="{{type=='takePhoto'}}"/image video class="cover-9" src="{{tempVideoPath}}" poster="{{tempThumbPath}}" wx:if="{{type=='startRecord'}}"/video view class="window-2" button bindtap="open" type="primary" data-type="takePhoto"拍照/button button bindtap="open" type="primary" data-type="startRecord"录制/button /view /view camera class="camera" device-position="{{device?'back':'front'}}" wx:if="{{camera}}" flash="off" cover-view class="cover-1" bindtap="camera" cover-view class="cover-2" cover-view class="cover-5" wx:if="{{type=='startRecord'&&startRecord}}"{{time}}S/cover-view /cover-view /cover-view cover-image class="cover-3" src="/images/xx2.png" style="width:60rpx;height:60rpx;" bindtap="close"/cover-image cover-image class="cover-4" src="/images/zh.png" style="width:80rpx;height:60rpx;" bindtap="devicePosition"/cover-image /camera/view
csspage{ height: 100%;}.view{ width: 100%; height: 100%;}.window{ width: 100%; height: 100%; position: absolute;}.window-2{ display: flex; flex-direction: row;}.camera{ width: 100%; height: 100%;}.cover-1{ width: 150rpx; height: 150rpx; border-radius: 150rpx; background-color: #dedcdc; display: flex; flex-direction: row; align-items: center; justify-content: center; position: absolute; bottom: 60rpx; left: 300rpx;}.cover-3{ position: absolute; bottom: 105rpx; left:135rpx;}.cover-9{ width: 728rpx; height: 80%; margin: 0 10rpx; border:2rpx solid; border-radius:5px; }button{ margin: 0 10rpx; width: 100%;}.cover-4{ position: absolute; top: 60rpx; right:40rpx;}.cover-2{ width: 110rpx; height: 110rpx; border-radius: 110rpx; background-color: #ffffff; display: flex; flex-direction: row; align-items: center; justify-content: center; color:#da2121; font-size: 32rpx;}
nodejs代码
文件上传使用multer模块,引入multer模块后配置好并添加一个上传处理的路由,创建上传的目录,本文是uploads/tmp目录const multer = require('multer');let path = require("path");//上传文件配置const storage = multer.diskStorage({ //文件存储位置 destination: (req, file, cb) = { cb(null, path.resolve(__dirname, '../uploads/tmp/')); }, //文件名 filename: (req, file, cb) = { cb(null, `${Date.now()}_${Math.ceil(Math.random() * 1000)}_multer.${file.originalname.split('.').pop()}`); }});const uploadCfg = { storage: storage, limits: { //上传文件的大小限制,单位bytes fileSize: 1024 * 1024 * 20 }};router.post("/api/upload", async (req, res) = { let upload = multer(uploadCfg).any(); upload(req, res, async (err) = { if (err) { res.json({ path: `//uploads/tmp/${uploadFile.filename}` }); console.log(err); return; }; console.log(req.files); let uploadFile = req.files[0]; res.json({ path: `//uploads/tmp/${uploadFile.filename}` }); });})
后端打印上传的文件夹
素材
向下箭头:https://img-blog.csdn.net/20180226111545178翻转图片:https://img-blog.csdn.net/20180226111559273参考地址:
https://mp.weixin.qq.com/debug/wxadoc/dev/component/camera.htmlhttps://mp.weixin.qq.com/debug/wxadoc/dev/api/api-camera.html
意外金喜的博客:http://blog.csdn.net/zzwwjjdj1
小程序