diff --git a/hello-world/vue/README.md b/hello-world/vue/README.md
index 3bad4eb0..3290dab2 100644
--- a/hello-world/vue/README.md
+++ b/hello-world/vue/README.md
@@ -1,53 +1,94 @@
# Hello World Sample for Vue3
-[Vue 3](https://v3.vuejs.org/) is version 3 of Vue which is a progressive framework for building user interfaces. Check out the following guide on how to implement Dynamsoft Barcode Reader JavaScript SDK (hereafter called "the library") into a Vue 3 application. Note that in this sample, `TypeScript` is used.
+[Vue 3](https://v3.vuejs.org/) is version 3 of Vue which is a progressive framework for building user interfaces. Check out the following guide on how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a Vue 3 application. Note that in this sample, `TypeScript` is used.
+
+In this guide, we will be using [`dynamsoft-barcode-reader-bundle 10.2.1000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/10.2.1000).
+
+> Note:
+>
+> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks!
+>
+> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have.
## Official Sample
-* Hello World in Vue 3 - Demo
+* Hello World in Vue 3 - Demo
* Hello World in Vue 3 - Source Code
## Preparation
Make sure you have [node](https://nodejs.org/) installed. `node 16.20.1` and `vue 3.3.4` are used in the example below.
-## Create the sample project
+## Quick Start
+
+```cmd
+npm install
+npm run dev
+```
+Then open http://localhost:5173/ to view the sample app.
+
+## Creating the sample project
+
+In this section, we will be creating a Vue application utilizing the Dynamsoft Barcode Reader bundle sdk.
+
+We'll be exploring how you could create a page that not only enables barcode scanning via a webcam or a built-in camera, but also decode barcodes from local images.
+
+By the end of this guide, you'll have a good understanding of the SDK and be ready to discover more ways to use it!
### Create a Bootstrapped Raw Vue Application
```cmd
npm create vue@3
-# When asked 'Add TypeScript?', select 'Yes'.
+```
+
+On installation, you will be prompted to configure your project.\
+You can customize these options according to your preferences.\
+Below is the configuration used for this sample.
+
+```
+√ Project name: ... vue-project
+√ Add TypeScript? ... Yes
+√ Add JSX Support? ... No
+√ Add Vue Router for Single Page Application development? ... No
+√ Add Pinia for state management? ... No
+√ Add Vitest for Unit Testing? ... No
+√ Add an End-to-End Testing Solution? » No
+√ Add ESLint for code quality? ... No
+√ Add Vue DevTools 7 extension for debugging? (experimental) ... No
```
### **CD** to the root directory of the application and install necessary libraries
```cmd
npm install
-npm install dynamsoft-core
-npm install dynamsoft-license
-npm install dynamsoft-utility
-npm install dynamsoft-barcode-reader
-npm install dynamsoft-capture-vision-router
-npm install dynamsoft-camera-enhancer
+npm install dynamsoft-barcode-reader-bundle
```
## Start to implement
-### Add file "cvr.ts" under "/src/" to configure libraries
+### Add file "dynamsoft.config.ts" under "/src/" to configure libraries
```typescript
-import { CoreModule } from 'dynamsoft-core';
-import { LicenseManager } from 'dynamsoft-license';
-import 'dynamsoft-barcode-reader';
+import { CoreModule } from "dynamsoft-core";
+import { LicenseManager } from "dynamsoft-license";
+import "dynamsoft-barcode-reader";
+
+// Configures the paths where the .wasm files and other necessary resources for modules are located.
+CoreModule.engineResourcePaths = {
+ std: "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-std@1.2.10/dist/",
+ dip: "https://cdn.jsdelivr.net/npm/dynamsoft-image-processing@2.2.30/dist/",
+ core: "https://cdn.jsdelivr.net/npm/dynamsoft-core@3.2.30/dist/",
+ license: "https://cdn.jsdelivr.net/npm/dynamsoft-license@3.2.21/dist/",
+ cvr: "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-router@2.2.30/dist/",
+ dbr: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader@10.2.10/dist/",
+ dce: "https://cdn.jsdelivr.net/npm/dynamsoft-camera-enhancer@4.0.3/dist/",
+};
/** LICENSE ALERT - README
* To use the library, you need to first specify a license key using the API "initLicense()" as shown below.
*/
-LicenseManager.initLicense(
- 'DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9'
-);
+LicenseManager.initLicense("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9", true);
/**
* You can visit https://www.dynamsoft.com/customer/license/trialLicense?utm_source=github&product=dbr&package=js to get your own trial license good for 30 days.
@@ -56,18 +97,8 @@ LicenseManager.initLicense(
* LICENSE ALERT - THE END
*/
-CoreModule.engineResourcePaths = {
- std: "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-std@1.2.10/dist/",
- dip: "https://cdn.jsdelivr.net/npm/dynamsoft-image-processing@2.2.30/dist/",
- core: "https://cdn.jsdelivr.net/npm/dynamsoft-core@3.2.30/dist/",
- license: "https://cdn.jsdelivr.net/npm/dynamsoft-license@3.2.21/dist/",
- cvr: "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-router@2.2.30/dist/",
- dbr: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader@10.2.10/dist/",
- dce: "https://cdn.jsdelivr.net/npm/dynamsoft-camera-enhancer@4.0.3/dist/"
-};
-
-// Preload "BarcodeReader" module for reading barcodes. It will save time on the initial decoding by skipping the module loading.
-CoreModule.loadWasm(['DBR']);
+// Optional. Preload "BarcodeReader" module for reading barcodes. It will save time on the initial decoding by skipping the module loading.
+CoreModule.loadWasm(["DBR"]);
```
> Note:
@@ -77,304 +108,313 @@ CoreModule.loadWasm(['DBR']);
### Create and edit the `VideoCapture` component
-* Add a file `VideoCapture.vue` under "/components/" as the `VideoCapture` component. The `VideoCapture` component helps decode barcodes via camera.
+* Create `VideoCapture.vue` under `/components/`. The VideoCapture component helps decode barcodes via camera.
* In `VideoCapture.vue`, add the following code for initializing and destroying some instances.
```vue
+
-
- Results:
+
-
+ Results:
+
```
+> Note:
+>
+> If you're looking to customize the UI, the UI customization feature are provided by the auxiliary SDK "Dynamsoft Camera Enhancer". For more details, refer to our [User Guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/index.html#customize-the-ui)
### Create and edit the `ImageCapture` component
-* Add a file `ImageCapture.vue` under "/components/" as the `ImageCapture` component. The `ImageCapture` component helps decode barcodes in an image.
+* Create `ImageCapture.vue` under `/components/`. The `ImageCapture` component helps decode barcodes in an image.
* In `ImageCapture.vue`, add code for initializing and destroying `CaptureVisionRouter` instance.
```vue
+
-
-
+
+
+
+
+
```
-### Add `VideoCapture` and `ImageCapture` components in `HelloWorld.vue`
+### Add the `VideoCapture` and `ImageCapture` component to `App.vue`
+
+* On `/src/App.vue`, we will edit the component so that it offers buttons to switch components between `VideoCapture` and `ImageCapture`.
+
+* Add following code to `App.vue`.
```vue
+
-
-
Hello World for Vue 3
-
-
-
+
+
+
Hello World for Vue
+
-
-
-
+
+
+
+
+
-```
-
-### Add the `HelloWorld` component to `App.vue`
-
-Edit the file `App.vue` to be like this
-```vue
-
-
-
-
-
-
-
```
+> Note:
+>
+> With Vue's `defineAsyncComponent` we can improve the initial load speed and performance of the application.
+>
+> `defineAsyncComponent` allows us to load components such as `VideoCapture` and `ImageCapture` asynchronously, which means that the component's code is only loaded when it's needed. This will result in a faster initial load times.
+>
+> However, if you're implementing server-side rendering with Vue, using `defineAsyncComponent` might cause issues while loading `VideoCapture` and `ImageCapture` as we use the window/document object. Make sure to load these components on the client-side!
+>
+> Read more: https://vuejs.org/guide/components/async.html
* Try running the project.
```cmd
npm run dev
```
-
-If you have followed all the steps correctly, you should now have a functioning page that allows you to scan barcodes from a webcam or a built-in camera. Additionally, if you want to decode a local image, click the `Decode Image` button and select the image you want to decode. Any barcodes that are detected will be displayed in a dialog.
+If you followed all the steps correctly, you will have a working page that turns one of the cameras hooked to or built in your computer or mobile device into a barcode scanner. Also, if you want to decode a local image, just click the `Decode Image` button and select the image you want to decode. Once barcodes are found, the results will show in a dialog.
### Comment out the following code in `assets/main.css`. (optional)
diff --git a/hello-world/vue/index.html b/hello-world/vue/index.html
index 962d379d..e9c29d99 100644
--- a/hello-world/vue/index.html
+++ b/hello-world/vue/index.html
@@ -1,10 +1,16 @@
-
-
-
- read-video-vue3
+
+
+
+
+
+
+ Hello World for Vue 3 - Dynamsoft Barcode Reader Sample
diff --git a/hello-world/vue/package.json b/hello-world/vue/package.json
index 53d4b78e..77fc7a23 100644
--- a/hello-world/vue/package.json
+++ b/hello-world/vue/package.json
@@ -23,4 +23,4 @@
"vite": "^4.0.0",
"vue-tsc": "^1.0.12"
}
-}
+}
\ No newline at end of file
diff --git a/hello-world/vue/src/App.vue b/hello-world/vue/src/App.vue
index 3c4c188a..4f59da75 100644
--- a/hello-world/vue/src/App.vue
+++ b/hello-world/vue/src/App.vue
@@ -5,6 +5,7 @@ import VideoCapture from "./components/VideoCapture.vue";
import ImageCapture from "./components/ImageCapture.vue";
const mode: Ref = ref("video");
+
@@ -14,11 +15,13 @@ const mode: Ref = ref("video");
-
-
+
+
-
-
+
+
@@ -29,6 +32,7 @@ const mode: Ref = ref("video");
align-items: center;
margin-top: 20px;
}
+
.title .title-logo {
width: 30px;
height: 30px;
@@ -53,13 +57,14 @@ const mode: Ref = ref("video");
border-bottom-left-radius: 10px;
border-right: transparent;
}
+
.top-btns button:nth-child(2) {
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
border-left: transparent;
}
-@media screen and (max-width: 500px) {
+@media screen and (max-width: 800px) {
.top-btns {
width: 70%;
}
diff --git a/hello-world/vue/src/components/ImageCapture.vue b/hello-world/vue/src/components/ImageCapture.vue
index a9a85f85..25392c19 100644
--- a/hello-world/vue/src/components/ImageCapture.vue
+++ b/hello-world/vue/src/components/ImageCapture.vue
@@ -5,34 +5,39 @@ import { EnumCapturedResultItemType } from "dynamsoft-core";
import type { BarcodeResultItem } from "dynamsoft-barcode-reader";
import { CaptureVisionRouter } from "dynamsoft-capture-vision-router";
-const resDiv: Ref = ref(null);
+const resultContainer: Ref = ref(null);
let pCvRouter: Promise;
-let bDestoried = false;
+let isDestroyed = false;
const captureImage = async (e: Event) => {
let files = [...(e.target! as HTMLInputElement).files!];
- (e.target! as HTMLInputElement).value = '';
- resDiv.value!.innerText = "";
+ (e.target! as HTMLInputElement).value = ''; // reset input
+ resultContainer.value!.innerText = "";
try {
+ // ensure cvRouter is created only once
const cvRouter = await (pCvRouter = pCvRouter || CaptureVisionRouter.createInstance());
- if (bDestoried) return;
-
- for(let file of files){
+ if (isDestroyed) return;
+
+ for (let file of files) {
// Decode selected image with 'ReadBarcodes_SpeedFirst' template.
const result = await cvRouter.capture(file, "ReadBarcodes_SpeedFirst");
- if (bDestoried) return;
+ if (isDestroyed) return;
- if(files.length > 1){
- resDiv.value!.innerText += `\n${file.name}:\n`;
+ // Print file name if there's multiple files
+ if (files.length > 1) {
+ resultContainer.value!.innerText += `\n${file.name}:\n`;
}
for (let _item of result.items) {
- if(_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) { continue; }
+ if (_item.type !== EnumCapturedResultItemType.CRIT_BARCODE) {
+ continue; // check if captured result item is a barcode
+ }
let item = _item as BarcodeResultItem;
- resDiv.value!.innerText += item.text + "\n";
+ resultContainer.value!.innerText += item.text + "\n"; // output the decoded barcode text
console.log(item.text);
}
- if (!result.items.length) resDiv.value!.innerText += 'No barcode found\n';
+ // If no items are found, display that no barcode was detected
+ if (!result.items.length) resultContainer.value!.innerText += 'No barcode found\n';
}
} catch (ex: any) {
let errMsg = ex.message || ex;
@@ -42,32 +47,32 @@ const captureImage = async (e: Event) => {
}
onBeforeUnmount(async () => {
- bDestoried = true;
- if(pCvRouter){
- try{
+ isDestroyed = true;
+ if (pCvRouter) {
+ try {
(await pCvRouter).dispose();
- }catch(_){}
+ } catch (_) { }
}
});
-
-
-
+
+
+
-
+
-
+
\ No newline at end of file
diff --git a/hello-world/vue/src/components/VideoCapture.vue b/hello-world/vue/src/components/VideoCapture.vue
index 456457ef..6f32d162 100644
--- a/hello-world/vue/src/components/VideoCapture.vue
+++ b/hello-world/vue/src/components/VideoCapture.vue
@@ -5,49 +5,48 @@ import { CameraEnhancer, CameraView } from "dynamsoft-camera-enhancer";
import { CaptureVisionRouter } from "dynamsoft-capture-vision-router";
import { MultiFrameResultCrossFilter } from "dynamsoft-utility";
-const strErrorDistoryed = 'videoCapture component destoryed';
+const componentDestroyedErrorMsg = "VideoCapture Component Destroyed";
-const uiContainer: Ref = ref(null);
+const cameraViewContainer: Ref = ref(null);
const resultsContainer: Ref = ref(null);
-let resolveInit:()=>void;
-const pInit:Promise = new Promise(r=>{resolveInit=r});
-let bDestoryed = false;
+let resolveInit: () => void;
+const pInit: Promise = new Promise(r => { resolveInit = r });
+let isDestroyed = false;
-let cvRouter:CaptureVisionRouter;
-let cameraEnhancer:CameraEnhancer;
+let cvRouter: CaptureVisionRouter;
+let cameraEnhancer: CameraEnhancer;
onMounted(async () => {
- try{
+ try {
// Create a `CameraEnhancer` instance for camera control and a `CameraView` instance for UI control.
const cameraView = await CameraView.createInstance();
- if(bDestoryed){ throw Error(strErrorDistoryed); } // Check if component is destroyed after every async
+ if (isDestroyed) { throw Error(componentDestroyedErrorMsg); } // Check if component is destroyed after every async
+
cameraEnhancer = await CameraEnhancer.createInstance(cameraView);
- if(bDestoryed){ throw Error(strErrorDistoryed); }
+ if (isDestroyed) { throw Error(componentDestroyedErrorMsg); }
// Get default UI and append it to DOM.
- uiContainer.value!.append(cameraView.getUIElement());
+ cameraViewContainer.value!.append(cameraView.getUIElement());
// Create a `CaptureVisionRouter` instance and set `CameraEnhancer` instance as its image source.
cvRouter = await CaptureVisionRouter.createInstance();
- if(bDestoryed){ throw Error(strErrorDistoryed); }
+ if (isDestroyed) { throw Error(componentDestroyedErrorMsg); }
cvRouter.setInput(cameraEnhancer);
// Define a callback for results.
- cvRouter.addResultReceiver({ onDecodedBarcodesReceived: (result) => {
- if (!result.barcodeResultItems.length) return;
-
- resultsContainer.value!.textContent = '';
- console.log(result);
- for (let item of result.barcodeResultItems) {
- resultsContainer.value!.append(
- `${item.formatString}: ${item.text}`,
- document.createElement('br'),
- document.createElement('hr'),
- );
+ cvRouter.addResultReceiver({
+ onDecodedBarcodesReceived: (result) => {
+ if (!result.barcodeResultItems.length) return;
+
+ resultsContainer.value!.textContent = '';
+ console.log(result);
+ for (let item of result.barcodeResultItems) {
+ resultsContainer.value!.textContent += `${item.formatString}: ${item.text}\n\n`;
+ }
}
- }});
+ });
// Filter out unchecked and duplicate results.
const filter = new MultiFrameResultCrossFilter();
@@ -56,55 +55,57 @@ onMounted(async () => {
// Filter out duplicate barcodes within 3 seconds.
filter.enableResultDeduplication("barcode", true);
await cvRouter.addResultFilter(filter);
- if(bDestoryed){ throw Error(strErrorDistoryed); }
+ if (isDestroyed) { throw Error(componentDestroyedErrorMsg); }
// Open camera and start scanning single barcode.
await cameraEnhancer.open();
- if(bDestoryed){ throw Error(strErrorDistoryed); }
+ if (isDestroyed) { throw Error(componentDestroyedErrorMsg); }
await cvRouter.startCapturing("ReadSingleBarcode");
- if(bDestoryed){ throw Error(strErrorDistoryed); }
+ if (isDestroyed) { throw Error(componentDestroyedErrorMsg); }
+
+ } catch (ex: any) {
- }catch(ex:any){
-
- if((ex as Error)?.message === strErrorDistoryed){
- console.log(strErrorDistoryed);
- }else{
+ if ((ex as Error)?.message === componentDestroyedErrorMsg) {
+ console.log(componentDestroyedErrorMsg);
+ } else {
let errMsg = ex.message || ex;
console.error(errMsg);
alert(errMsg);
}
}
- // distroy function will wait pInit
+ // Resolve pInit promise once initialization is complete.
resolveInit!();
});
+// dispose cvRouter when it's no longer needed
onBeforeUnmount(async () => {
- bDestoryed = true;
- try{
- await pInit;
+ isDestroyed = true;
+ try {
+ await pInit; // Wait for the pInit to complete before disposing resources.
cvRouter?.dispose();
cameraEnhancer?.dispose();
- }catch(_){}
+ } catch (_) { }
});