微信小程序相机组件wx.createCameraContext()的使用模拟微信拍照-后端为nodejs

在本文 微信小程序相机组件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>
css
page{
  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://mp.weixin.qq.com/debug/wxadoc/dev/component/camera.html
https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-camera.html

意外金喜的博客:http://blog.csdn.net/zzwwjjdj1



  • 13
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值