Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
vue-qrcode-reader
Advanced tools
A Vue.js component, accessing the device camera and allowing users to read QR-Codes, within the browser
A Vue.js 2 component, accessing the device camera and allowing users to read QR codes, within the browser.
No | Yes | Yes | Yes | 11+ |
decode
eventOnce a stream from the users camera is loaded, it is displayed and continuously scanned for QR codes. Results are indicated by the decode
event. This also accounts for decoded images drag-and-dropped in the area the component occupies.
<qrcode-reader @decode="onDecode"></qrcode-reader>
methods: {
onDecode (decodedString) {
// ...
}
}
You might notice that when you scan the same QR code multiple times in a row,
decode
is still only emitted once. When you hold a QR code in the camera, frames are actually decoded multiple times a second but you don't want to be flooded withdecode
events that often. That's why the last decoded QR code is always cached and only new results are propagated. However, you can clear this internal cache by setting thepaused
prop to true.
detect
eventThe detect
event is quite similar to decode
but it provides more details. decode
only gives you the string encoded by QR codes. detect
additionally
In case of errors decode
also silently fails. For example when a non-image file is drag-and-dropped.
<qrcode-reader @detect="onDetect"></qrcode-reader>
methods: {
async onDetect (promise) {
try {
const {
source, // 'file', 'url' or 'stream'
imageData, // raw image data of image/frame
content, // decoded String
location // QR code coordinates
} = await promise
// ...
} catch (error) {
if (error.name === 'DropImageFetchError') {
// drag-and-dropped URL (probably just an <img> element) from different
// domain without CORS header caused same-origin-policy violation
} else if (error.name === 'DropImageDecodeError') {
// drag-and-dropped file is not of type image and can't be decoded
} else {
// idk, open an issue ¯\_(ツ)_/¯
}
}
}
}
init
eventIt might take a while before the component is ready and the scanning process starts. The user has to be asked for camera access permission first and the camera stream has to be loaded.
If you want to show a loading indicator, you can listen for the init
event. It's emitted as soon as the component is mounted and carries a promise which resolves when everything is ready. The promise is rejected if initialization fails. This can have a couple of reasons.
In Chrome you can't prompt users for permissions a second time. Once denied, users can only manually grant them. Make sure your users understand why you need access to their camera before you mount this component. Otherwise they might panic and deny and then get frustrated because they don't know how to change their decision.
<qrcode-reader @init="onInit"></qrcode-reader>
methods: {
async onInit (promise) {
// show loading indicator
try {
await promise
// successfully initialized
} catch (error) {
if (error.name === 'NotAllowedError') {
// user denied camera access permisson
} else if (error.name === 'NotFoundError') {
// no suitable camera device installed
} else if (error.name === 'NotSupportedError') {
// page is not served over HTTPS (or localhost)
} else if (error.name === 'NotReadableError') {
// maybe camera is already in use
} else if (error.name === 'OverconstrainedError') {
// passed constraints don't match any camera.
// Did you requested the front camera although there is none?
} else {
// browser might be lacking features (WebRTC, ...)
}
} finally {
// hide loading indicator
}
}
}
track
propBy default detected QR codes are visually highlighted. A transparent canvas overlays the camera stream. When a QR code is detected, its location is painted to the canvas. You can enable/disable this feature by passing true
/false
via the track
prop. If tracking is disabled the camera stream is scanned much less frequently. So if you encounter performance problems on your target device, this might help.
You can also pass a function with track
to customize the way the location is painted. This function is called to produce each frame. It receives the location object as the first argument and a CanvasRenderingContext2D
instance as the second argument.
Avoid access to reactive properties in this function (like stuff in
data
,computed
or your Vuex store). The function is called several times a second and might cause memory leaks. If you want to be save don't accessthis
at all.
Say you want to paint in a different color that better fits your overall page theme.
<qrcode-reader :track="repaintLocation"></qrcode-reader>
methods: {
repaintLocation (location, ctx) {
if (location !== null) {
const {
topLeftCorner,
topRightCorner,
bottomLeftCorner,
bottomRightCorner,
} = location
ctx.strokeStyle = 'blue' // instead of red
ctx.beginPath()
ctx.moveTo(topLeftCorner.x, topLeftCorner.y)
ctx.lineTo(bottomLeftCorner.x, bottomLeftCorner.y)
ctx.lineTo(bottomRightCorner.x, bottomRightCorner.y)
ctx.lineTo(topRightCorner.x, topRightCorner.y)
ctx.lineTo(topLeftCorner.x, topLeftCorner.y)
ctx.closePath()
ctx.stroke()
}
}
}
Distributed content will overlay the camera stream, wrapped in a position: absolute
container.
<qrcode-reader>
<b>stuff here overlays the camera stream</b>
</qrcode-reader>
paused
propWith the paused
prop you can prevent further decode
propagation. Functions passed via track
are also stopped being called. Useful for example if you want to validate results one at a time.
When the component is paused the camera stream freezes but is actually still running in the background. The browser will tell you that the camera is still in use. If you want to kill the stream completely you can pass
false
to thecamera
prop.
<qrcode-reader @decode="onDecode" :paused="paused"></qrcode-reader>
data () {
return {
paused: false
}
},
methods: {
onDecode (content) {
this.paused = true
// ...
}
}
camera
propWith the camera
prop you can filter the set of cameras installed on a client device. For example, if you want to access the front camera instead of the rear camera, pass this:
<qrcode-reader :camera="{ facingMode: 'user' }"></qrcode-reader>
This component uses getUserMedia to request camera streams. This method accepts a constraints object. By default this component passes this:
{
audio: false, // don't request microphone access
video: {
facingMode: { ideal: 'environment' }, // use rear camera if available
width: { min: 360, ideal: 680, max: 1920 }, // constrain video width resolution
height: { min: 240, ideal: 480, max: 1080 }, // constrain video height resolution
}
}
This video
part in this object is essentially what you can change using the camera
prop. Note that you only have to pass properties you want to override. All the other default properties on the first depth level are preserved. Here are a few examples:
camera="{ facingMode: 'user' }"
: the facingMode
property is passed and is the only property that changes. width
and height
are still the default value.
camera="false"
: overrides ALL default properties. No camera can match those constraints so no camera is request in the first place. You can use this to turn of the camera at runtime.
camera="{}"
: since an empty object does not contain properties that could override something, this is just like falling back to the default. The same as not using the camera
prop at all or passing undefined
/null
.
camera="true"
: overrides ALL default properties. You will accept any camera type there is. Not recommended though as iOS seems to have trouble when the height
and width
constraints are missing.
If you change this property after initialization, a new camera stream has to be requested and the
init
event will be emitted again.
yarn add vue-qrcode-reader
or using NPM:
npm install --save vue-qrcode-reader
Register component globally:
import Vue from 'vue'
import VueQrcodeReader from 'vue-qrcode-reader'
Vue.use(VueQrcodeReader)
Register locally in other components scope:
import Vue from 'vue'
import { QrcodeReader } from 'vue-qrcode-reader'
Vue.component('my-component', {
components: { QrcodeReader },
// ...
)
⚠️ A css file is included when importing the package. You may have to setup your bundler to embed the css in your page.
You need to include a script and CSS file. You can pull both from unpkg.com. Make sure to replace [VERSION]
with the version you need (for example 1.0.1
):
<link rel="stylesheet" href="https://unpkg.com/vue-qrcode-reader@[VERSION]/dist/vue-qrcode-reader.css"/>
<script src="vue.js"></script>
<script src="https://unpkg.com/vue-qrcode-reader@[VERSION]/dist/vue-qrcode-reader.browser.js"></script>
The plugin should be auto-installed. If not, you can install it manually.
Register component globally:
Vue.use(VueQrcodeReader)
Register locally in other components scope:
Vue.component('my-component', {
components: {
'qrcode-reader': VueQrcodeReader.QrcodeReader
},
// ...
)
FAQs
A set of Vue.js components for detecting and decoding QR codes.
The npm package vue-qrcode-reader receives a total of 15,004 weekly downloads. As such, vue-qrcode-reader popularity was classified as popular.
We found that vue-qrcode-reader demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.