mirror of
https://github.com/yugasun/qrcode-decoder.git
synced 2026-08-13 12:41:37 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee7b3ea8e8 | ||
|
|
e665a30b60 | ||
|
|
b9b09029ec | ||
|
|
a8f2f06f4f | ||
|
|
564c55743a | ||
|
|
f80b934b71 | ||
|
|
58c9419c2c | ||
|
|
27e88436e3 | ||
|
|
ede323bb2a | ||
|
|
bf8c373a47 | ||
|
|
ebd34c84f6 | ||
|
|
2cede9967c | ||
|
|
95ae10bd90 | ||
|
|
f84b71c352 | ||
|
|
02a4c715f4 | ||
|
|
0cab0e9e0c |
@@ -1,71 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/env",
|
|
||||||
{
|
|
||||||
"modules": false,
|
|
||||||
"targets": {
|
|
||||||
"browsers": [
|
|
||||||
">0.25%"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"useBuiltIns": "usage"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@babel/typescript"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"development": {
|
|
||||||
"plugins": [
|
|
||||||
"@babel/transform-runtime"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"production": {
|
|
||||||
"plugins": [
|
|
||||||
"@babel/transform-runtime",
|
|
||||||
"transform-remove-console"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"test": {
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"@babel/env",
|
|
||||||
{
|
|
||||||
"modules": "commonjs",
|
|
||||||
"targets": {
|
|
||||||
"node": "current"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@babel/typescript"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"@babel/plugin-syntax-dynamic-import",
|
|
||||||
"@babel/plugin-syntax-import-meta",
|
|
||||||
"@babel/plugin-proposal-class-properties",
|
|
||||||
"@babel/plugin-proposal-json-strings",
|
|
||||||
[
|
|
||||||
"@babel/plugin-proposal-decorators",
|
|
||||||
{
|
|
||||||
"legacy": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@babel/plugin-proposal-function-sent",
|
|
||||||
"@babel/plugin-proposal-export-namespace-from",
|
|
||||||
"@babel/plugin-proposal-numeric-separator",
|
|
||||||
"@babel/plugin-proposal-throw-expressions",
|
|
||||||
"@babel/plugin-proposal-export-default-from",
|
|
||||||
"@babel/plugin-proposal-logical-assignment-operators",
|
|
||||||
"@babel/plugin-proposal-optional-chaining",
|
|
||||||
[
|
|
||||||
"@babel/plugin-proposal-pipeline-operator",
|
|
||||||
{
|
|
||||||
"proposal": "minimal"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator",
|
|
||||||
"@babel/plugin-proposal-do-expressions"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
root = true
|
|
||||||
[*]
|
|
||||||
insert_final_newline = true
|
|
||||||
[*.{js,ts}]
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
charset = utf-8
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_OPTIONS: --max-old-space-size=6144
|
|
||||||
# install playwright binary manually (because pnpm only runs install script once)
|
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- release/*
|
|
||||||
- feat/*
|
|
||||||
- fix/*
|
|
||||||
- perf/*
|
|
||||||
- v1
|
|
||||||
- v2
|
|
||||||
pull_request:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
timeout-minutes: 20
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest]
|
|
||||||
node_version: [16]
|
|
||||||
fail-fast: false
|
|
||||||
|
|
||||||
name: "Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}"
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v2.2.2
|
|
||||||
|
|
||||||
- name: Set node version to ${{ matrix.node_version }}
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node_version }}
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Install deps
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm run build
|
|
||||||
|
|
||||||
test:
|
|
||||||
timeout-minutes: 10
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: "Lint: node-16, ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v2.2.2
|
|
||||||
|
|
||||||
- name: Set node version to 16
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Install deps
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: pnpm run test
|
|
||||||
|
|
||||||
lint:
|
|
||||||
timeout-minutes: 10
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: "Lint: node-16, ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v2.2.2
|
|
||||||
|
|
||||||
- name: Set node version to 16
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Install deps
|
|
||||||
run: pnpm install
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: pnpm run build
|
|
||||||
|
|
||||||
- name: Check formatting
|
|
||||||
run: pnpm run prettier
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
node_modules
|
|
||||||
.DS_STORE
|
|
||||||
lerna-debug.log
|
|
||||||
yarn-error.log
|
|
||||||
dist
|
|
||||||
includes
|
|
||||||
tsconfig.tsbuildinfo
|
|
||||||
.env
|
|
||||||
coverage
|
|
||||||
yarn.lock
|
|
||||||
.rpt2_cache
|
|
||||||
|
|
||||||
demo/lib/index.min.js
|
|
||||||
-29
@@ -1,29 +0,0 @@
|
|||||||
node_modules
|
|
||||||
*.map
|
|
||||||
tests
|
|
||||||
test
|
|
||||||
__tests__
|
|
||||||
__test__
|
|
||||||
.github
|
|
||||||
.env*
|
|
||||||
jest.config.js
|
|
||||||
.eslintrc.js
|
|
||||||
.eslintignore
|
|
||||||
.prettierignore
|
|
||||||
prettier.config.js
|
|
||||||
release.config.js
|
|
||||||
commitlint.config.js
|
|
||||||
.editorconfig
|
|
||||||
lerna.json
|
|
||||||
tsconfig.tsbuildinfo
|
|
||||||
tsconfig.json
|
|
||||||
tsconfig.base.json
|
|
||||||
.rpt2_cache
|
|
||||||
.vscode
|
|
||||||
/demo
|
|
||||||
/doc
|
|
||||||
/scripts
|
|
||||||
tslint.json
|
|
||||||
yarn-error.log
|
|
||||||
.babelrc
|
|
||||||
yarn.lock
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
shamefully-hoist=true
|
|
||||||
strict-peer-dependencies=true
|
|
||||||
auto-install-peers=true
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
# Development folders and files #
|
|
||||||
#################################
|
|
||||||
.tmp/
|
|
||||||
node_modules/
|
|
||||||
package.json
|
|
||||||
.travis.yml
|
|
||||||
dist
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 80,
|
|
||||||
"singleQuote": true,
|
|
||||||
"trailingComma": "all",
|
|
||||||
"arrowParens": "always",
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": "*.json",
|
|
||||||
"options": {
|
|
||||||
"parser": "json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2018 Yuga Sun
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
# [qrcode-decoder](https://github.com/yugasun/qrcode-decoder)
|
|
||||||
|
|
||||||
[](http://www.npmtrends.com/qrcode-decoder)
|
|
||||||
[](http://www.npmtrends.com/qrcode-decoder)
|
|
||||||
[](https://github.com/yugasun/qrcode-decoder/blob/master/LICENSE)
|
|
||||||
|
|
||||||
[简体中文](./README.zh-CN.md) | English
|
|
||||||
|
|
||||||
A tool for decoding qrcode.
|
|
||||||
|
|
||||||
## Directory
|
|
||||||
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── demo code demo
|
|
||||||
├── dist build output
|
|
||||||
├── doc docs
|
|
||||||
├── src source code
|
|
||||||
├── test unit test
|
|
||||||
├── CHANGELOG.md change log
|
|
||||||
└── TODO.md todo list
|
|
||||||
```
|
|
||||||
|
|
||||||
## Guide
|
|
||||||
|
|
||||||
Use `npm` to install.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install --save qrcode-decoder
|
|
||||||
```
|
|
||||||
|
|
||||||
Using in webpack:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import QrcodeDecoder from 'qrcode-decoder';
|
|
||||||
```
|
|
||||||
|
|
||||||
Using in browser:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script src="https://unpkg.com/qrcode-decoder@0.3.1/dist/index.min.js"></script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Demo
|
|
||||||
|
|
||||||
### QrcodeDecoder()
|
|
||||||
|
|
||||||
User `new` to create a decoder object.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var qr = new QrcodeDecoder();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### decodeFromImage(img, options)
|
|
||||||
|
|
||||||
Decodes an image from url or an `<img>` element with a `src` attribute set.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromImage(img).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/image.html)
|
|
||||||
|
|
||||||
#### decodeFromVideo(videoElem, options)
|
|
||||||
|
|
||||||
Decodes directly from a video with a well specified `src` attribute
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromVideo(videoElement).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/video.html)
|
|
||||||
|
|
||||||
#### decodeFromCamera(videoElem, options)
|
|
||||||
|
|
||||||
Decodes from a videoElement.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromCamera(videoElem).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/camera.html)
|
|
||||||
|
|
||||||
#### stop()
|
|
||||||
|
|
||||||
Stops the current `qr` from searching for a QRCode.
|
|
||||||
|
|
||||||
## Develop
|
|
||||||
|
|
||||||
Install dependencies:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Build code:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
Run unit test:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
Modify version in `package.json`, run `release` script:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run release
|
|
||||||
```
|
|
||||||
|
|
||||||
Publish
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm publish
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT](./LICENSE)
|
|
||||||
-128
@@ -1,128 +0,0 @@
|
|||||||
# [qrcode-decoder](https://github.com/yugasun/qrcode-decoder)
|
|
||||||
|
|
||||||
[](http://www.npmtrends.com/qrcode-decoder)
|
|
||||||
[](http://www.npmtrends.com/qrcode-decoder)
|
|
||||||
[](https://github.com/yugasun/qrcode-decoder/blob/master/LICENSE)
|
|
||||||
|
|
||||||
简体中文 | [English](./README.md)
|
|
||||||
|
|
||||||
二维码解析工具。
|
|
||||||
|
|
||||||
## 目录介绍
|
|
||||||
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── demo 使用demo
|
|
||||||
├── dist 编译产出代码
|
|
||||||
├── doc 项目文档
|
|
||||||
├── src 源代码目录
|
|
||||||
├── test 单元测试
|
|
||||||
├── CHANGELOG.md 变更日志
|
|
||||||
└── TODO.md 计划功能
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用者指南
|
|
||||||
|
|
||||||
通过 npm 下载安装代码
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install --save qrcode-decoder
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你是 webpack 等环境
|
|
||||||
|
|
||||||
```js
|
|
||||||
import QrcodeDecoder from 'qrcode-decoder';
|
|
||||||
```
|
|
||||||
|
|
||||||
如果你是浏览器环境
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script src="https://unpkg.com/qrcode-decoder@0.3.1/dist/index.min.js"></script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 示例
|
|
||||||
|
|
||||||
### QrcodeDecoder()
|
|
||||||
|
|
||||||
通过 `new` 关键字生成处理对象。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var qr = new QrcodeDecoder();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### decodeFromImage(img, options)
|
|
||||||
|
|
||||||
解析页面中的图片二维码。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromImage(img).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/image.html)
|
|
||||||
|
|
||||||
#### decodeFromVideo(videoElem, options)
|
|
||||||
|
|
||||||
解析页面中的视频中的二维码。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromVideo(videoElement).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/video.html)
|
|
||||||
|
|
||||||
#### decodeFromCamera(videoElem, options)
|
|
||||||
|
|
||||||
通过获取摄像头视频来扫描解析二维码。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromCamera(videoElem).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/camera.html)
|
|
||||||
|
|
||||||
#### stop()
|
|
||||||
|
|
||||||
停止当前视频捕获。
|
|
||||||
|
|
||||||
## 开发
|
|
||||||
|
|
||||||
首次运行需要先安装依赖
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
一键打包生成生产代码
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
运行单元测试,浏览器环境需要手动测试,位于`test/browser`
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
修改 package.json 中的版本号,修改 README.md 中的版本号,修改 CHANGELOG.md,然后发布新版
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run release
|
|
||||||
```
|
|
||||||
|
|
||||||
将新版本发布到 npm
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm publish
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[MIT](./LICENSE)
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import QrcodeDecoder from '../';
|
|
||||||
|
|
||||||
describe('QrcodeDecoder', () => {
|
|
||||||
test('use', async () => {
|
|
||||||
const res = await import('../dist');
|
|
||||||
|
|
||||||
expect(res.default).toEqual(QrcodeDecoder);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('new QrcodeDecoder()', async () => {
|
|
||||||
const qr = new QrcodeDecoder();
|
|
||||||
|
|
||||||
expect(qr).toBeDefined();
|
|
||||||
expect(qr.videoConstraints).toEqual({
|
|
||||||
video: {
|
|
||||||
width: { min: 360, ideal: 720, max: 1080 },
|
|
||||||
height: { min: 360, ideal: 720, max: 1080 },
|
|
||||||
facingMode: { exact: 'environment' },
|
|
||||||
},
|
|
||||||
audio: false,
|
|
||||||
});
|
|
||||||
expect(qr.decodeFromImage).toBeDefined();
|
|
||||||
expect(qr.decodeFromCamera).toBeDefined();
|
|
||||||
expect(qr.decodeFromVideo).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -20,7 +20,7 @@
|
|||||||
var vConsole = new VConsole();
|
var vConsole = new VConsole();
|
||||||
console.log('Hello world');
|
console.log('Hello world');
|
||||||
function main() {
|
function main() {
|
||||||
var qr = new QrcodeDecoder();
|
var qr = new QrcodeDecoder.default();
|
||||||
var video = document.querySelector('#video');
|
var video = document.querySelector('#video');
|
||||||
var start = document.querySelector('#start');
|
var start = document.querySelector('#start');
|
||||||
var stop = document.querySelector('#stop');
|
var stop = document.querySelector('#stop');
|
||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
# Api
|
|
||||||
|
|
||||||
### QrcodeDecoder()
|
|
||||||
|
|
||||||
User `new` to create a decoder object.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var qr = new QrcodeDecoder();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### decodeFromImage(img, options)
|
|
||||||
|
|
||||||
Decodes an image from url or an `<img>` element with a `src` attribute set.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromImage(img).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/image.html)
|
|
||||||
|
|
||||||
#### decodeFromVideo(videoElem, options)
|
|
||||||
|
|
||||||
Decodes directly from a video with a well specified `src` attribute
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromVideo(videoElement).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/video.html)
|
|
||||||
|
|
||||||
#### decodeFromCamera(videoElem, options)
|
|
||||||
|
|
||||||
Decodes from a videoElement.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromCamera(videoElem).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/camera.html)
|
|
||||||
|
|
||||||
#### stop()
|
|
||||||
|
|
||||||
Stops the current `qr` from searching for a QRCode.
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
# Api
|
|
||||||
|
|
||||||
### QrcodeDecoder()
|
|
||||||
|
|
||||||
通过 `new` 关键字生成处理对象。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var qr = new QrcodeDecoder();
|
|
||||||
```
|
|
||||||
|
|
||||||
#### decodeFromImage(img, options)
|
|
||||||
|
|
||||||
解析页面中的图片二维码。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromImage(img).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/image.html)
|
|
||||||
|
|
||||||
#### decodeFromVideo(videoElem, options)
|
|
||||||
|
|
||||||
解析页面中的视频中的二维码。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromVideo(videoElement).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/video.html)
|
|
||||||
|
|
||||||
#### decodeFromCamera(videoElem, options)
|
|
||||||
|
|
||||||
通过获取摄像头视频来扫描解析二维码。
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
qr.decodeFromCamera(videoElem).then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
[Demo](./demo/camera.html)
|
|
||||||
|
|
||||||
#### stop()
|
|
||||||
|
|
||||||
停止当前视频捕获。
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
var vConsole = new VConsole();
|
var vConsole = new VConsole();
|
||||||
function main() {
|
function main() {
|
||||||
var qr = new QrcodeDecoder();
|
var qr = new QrcodeDecoder.default();
|
||||||
|
|
||||||
var btn1 = document.querySelector('button#decode1');
|
var btn1 = document.querySelector('button#decode1');
|
||||||
var btn2 = document.querySelector('button#decode2');
|
var btn2 = document.querySelector('button#decode2');
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
const isDebug = process.env.DEBUG === 'true';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
verbose: true,
|
|
||||||
silent: !isDebug,
|
|
||||||
transform: {
|
|
||||||
'^.+\\.tsx?$': 'ts-jest',
|
|
||||||
},
|
|
||||||
testTimeout: 60000,
|
|
||||||
transform: {
|
|
||||||
'^.+\\.tsx?$': 'ts-jest',
|
|
||||||
},
|
|
||||||
testRegex: '(/__tests__/.*\\.(test|spec))\\.tsx?$',
|
|
||||||
testPathIgnorePatterns: ['/node_modules/', '/dist/', '/demo/'],
|
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
||||||
};
|
|
||||||
Vendored
+2
File diff suppressed because one or more lines are too long
@@ -1,99 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "qrcode-decoder",
|
|
||||||
"version": "0.3.1",
|
|
||||||
"description": "Tool for decoding qrcode",
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"browser": "dist/index.min.js",
|
|
||||||
"unpkg": "dist/index.min.js",
|
|
||||||
"module": "dist/index.esm.js",
|
|
||||||
"types": "dist/index.d.ts",
|
|
||||||
"sideEffects": false,
|
|
||||||
"scripts": {
|
|
||||||
"build": "ts-node -P scripts/tsconfig.json scripts/bundle.ts commonjs,esm,aio && npm run copy-file",
|
|
||||||
"dts": "tsc src/index.ts --declaration --emitDeclarationOnly --outDir './dist'",
|
|
||||||
"prettier": "prettier --check '**/*.{ts,tsx,md}' --config .prettierrc",
|
|
||||||
"prettier:fix": "prettier --write '**/*.{ts,tsx,md}' --config .prettierrc",
|
|
||||||
"test": "jest",
|
|
||||||
"codecov": "jest --coverage && codecov",
|
|
||||||
"copy-file": "cp dist/index.min.js demo/lib",
|
|
||||||
"release": "git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags",
|
|
||||||
"pages": "gh-pages -d demo --remote origin",
|
|
||||||
"demo": "http-server demo -c-1"
|
|
||||||
},
|
|
||||||
"husky": {
|
|
||||||
"hooks": {
|
|
||||||
"pre-commit": "lint-staged"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lint-staged": {
|
|
||||||
"*.{ts,tsx,md}": [
|
|
||||||
"npm run prettier:fix",
|
|
||||||
"git add ."
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@babel/cli": "^7.7.0",
|
|
||||||
"@babel/core": "^7.7.2",
|
|
||||||
"@babel/plugin-proposal-class-properties": "^7.7.0",
|
|
||||||
"@babel/plugin-proposal-decorators": "^7.7.0",
|
|
||||||
"@babel/plugin-proposal-do-expressions": "^7.6.0",
|
|
||||||
"@babel/plugin-proposal-export-default-from": "^7.5.2",
|
|
||||||
"@babel/plugin-proposal-export-namespace-from": "^7.5.2",
|
|
||||||
"@babel/plugin-proposal-function-sent": "^7.7.0",
|
|
||||||
"@babel/plugin-proposal-json-strings": "^7.2.0",
|
|
||||||
"@babel/plugin-proposal-logical-assignment-operators": "^7.2.0",
|
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
|
|
||||||
"@babel/plugin-proposal-numeric-separator": "^7.2.0",
|
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.6.0",
|
|
||||||
"@babel/plugin-proposal-pipeline-operator": "^7.5.0",
|
|
||||||
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
|
||||||
"@babel/plugin-syntax-import-meta": "^7.2.0",
|
|
||||||
"@babel/plugin-transform-runtime": "^7.6.2",
|
|
||||||
"@babel/polyfill": "^7.7.0",
|
|
||||||
"@babel/preset-env": "^7.7.1",
|
|
||||||
"@babel/preset-typescript": "^7.7.2",
|
|
||||||
"@babel/runtime": "^7.7.2",
|
|
||||||
"@types/jest": "^24.9.0",
|
|
||||||
"@types/node": "^13.1.8",
|
|
||||||
"chalk": "^3.0.0",
|
|
||||||
"codecov": "^3.8.1",
|
|
||||||
"cross-env": "^6.0.3",
|
|
||||||
"fancy-log": "^1.3.3",
|
|
||||||
"gh-pages": "^3.1.0",
|
|
||||||
"http-server": "^14.1.0",
|
|
||||||
"husky": "^3.0.9",
|
|
||||||
"jest": "^24.9.0",
|
|
||||||
"lint-staged": "^9.5.0",
|
|
||||||
"prettier": "^1.18.2",
|
|
||||||
"rollup": "^2.38.1",
|
|
||||||
"rollup-plugin-commonjs": "^8.3.0",
|
|
||||||
"rollup-plugin-json": "^3.1.0",
|
|
||||||
"rollup-plugin-node-builtins": "^2.1.2",
|
|
||||||
"rollup-plugin-node-globals": "^1.4.0",
|
|
||||||
"rollup-plugin-node-resolve": "^3.4.0",
|
|
||||||
"rollup-plugin-typescript2": "0.17.1",
|
|
||||||
"rollup-plugin-uglify": "^6.0.4",
|
|
||||||
"ts-jest": "^24.3.0",
|
|
||||||
"ts-node": "^8.4.1",
|
|
||||||
"tslint": "^5.20.1",
|
|
||||||
"tslint-config-prettier": "^1.18.0",
|
|
||||||
"typescript": "^3.7.5"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+https://github.com/yugasun/qrcode-decoder.git"
|
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"node-utils"
|
|
||||||
],
|
|
||||||
"author": "yugasun",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/yugasun/qrcode-decoder/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/yugasun/qrcode-decoder#readme",
|
|
||||||
"dependencies": {
|
|
||||||
"jsqr": "^1.4.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Generated
-7446
File diff suppressed because it is too large
Load Diff
@@ -1,144 +0,0 @@
|
|||||||
import * as path from 'path';
|
|
||||||
import * as rollup from 'rollup';
|
|
||||||
import resolve from 'rollup-plugin-node-resolve';
|
|
||||||
import typescript2 from 'rollup-plugin-typescript2';
|
|
||||||
import { uglify } from 'rollup-plugin-uglify';
|
|
||||||
import globals from 'rollup-plugin-node-globals';
|
|
||||||
import commonjs from 'rollup-plugin-commonjs';
|
|
||||||
import ts from 'typescript';
|
|
||||||
|
|
||||||
import { createLogger } from './logger';
|
|
||||||
|
|
||||||
const logBundle = createLogger('bundle');
|
|
||||||
|
|
||||||
const plugins: rollup.Plugin[] = [
|
|
||||||
resolve({
|
|
||||||
browser: true,
|
|
||||||
jsnext: true,
|
|
||||||
preferBuiltins: true,
|
|
||||||
}),
|
|
||||||
commonjs(),
|
|
||||||
typescript2({
|
|
||||||
tsconfig: path.join(__dirname, '..', 'tsconfig.json'),
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
async function bundleEsm() {
|
|
||||||
const bundle = await rollup.rollup({
|
|
||||||
input: path.join(process.cwd(), 'src/index.ts'),
|
|
||||||
plugins: [...plugins, globals()],
|
|
||||||
external: ['jsqr'],
|
|
||||||
});
|
|
||||||
await bundle.write({
|
|
||||||
file: 'dist/index.esm.js',
|
|
||||||
name: 'QrcodeDecoder',
|
|
||||||
format: 'esm',
|
|
||||||
sourcemap: false,
|
|
||||||
globals: {
|
|
||||||
jsqr: 'jsqr',
|
|
||||||
tslib: 'tslib',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async function bundleUmd() {
|
|
||||||
const bundle = await rollup.rollup({
|
|
||||||
input: path.join(process.cwd(), 'src/index.ts'),
|
|
||||||
plugins: [...plugins],
|
|
||||||
external: ['jsqr'],
|
|
||||||
});
|
|
||||||
await bundle.write({
|
|
||||||
file: 'dist/index.js',
|
|
||||||
exports: 'named',
|
|
||||||
name: 'QrcodeDecoder',
|
|
||||||
format: 'umd',
|
|
||||||
sourcemap: false,
|
|
||||||
globals: {
|
|
||||||
jsqr: 'jsqr',
|
|
||||||
tslib: 'tslib',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bundleCommonjs() {
|
|
||||||
const bundle = await rollup.rollup({
|
|
||||||
input: path.join(process.cwd(), 'src/index.ts'),
|
|
||||||
plugins: [...plugins],
|
|
||||||
external: ['jsqr'],
|
|
||||||
});
|
|
||||||
await bundle.write({
|
|
||||||
file: 'dist/index.js',
|
|
||||||
exports: 'named',
|
|
||||||
name: 'QrcodeDecoder',
|
|
||||||
format: 'commonjs',
|
|
||||||
sourcemap: false,
|
|
||||||
globals: {
|
|
||||||
jsqr: 'jsqr',
|
|
||||||
tslib: 'tslib',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bundleAio() {
|
|
||||||
const bundle = await rollup.rollup({
|
|
||||||
input: path.join(process.cwd(), 'src/index.ts'),
|
|
||||||
plugins: [
|
|
||||||
...plugins,
|
|
||||||
uglify({
|
|
||||||
compress: {
|
|
||||||
drop_debugger: true,
|
|
||||||
drop_console: false,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
await bundle.write({
|
|
||||||
file: 'dist/index.min.js',
|
|
||||||
name: 'QrcodeDecoder',
|
|
||||||
format: 'iife',
|
|
||||||
sourcemap: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bundle() {
|
|
||||||
try {
|
|
||||||
const outputs = process.argv.slice(2)[0].split(',');
|
|
||||||
logBundle(`Creating bundle`);
|
|
||||||
|
|
||||||
if (outputs.indexOf('esm') === -1) {
|
|
||||||
logBundle(`Skipping esm`);
|
|
||||||
} else {
|
|
||||||
logBundle(`Creating esm`);
|
|
||||||
await bundleEsm();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputs.indexOf('umd') === -1) {
|
|
||||||
logBundle(`Skipping umd`);
|
|
||||||
} else {
|
|
||||||
logBundle(`Creating umd`);
|
|
||||||
|
|
||||||
await bundleUmd();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputs.indexOf('commonjs') === -1) {
|
|
||||||
logBundle(`Skipping commonjs`);
|
|
||||||
} else {
|
|
||||||
logBundle(`Creating commonjs`);
|
|
||||||
|
|
||||||
await bundleCommonjs();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (outputs.indexOf('aio') === -1) {
|
|
||||||
logBundle(`Skipping umd aio`);
|
|
||||||
} else {
|
|
||||||
logBundle(`Creating umd aio`);
|
|
||||||
|
|
||||||
await bundleAio();
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
logBundle('Failed to bundle:');
|
|
||||||
logBundle(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bundle();
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import * as l from 'fancy-log';
|
|
||||||
const log = <typeof import('fancy-log')>(<any>(<any>l).default || l);
|
|
||||||
import * as c from 'chalk';
|
|
||||||
const chalk = <import('chalk').Chalk>(c.default || c);
|
|
||||||
|
|
||||||
export function createLogger(name: string): typeof log {
|
|
||||||
const prefix = `> ${chalk.green(name)} `;
|
|
||||||
const logger = <typeof log>log.bind(log, prefix);
|
|
||||||
logger.info = log.info.bind(log, prefix);
|
|
||||||
logger.dir = log.dir.bind(log, prefix);
|
|
||||||
logger.warn = log.warn.bind(log, prefix);
|
|
||||||
logger.error = log.error.bind(log, prefix);
|
|
||||||
return logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
export { chalk as c };
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"module": "commonjs",
|
|
||||||
"target": "es2015",
|
|
||||||
"resolveJsonModule": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-343
@@ -1,343 +0,0 @@
|
|||||||
import { Options } from 'jsqr';
|
|
||||||
import jsQR from 'jsqr';
|
|
||||||
|
|
||||||
const videoSize = {
|
|
||||||
width: { min: 360, ideal: 720, max: 1080 },
|
|
||||||
height: { min: 360, ideal: 720, max: 1080 },
|
|
||||||
};
|
|
||||||
|
|
||||||
class QrcodeDecoder {
|
|
||||||
timerCapture: null | NodeJS.Timeout;
|
|
||||||
canvasElem: null | HTMLCanvasElement;
|
|
||||||
gCtx: null | CanvasRenderingContext2D;
|
|
||||||
stream: null | MediaStream;
|
|
||||||
videoElem: null | HTMLVideoElement;
|
|
||||||
getUserMediaHandler: null;
|
|
||||||
videoConstraints: MediaStreamConstraints;
|
|
||||||
defaultOption: Options;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.timerCapture = null;
|
|
||||||
this.canvasElem = null;
|
|
||||||
this.gCtx = null;
|
|
||||||
this.stream = null;
|
|
||||||
this.videoElem = null;
|
|
||||||
this.getUserMediaHandler = null;
|
|
||||||
this.videoConstraints = {
|
|
||||||
// default use rear camera
|
|
||||||
video: { ...videoSize, facingMode: { exact: 'environment' } },
|
|
||||||
audio: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.defaultOption = { inversionAttempts: 'attemptBoth' };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies if canvas element is supported.
|
|
||||||
*/
|
|
||||||
isCanvasSupported() {
|
|
||||||
const elem = document.createElement('canvas');
|
|
||||||
return !!(elem.getContext && elem.getContext('2d'));
|
|
||||||
}
|
|
||||||
|
|
||||||
_createImageData(target: CanvasImageSource, width: number, height: number) {
|
|
||||||
if (!this.canvasElem) {
|
|
||||||
this._prepareCanvas(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.gCtx!.clearRect(0, 0, width, height);
|
|
||||||
this.gCtx!.drawImage(target, 0, 0, width, height);
|
|
||||||
|
|
||||||
const imageData = this.gCtx!.getImageData(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
this.canvasElem!.width,
|
|
||||||
this.canvasElem!.height,
|
|
||||||
);
|
|
||||||
|
|
||||||
return imageData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the canvas element (which will
|
|
||||||
* receive the image from the camera and provide
|
|
||||||
* what the algorithm needs for checking for a
|
|
||||||
* QRCode and then decoding it.)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param {DOMElement} canvasElem the canvas
|
|
||||||
* element
|
|
||||||
* @param {number} width The width that
|
|
||||||
* the canvas element
|
|
||||||
* should have
|
|
||||||
* @param {number} height The height that
|
|
||||||
* the canvas element
|
|
||||||
* should have
|
|
||||||
* @return {DOMElement} the canvas
|
|
||||||
* after the resize if width and height
|
|
||||||
* provided.
|
|
||||||
*/
|
|
||||||
_prepareCanvas(width: number, height: number) {
|
|
||||||
if (!this.canvasElem) {
|
|
||||||
this.canvasElem = document.createElement('canvas');
|
|
||||||
this.canvasElem.style.width = `${width}px`;
|
|
||||||
this.canvasElem.style.height = `${height}px`;
|
|
||||||
this.canvasElem.width = width;
|
|
||||||
this.canvasElem.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.gCtx = this.canvasElem.getContext('2d');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Based on the video dimensions and the canvas
|
|
||||||
* that was previously generated captures the
|
|
||||||
* video/image source and then paints into the
|
|
||||||
* canvas so that the decoder is able to work as
|
|
||||||
* it expects.
|
|
||||||
* @param {DOMElement} videoElem <video> dom element
|
|
||||||
* @param {Object} options options (optional) - Additional options.
|
|
||||||
* inversionAttempts - (attemptBoth (default), dontInvert, onlyInvert, or invertFirst)
|
|
||||||
* refer to jsqr options: https://github.com/cozmo/jsQR
|
|
||||||
*/
|
|
||||||
async _captureToCanvas(videoElem: HTMLVideoElement, options: Options) {
|
|
||||||
if (this.timerCapture) {
|
|
||||||
clearTimeout(this.timerCapture);
|
|
||||||
}
|
|
||||||
const proms = () => {
|
|
||||||
const p = new Promise(async (resolve) => {
|
|
||||||
let code;
|
|
||||||
if (videoElem.videoWidth && videoElem.videoHeight) {
|
|
||||||
const imageData = this._createImageData(
|
|
||||||
videoElem,
|
|
||||||
videoElem.videoWidth,
|
|
||||||
videoElem.videoHeight,
|
|
||||||
);
|
|
||||||
|
|
||||||
code = jsQR(
|
|
||||||
imageData.data,
|
|
||||||
imageData.width,
|
|
||||||
imageData.height,
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (code) {
|
|
||||||
resolve(code);
|
|
||||||
} else {
|
|
||||||
this.timerCapture = setTimeout(async () => {
|
|
||||||
code = await this._captureToCanvas(videoElem, options);
|
|
||||||
resolve(code);
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.timerCapture = setTimeout(async () => {
|
|
||||||
code = await this._captureToCanvas(videoElem, options);
|
|
||||||
resolve(code);
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await proms();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the video element for receiving
|
|
||||||
* camera's input. Releases a stream if there
|
|
||||||
* was any (resets).
|
|
||||||
*
|
|
||||||
* @param {DOMElement} videoElem <video> dom element
|
|
||||||
* @param {Object} options options (optional) - Additional options.
|
|
||||||
* inversionAttempts - (attemptBoth (default), dontInvert, onlyInvert, or invertFirst)
|
|
||||||
* refer to jsqr options: https://github.com/cozmo/jsQR
|
|
||||||
*/
|
|
||||||
async decodeFromCamera(videoElem: HTMLVideoElement, options: any = {}) {
|
|
||||||
const opts = {
|
|
||||||
...this.defaultOption,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.stop();
|
|
||||||
if (!navigator.mediaDevices.getUserMedia) {
|
|
||||||
throw new Error("Couldn't get video from camera");
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream: MediaStream;
|
|
||||||
try {
|
|
||||||
stream = await navigator.mediaDevices.getUserMedia(this.videoConstraints);
|
|
||||||
} catch (e) {
|
|
||||||
if ((e as OverconstrainedError).name === 'OverconstrainedError') {
|
|
||||||
console.log('[OverconstrainedError] Can not use rear camera.');
|
|
||||||
|
|
||||||
stream = await navigator.mediaDevices.getUserMedia({
|
|
||||||
video: {
|
|
||||||
...videoSize,
|
|
||||||
...{
|
|
||||||
width: opts.width,
|
|
||||||
height: opts.height,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
audio: false,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream) {
|
|
||||||
videoElem.srcObject = stream;
|
|
||||||
// videoElem.src = window.URL.createObjectURL(stream);
|
|
||||||
this.videoElem = videoElem;
|
|
||||||
this.stream = stream;
|
|
||||||
|
|
||||||
const code = await this.decodeFromVideo(videoElem, opts);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares the video element for video file.
|
|
||||||
*
|
|
||||||
* @param {DOMElement} videoElem <video> dom element
|
|
||||||
* @param {Object} options options (optional) - Additional options.
|
|
||||||
* inversionAttempts - (attemptBoth (default), dontInvert, onlyInvert, or invertFirst)
|
|
||||||
* refer to jsqr options: https://github.com/cozmo/jsQR
|
|
||||||
*/
|
|
||||||
async decodeFromVideo(videoElem: HTMLVideoElement, options = {}) {
|
|
||||||
const opts = {
|
|
||||||
...this.defaultOption,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
this.videoElem = videoElem;
|
|
||||||
const code = await this._captureToCanvas(videoElem, opts);
|
|
||||||
return code;
|
|
||||||
} catch (e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes an image from its src.
|
|
||||||
* @param {DOMElement} imageElem
|
|
||||||
* @param {Object} options options (optional) - Additional options.
|
|
||||||
* inversionAttempts - (attemptBoth (default), dontInvert, onlyInvert, or invertFirst)
|
|
||||||
* refer to jsqr options: https://github.com/cozmo/jsQR
|
|
||||||
*/
|
|
||||||
async decodeFromImage(
|
|
||||||
img: HTMLImageElement,
|
|
||||||
options: { crossOrigin?: string } = {},
|
|
||||||
) {
|
|
||||||
let imgDom: HTMLImageElement | null = null;
|
|
||||||
const opts = {
|
|
||||||
...this.defaultOption,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
if (+img.nodeType > 0) {
|
|
||||||
if (!img.src) {
|
|
||||||
throw new Error('The ImageElement must contain a src');
|
|
||||||
}
|
|
||||||
imgDom = img;
|
|
||||||
} else if (typeof img === 'string') {
|
|
||||||
imgDom = document.createElement('img');
|
|
||||||
if (options.crossOrigin) {
|
|
||||||
imgDom.crossOrigin = options.crossOrigin;
|
|
||||||
}
|
|
||||||
imgDom.src = img;
|
|
||||||
const proms = () =>
|
|
||||||
new Promise((resolve) => {
|
|
||||||
imgDom!.onload = () => resolve(true);
|
|
||||||
});
|
|
||||||
await proms();
|
|
||||||
}
|
|
||||||
|
|
||||||
let code = null;
|
|
||||||
if (imgDom) {
|
|
||||||
code = this._decodeFromImageElm(imgDom, opts);
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
_decodeFromImageElm(imgObj: HTMLImageElement, options = {}) {
|
|
||||||
const opts: Options = {
|
|
||||||
...this.defaultOption,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
const imageData = this._createImageData(
|
|
||||||
imgObj,
|
|
||||||
imgObj.width,
|
|
||||||
imgObj.height,
|
|
||||||
);
|
|
||||||
|
|
||||||
const code = jsQR(imageData.data, imageData.width, imageData.height, opts);
|
|
||||||
|
|
||||||
if (code) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases a video stream that was being
|
|
||||||
* captured by prepareToVideo
|
|
||||||
*/
|
|
||||||
stop() {
|
|
||||||
if (this.stream) {
|
|
||||||
const track = this.stream.getTracks()[0];
|
|
||||||
track.stop();
|
|
||||||
this.stream = null;
|
|
||||||
|
|
||||||
// fix: clear black bg after camera capture
|
|
||||||
this.videoElem!.srcObject = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.timerCapture) {
|
|
||||||
clearTimeout(this.timerCapture);
|
|
||||||
this.timerCapture = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the sourceId for the camera to use.
|
|
||||||
*/
|
|
||||||
setGroupId(groupId: string) {
|
|
||||||
if (groupId) {
|
|
||||||
this.videoConstraints.video = {
|
|
||||||
advanced: [{ groupId }],
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
this.videoConstraints.video = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of all available video sources on
|
|
||||||
* the current device.
|
|
||||||
*/
|
|
||||||
async getVideoDevices() {
|
|
||||||
if (navigator.mediaDevices.enumerateDevices) {
|
|
||||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
||||||
return devices.filter((item: MediaDeviceInfo) => {
|
|
||||||
if (item.kind === 'videoinput') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
'Current browser doest not support MediaStreamTrack.getSources',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default QrcodeDecoder;
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "dist",
|
|
||||||
"baseUrl": ".",
|
|
||||||
"composite": true,
|
|
||||||
"declaration": true,
|
|
||||||
"declarationMap": true,
|
|
||||||
"downlevelIteration": true,
|
|
||||||
"emitDecoratorMetadata": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"preserveConstEnums": true,
|
|
||||||
"importHelpers": false,
|
|
||||||
"lib": ["esnext", "dom"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"sourceMap": false,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"strict": true,
|
|
||||||
"target": "es5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["tslint:latest", "tslint-config-prettier"],
|
|
||||||
"rules": {
|
|
||||||
"interface-name": [true, "never-prefix"],
|
|
||||||
"member-access": false,
|
|
||||||
"no-angle-bracket-type-assertion": false,
|
|
||||||
"no-bitwise": false,
|
|
||||||
"no-console": false,
|
|
||||||
"no-default-export": true,
|
|
||||||
"no-empty-interface": false,
|
|
||||||
"no-implicit-dependencies": false,
|
|
||||||
"no-submodule-imports": false,
|
|
||||||
"ordered-imports": [false],
|
|
||||||
"object-literal-sort-keys": false,
|
|
||||||
"object-literal-key-quotes": [true, "as-needed"],
|
|
||||||
"quotemark": [true, "single"],
|
|
||||||
"semicolon": [true, "always", "ignore-bound-class-methods"],
|
|
||||||
"jsx-boolean-value": false
|
|
||||||
},
|
|
||||||
"linterOptions": {
|
|
||||||
"exclude": ["config/**/*.js", "node_modules/**/*.ts"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
var result = document.querySelector('#result');
|
var result = document.querySelector('#result');
|
||||||
var start = document.querySelector('#start');
|
var start = document.querySelector('#start');
|
||||||
var stop = document.querySelector('#stop');
|
var stop = document.querySelector('#stop');
|
||||||
var qr = new QrcodeDecoder();
|
var qr = new QrcodeDecoder.default();
|
||||||
|
|
||||||
start.onclick = startScan;
|
start.onclick = startScan;
|
||||||
|
|
||||||
Reference in New Issue
Block a user