实现功能为用户点击扫码会去扫描二维码,然后将扫描的场景图片相当于进行了一下拍照保存,然后将图片转为base64,然后将base64传给后端进行处理。目的是为了防止用户截图保存,翻拍以及拍照识别等作弊行为。因此在扫码的过程中需要拿到码信息和相关的场景图片。
页面结构
两个文件
pages/index/index和pages/scan/scan分别为首页和扫码页面。
首页代码
pages/index/index.wxml代码如下
<!--pages/index/index.wxml-->
<button bind:tap="goScan">去扫码</button>
<text wx:if="{{data!=''}}">扫码结果: {{data}}</text>
<text wx:if="{{filePath}}">扫码的base64图片</text>
<image wx:if="{{filePath}}" src="{{filePath}}"></image>
page/index/index.js代码如下
Page({
data: {
filePath: "",
data:""
},
goScan() {
const that = this;
wx.navigateTo({
url: "../scan/scan",
events: {
acceptDataFromB: (data) => {
console.log("首页获取的扫码结果:", data);
const fs = wx.getFileSystemManager();
fs.readFile({
filePath: data.filePath,
encoding: 'base64', // 指定读取文件的编码为base64
success(res) {
// 下面打印的这个base64就是完整的截图的图片
console.log("data:image/jpeg;base64," + res.data);
// 上传图片...
that.setData({
filePath: "data:image/jpeg;base64," + res.data,
data:JSON.stringify(data)
})
},
fail(err) {
console.error("文件读取失败:", err);
}
})
},
},
});
},
});
扫码页面代码
pages/scan/scan.wxml代码如下
<camera device-position="back" flash="off" binderror="error"
style="height: 100vh;width: 100vw;" mode="scanCode" bindscancode="onGetCode" frame-size="small"></camera>
<!-- 做一个扫码框框 -->
<view class="qrCodeKuang"></view>
pages/scan/scan.wxss代码如下
/* subF/pages/scanCode/scanCode.wxss */
.qrCodeKuang {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 500rpx;
height: 500rpx;
background: linear-gradient(#ffffff, #ffffff) left top,
linear-gradient(#ffffff, #ffffff) left top,
linear-gradient(#ffffff, #ffffff) right top,
linear-gradient(#ffffff, #ffffff) right top,
linear-gradient(#ffffff, #ffffff) right bottom,
linear-gradient(#ffffff, #ffffff) right bottom,
linear-gradient(#ffffff, #ffffff) left bottom,
linear-gradient(#ffffff, #ffffff) left bottom;
background-repeat: no-repeat;
background-size: 6rpx 60rpx, 60rpx 6rpx;
}
pages/scan/scan.js代码如下
Page({
onLoad() {
// 帧数组
this.frameList = [];
this.isEnd = false;
// 相机上下文对象
this.cameraContext = wx.createCameraContext();
this.cameraListener = this.cameraContext.onCameraFrame((frame) => {
// 存储一张帧图片
if (this.frameList.length === 0) {
this.frameList.push({
data: frame.data,
width: frame.width,
height: frame.height,
});
this.stopGetFrame();
}
});
},
// 获取到扫码结果
onGetCode(e) {
console.log("扫码页面获取到扫码结果", e);
this.qrCodeResult = e.detail.result;
if (this.frameList.length === 0 && !this.isEnd) this.startGetFrame();
},
// 开始获取帧图片
startGetFrame() {
this.cameraListener.start();
},
// 停止监听帧数据
stopGetFrame() {
this.cameraListener.stop();
this.transferFrame();
},
// frame转base64
frameToBase64(frameInfo) {
const frameWidth = frameInfo.width;
const frameHeight = frameInfo.height;
return new Promise((resolve, reject) => {
if (!frameInfo) {
reject(new Error("No frame data available"));
return;
}
// 创建离屏 canvas
const offscreenCanvas = wx.createOffscreenCanvas({
type: "2d",
width: frameWidth,
height: frameHeight,
});
const ctx = offscreenCanvas.getContext("2d");
// 创建 ImageData 对象
const imgData = ctx.createImageData(frameWidth, frameHeight);
// 将 ArrayBuffer 数据复制到 ImageData
const uint8Array = new Uint8Array(frameInfo.data);
imgData.data.set(uint8Array);
// 将 ImageData 绘制到 canvas
ctx.putImageData(imgData, 0, 0);
// 将 canvas 内容转换为 base64
const base64 = offscreenCanvas.toDataURL("image/png");
resolve(base64);
});
},
// 去掉前缀
removeBase64Prefix(base64Data) {
return base64Data.replace(/^data:image\/[a-z]+;base64,/, "");
},
// 处理帧数据
async transferFrame() {
console.log("获取到帧数据", this.frameList);
const fs = wx.getFileSystemManager();
let filePath = `${wx.env.USER_DATA_PATH}/example.png`;
const base64 = this.removeBase64Prefix(
await this.frameToBase64(this.frameList[0])
);
fs.writeFile({
filePath,
encoding: "base64",
data: base64,
success: (res) => {
console.log("写入成功", res);
const eventChannel = this.getOpenerEventChannel();
eventChannel.emit("acceptDataFromB", {
data: this.qrCodeResult,
filePath,
});
this.frameList = [];
this.frameList.length = 0;
this.isEnd = true;
// 返回页面再上传文件
wx.navigateBack();
},
fail(err) {
console.error("写入失败", err);
this.frameList = [];
this.frameList.length = 0;
},
});
},
});