Skip to content

Instantly share code, notes, and snippets.

@AnoRebel
Last active August 2, 2023 12:34
Show Gist options
  • Save AnoRebel/ef883adf32db3513f9482f58312bc380 to your computer and use it in GitHub Desktop.
Save AnoRebel/ef883adf32db3513f9482f58312bc380 to your computer and use it in GitHub Desktop.
Bar and QR code generator in Vue 3 using `jsbarcode` and `qrcode`
/**
* Script made from https://github.com/fengyuanchen/vue-qrcode and https://github.com/fengyuanchen/vue-barcode
*/
import { defineComponent, h, watch, ref, onMounted } from "vue"
import * as JsBarcode from "jsbarcode"
import { toCanvas, toDataURL, toString } from "qrcode"
const EVENT_READY = "ready"
export default defineComponent(
(props, { slots, emit }) => {
const root = ref(null)
/**
* Generate Bar/QR code.
*/
const generate = () => {
if (props.type === "barcode") {
JsBarcode(root.value, String(props.value), props.bar_options || {})
return
} else {
const options = props.qr_options || {}
const value = String(props.value)
const done = () => {
emit(EVENT_READY, root.value)
}
switch (props.tag) {
case "canvas":
toCanvas(root.value, value, options, (error: Error) => {
if (error) {
throw error
}
done()
})
break
case "img":
toDataURL(value, options, (error: Error, url: string) => {
if (error) {
throw error
}
root.value.src = url
root.value.onload = done
})
break
case "svg":
toString(value, options, (error: Error, string: string) => {
if (error) {
throw error
}
const div = document.createElement("div")
div.innerHTML = string
const svg = div.querySelector("svg")
if (svg) {
const { attributes, childNodes } = svg
Object.keys(attributes).forEach((key: string) => {
const attribute = attributes[Number(key)]
root.value.setAttribute(attribute.name, attribute.value)
})
Object.keys(childNodes).forEach((key: string) => {
const childNode = childNodes[Number(key)]
root.value.appendChild(childNode.cloneNode(true))
})
done()
}
})
break
default:
}
}
}
onMounted(() => {
if (root.value) {
generate()
}
})
watch(
() => props,
() => {
/**
* Update the Bar/QR Code when props changed.
*/
if (root.value) {
generate()
}
},
{ deep: true, immediate: true }
)
return () => {
return h(props.tag, { ref: "root" }, slots.default)
}
},
{
name: "CodeGenerator",
props: {
/**
* The type of code to generate.
*/
type: {
type: String,
required: true,
default: "qrcode",
validator(value: string) {
// The value must match one of these strings
return ["qrcode", "barcode"].includes(value)
},
},
/**
* The value of the bar code.
*/
value: {
type: String,
default: undefined,
},
/**
* The options for the QR code generator.
* {@link https://github.com/soldair/node-qrcode#qr-code-options}
*/
qr_options: {
type: Object,
default: {},
},
/**
* The options for the bar code generator.
* {@link https://github.com/lindell/JsBarcode#options}
*/
bar_options: {
type: Object,
default: {},
},
/**
* The tag name of the component's root element.
*/
tag: {
type: String,
default: "svg",
validator(value: string) {
// The value must match one of these strings
return ["svg", "canvas", "img"].includes(value)
},
},
},
emits: [EVENT_READY],
}
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment