编辑器二维码扫描仪的整合
最近我们在论坛收到一条有趣的帖子,询问是否可以将二维码扫描仪整合到编辑器中。我很高兴地说这确实可行,在本篇博文中,我将演示如何为编辑器创建一个 字段类型外挂程序,使二维码能够读入字段。我已经使用第三方 Instascan 库在您自己的系统中实现了这一点。
在进一步深入探讨之前,这里有一个关于此外挂程序的效果预览。只需编辑或创建新行,然后按“描述”字段输入元素旁边的“扫描”按钮。您应该能够从这里扫描二维码并在输入元素中看到结果。
姓名 | 城市 | 描述 |
---|
快速开始
如果您希望将 Instascan 与编辑器一起用作二维码扫描仪,您可以通过 NPM 安装 Instascan(npm install --save instascan
)或直接在脚本标签中导入 Instascan 来实现。
还需要此整合外挂程序,才能让它与编辑器一起使用,可以从此处下载
最后,(这就是这么容易!)您需要将 fields.type
选项设为 qr
- 例如:
fields: [
{
label: 'Code:',
name: 'code',
type: 'qr'
},
// ...
]
从中您会发现,当您编辑或创建记录时,您可以按您指定为 QR 字段的字段的输入旁边显示的扫描按钮。这随后会将活动信息流显示到您的网络摄像头,当您扫描二维码时,值将显示在输入元素中。
构建外挂程序
使用它足够简单,下面让我们深入了解它是如何工作的,我们调查一下如何为编辑器创建 自定义字段类型外挂程序。
Instascan
首先我们需要一个二维码扫描仪, Instascan 就是我们可用于此目的的库。它自我描述为“实时网络摄像头驱动的 HTML5 二维码扫描仪”,这正是我们所需的。
有几个 API 方法和配置选项,我们在这里不会讨论,但它们可能对您有用,我建议您仔细阅读他们在 github 上的自述文件,这样您才能设置 Instascan 以满足您自己的需求。他们也有一个 演示页面,很好地展示了它们提供的功能。
将 Instascan 与编辑器整合
为了使二维码扫描仪完全可重复使用,并在单个表单中允许多个二维码,我们将为编辑器创建一个 自定义字段类型外挂程序。我们需要为我们的编辑器外挂程序定义三个功能
create
- 当字段首次初始化时调用get
- 从字段中获取值set
- 将值设置到字段中。
create
这是此插件中几乎所有有趣的地方!以下是我们函数的结构,划分为几个部分(当一起使用时,它变得非常大)
create: function (conf) {
create: function (conf) {
// Section 1 - DOM setup, including container
// Section 2 - Instascan setup
// Section 3 - Toggle control
// Section 4 - Close behaviour
return container;
},
我们create
函数中的第一部分用于构造字段的 DOM,因为我们需要汇集几个不同的元素。请注意,我们将 input
元素分配给 conf
对象,这样就可以在其他插件方法中访问它。
// Section 1 - DOM setup
var safeId = DataTable.Editor.safeId(conf.id);
var video = $('<video/>').css({
display: 'none',
'max-width': '100%',
padding: '2% 0%',
});
var input = $('<input id="' + safeId + '"/>');
var scan = $('<button>Scan</button>').css({ margin: '0% 1%' });
var container = $('<div/>').append(input).append(scan).append(video);
conf.qrInput = input;
接下来是初始化 Instascan 实例。我们需要向 Instascan 实例添加一个scan
侦听器。在检测到二维码时,它将被触发,并会将 input
元素的值设置为二维码的值。这里添加的另一个内容是为 input
元素和视频 feed 都添加一个边框,持续半秒钟。这会直观地向用户表明已进行扫描。
var scanner = new Instascan.Scanner({ video: video[0] });
scanner.addListener('scan', function (content) {
input.val(content).css({ border: 'blue 2px solid' });
video.css({ border: 'blue 2px solid' });
setTimeout(() => {
input.css({ border: 'none' });
video.css({ border: 'none' });
}, 500);
});
现在我们有了准备就绪的 Instascan 实例,我们需要使用它!在此插件中,当单击上面定义的scan
按钮元素时,我们将为字段激活相机。为了启用扫描开始,我们使用Instascan.Camera.getCameras
方法,它会返回Promise
,然后使用实例的start()
方法。我们还将显示 video
元素,以便用户可以看到摄像头看到的内容。该切换的反向调用会调用 Instascan 实例的stop()
方法。在这两种情况下,都会更新按钮的内容,以反映单击它的操作。
// Section 3 - Toggle control
scan.on('click', function () {
if (this.innerHTML === 'Scan') {
Instascan.Camera.getCameras()
.then(function (cameras) {
if (cameras.length > 0) {
video.css({ display: 'block' });
scanner.start(cameras[0]);
} else {
console.error('No cameras found.');
}
})
.catch(function (e) {
console.error(e);
});
this.innerHTML = 'Stop';
} else if (this.innerHTML === 'Stop') {
video.css({ display: 'none' });
scanner.stop();
this.innerHTML = 'Scan';
}
});
要添加的最后一项是关闭表单的一个监听器,以确保在我们关闭表单时停止扫描二维码并关闭摄像头。
// Section 4 - Close behaviour
this.on('close', function () {
scanner.stop();
});
get
get 函数非常简单。因为我们在 create 函数中将 input
元素添加到 config
对象中,而且我们在 create
函数中安装的 Instascan scan
事件处理程序会向其写入值,所以我们只需获取它的值
get: function ( conf ) {
return conf.qrInput.val();
}
set
set 函数也相对简单,在这种情况下,将给定的值设置到 input
元素中
set: function (conf, val) {
conf.qrInput.val(val !== null ? val : '');
},
将所有这些函数放到一个插件中,就得到了上面显示的行为。最后的脚本可以从
高级用法
当然,还有更高级的方法来使用与 Editor 集成的 QR 阅读器。您可能有一些表示由逗号分隔的一系列字符串的 QR 代码,您希望将其直接放入一张表中。您可以读取代码,将结果拆分并分别将其放入各个字段,或基于扫描的代码,查询另一个 API 来填写其他字段(例如地理位置 API)。
实现计数系统也是可能的。假设您有一个项目的库存,并且需要扫描每个项目并跟踪每个项目的计数。您可以在表外运行 Instascan,并使用 DataTables API 来在每次扫描时递增每个项目类型的计数。
反馈
与往常一样,我们渴望听到您如何使用 DataTables 和 Editor。请在论坛中给我们留言,告诉我们您如何使用我们的软件,或者如果您遇到任何问题,或者对未来的增强功能有任何想法。我们很想了解是否有人能够将 Instascan 集成到他们的项目中。
根据反馈进行的补充
自发布此博客文章以来,我们已收到一些有关如何在移动设备上改进此文章的反馈,涵盖 Android 和 IOS。感谢 Daniel Bierschwale 提供这些内容。
后置摄像头
大多数移动设备既有后置摄像头,也有前置摄像头,你需要针对哪一个进行操作可能取决于你使用的设备和应用程序。在 Android 上,访问后置摄像头很简单,你只需在第二个摄像头开始扫描即可。这意味着将
scanner.start(cameras[0]);
更改为以下内容
scanner.start(cameras[1]);
但在 IOS 上,此操作并不简单。如这个 Github 问题 中详细说明的那样,你必须修改 camera.js 文件并设置
facingMode: "environment"
但是,这样做的缺点是无法在摄像头之间切换。
IOS 修复首帧冻结问题
在 IOS 上首次打开摄像头时,视频有时不会立即播放,只会显示第一帧。可通过编辑视频标签为
<video autoplay muted id="video" controls="true"/>