How to Build an Online Shipping Label Generator
A shipping label is an identification label that displays information about packages. It may contain the following info:
- Sender and receiver details (name, phone number, address)
- Tracking number
- Barcodes for reading the info with machines
A standard shipping label is 4x6 inches (10x15 cm).
Sample shipping label:
In this article, we are going to build an online shipping label generator which makes it convenient to create such labels since you can do this on any device that has a browser.
We will use two libraries:
- Dynamsoft Document Viewer: to draw the text and graphics and output a PDF file. A license is needed to use it. You can apply for one here.
- bwip-js: to generate barcodes.
New HTML File
Create a new HTML file with the following template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Online Shipping Label Generator</title>
<style>
h2 {
text-align: center;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
}
</style>
</head>
<body>
<div id="app">
<h2>Online Shipping Label Generator</h2>
</div>
<script></script>
</body>
</html>
Include Dependencies
Include the third-party libraries in the head:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/bwip-js/dist/bwip-js-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@latest/dist/ddv.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@latest/dist/ddv.css">
Layout Design
Create a form for inputting the details. At the bottom of the form, add a button to generate the label and add a button to fill in a preset template. Below the form, display the generated label in Dynamsoft Document Viewer’s Edit Viewer where we can view document images, download the images as a PDF file and print the document.
Code:
<style>
h2 {
text-align: center;
}
#app {
display: flex;
flex-direction: column;
align-items: center;
}
.form {
display: flex;
flex-direction: column;
width: 80%;
border: 1px solid lightgray;
border-radius: 5px;
}
.section {
padding: 5px 20px;
width: 100%;
}
#container {
margin-top: 20px;
width: 80%;
height: 480px;
}
<style/>
<div id="app">
<h2>Online Shipping Label Generator</h2>
<div class="form">
<div class="section">
<h3>Sender:</h3>
<div>
<label for="senderName">
Name: <input id="senderName" type="text"/>
</label>
</div>
<div>
<label for="senderPhone">
Phone: <input id="senderPhone" type="text"/>
</label>
</div>
<div>
<label for="senderAddressLineOne">
Address line 1: <input id="senderAddressLineOne" type="text"/>
</label>
</div>
<div>
<label for="senderAddressLineTwo">
Address line 2: <input id="senderAddressLineTwo" type="text"/>
</label>
</div>
<div>
<label for="senderCity">
City: <input id="senderCity" type="text"/>
</label>
</div>
<div>
<label for="senderState">
State/Province: <input id="senderState" type="text"/>
</label>
</div>
<div>
<label for="senderPostalCode">
Postal code: <input id="senderPostalCode" type="text"/>
</label>
</div>
</div>
<div class="section">
<h3>To:</h3>
<div>
<label for="receiverName">
Name: <input id="receiverName" type="text"/>
</label>
</div>
<div>
<label for="receiverPhone">
Phone: <input id="receiverPhone" type="text"/>
</label>
</div>
<div>
<label for="receiverAddressLineOne">
Address line 1: <input id="receiverAddressLineOne" type="text"/>
</label>
</div>
<div>
<label for="receiverAddressLineTwo">
Address line 2: <input id="receiverAddressLineTwo" type="text"/>
</label>
</div>
<div>
<label for="receiverCity">
City: <input id="receiverCity" type="text"/>
</label>
</div>
<div>
<label for="receiverState">
State/Province: <input id="receiverState" type="text"/>
</label>
</div>
<div>
<label for="receiverPostalCode">
Postal code: <input id="receiverPostalCode" type="text"/>
</label>
</div>
</div>
<div class="section">
<h3>Other:</h3>
<label for="packageNumber">
Package Number: <input id="packageNumber" type="text"/>
</label>
</div>
<div class="section">
<div>
<button onclick="generate()">Generate</button>
<button onclick="fillInTemplate()">Fill in template</button>
</div>
</div>
</div>
<div class="barcodes" style="display: none;">
<div id="code128"><canvas id="code128CVS"></canvas></div>
<div id="qrcode"><canvas id="qrcodeCVS"></canvas></div>
</div>
<div id="container"></div>
</div>
Generate the Label
Next, let’s generate the shipping label with JavaScript.
Initialize Dynamsoft Document Viewer
-
Initialize Dynamsoft Document Viewer with a license. You can apply for one here.
async function initDDV(){ Dynamsoft.DDV.Core.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="; // Public trial license which is valid for 24 hours Dynamsoft.DDV.Core.engineResourcePath = "https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@latest/dist/engine";// Lead to a folder containing the distributed WASM files await Dynamsoft.DDV.Core.loadWasm(); await Dynamsoft.DDV.Core.init(); }
-
Create an edit viewer instance and a document instance. Bind the edit viewer with the document and the container.
function initEditViewer(){ // Configure image filter feature Dynamsoft.DDV.setProcessingHandler("imageFilter", new Dynamsoft.DDV.ImageFilter()); // Create an edit viewer editViewer = new Dynamsoft.DDV.EditViewer({ container: "container", uiConfig: Dynamsoft.DDV.getDefaultUiConfig("editViewer", {includeAnnotationSet: true}), }); const docManager = Dynamsoft.DDV.documentManager; doc = docManager.createDocument(); editViewer.openDocument(doc.uid); }
Generate Barcodes
Use bwip-js to generate barcodes for later usage.
-
Generate the Code 128 barcode for the package number.
let code128CVS = bwipjs.toCanvas("code128CVS",{ bcid: 'code128', // Barcode type text: document.getElementById("packageNumber").value, // Text to encode scale: 5, height: 12, // Bar height, in millimeters includetext: true, // Show human-readable text textxalign: 'center', // Always good to set this textcolor: '000000', // Black text });
-
Generate the QR code for storing extra info.
let text = JSON.stringify(getDataFor2D(),null,0); let qrcodeCVS = bwipjs.toCanvas("qrcodeCVS",{ bcid: 'qrcode', // Barcode type text: text, // Text to encode scale: 5 }); function getDataFor2D(){ let data = { "senderName": document.getElementById("senderName").value, "receiverName": document.getElementById("receiverName").value, "packageNumber": document.getElementById("packageNumber").value } return data; }
There are other types of 2D codes for delivery packages:
- Maxicode: MaxiCode was created by United Parcel Service (UPS) in 1992 for tracking and managing the shipment of packages. It usually contains a Structured Carrier Message about the package.
- Aztec: Aztec Code has the potential to use less space than other matrix barcodes because it does not require a surrounding blank “quiet zone”. Aztec codes are widely used for transport ticketing.
- PDF417: PDF417 is a stacked barcode that can be read with a simple linear scan while other 2D codes need an image sensor.
Here, we just use QR code as an example.
Draw the Text and Graphics
Dynamsoft Document Viewer provides an annotation feature which allows us to draw text and graphics. We are going to use it to create the shipping label.
-
Create an A4-sized document page using canvas and load it to Dynamsoft Document Viewer.
let canvas = document.createElement("canvas"); canvas.width = 2480; //pixels of A4 size in 300 DPI canvas.height = 3508; let context = canvas.getContext('2d'); context.fillStyle = 'rgb(255,255,255)'; context.fillRect(0,0,canvas.width,canvas.height); canvas.toBlob(async (blob) => { await doc.loadSource(blob); });
-
Draw a shipping-label-sized rectangle.
const pageUid = editViewer.indexToUid(doc.pages.length - 1); let width = 900; // 4 inches -> 900 points in 72 DPI let height = 1350; // 6 inches -> 1350 points in 72 DPI let margin = 50; //margin to the A4 page const options = { x: margin, y: margin, width: width, height: height, borderWidth: 5, borderColor: "black", background: "transparent" } const rect = Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "rectangle",options);
-
Draw the QR code.
const qrBlob = await getBarcodeImageBlob("qrcodeCVS"); const qrStampOptions = { x: 90, y: 90, width: 200, height: 200, stamp: qrBlob } const qrStamp = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "stamp", qrStampOptions); function getBarcodeImageBlob(id){ return new Promise((resolve, reject) => { let canvas = document.getElementById(id); canvas.toBlob(async (blob) => { resolve(blob) }); }) }
-
Draw the line between the QR code and the sender’s info.
const firstLineOptions = { startPoint: {x:margin, y:340}, endPoint: {x:width+margin, y:340}, borderWidth: 2, borderColor: "black", background: "black" } const firstline = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "line", firstLineOptions);
-
Draw the sender’s info using a textbox.
const senderTextBoxOptions = { x: 90, y: 400, width: 600, height: 150, textAlign: "left", borderWidth: 0, textContents: getSenderText() }; const senderTextBox = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "textBox", senderTextBoxOptions); function getSenderText(){ let text = document.getElementById("senderName").value + "\n"; text = text + document.getElementById("senderPhone").value + "\n"; text = text + document.getElementById("senderAddressLineOne").value + "\n"; if (document.getElementById("senderAddressLineTwo").value) { text = text + document.getElementById("senderAddressLineTwo").value + "\n"; } text = text + document.getElementById("senderCity").value + ", " + document.getElementById("senderState").value + " " + document.getElementById("senderPostalCode").value; return [{content: text, fontSize: 22}] }
-
Draw the receiver’s info using a textbox with a “To:” textbox in front of it.
const toTextBoxOptions = { x: 90, y: 640, width: 50, height: 150, textAlign: "left", borderWidth: 0, textContents: [{"content":"To:","fontWeight":"bold","fontSize":24}] } const toTextBox = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "textBox", toTextBoxOptions); const receiverTextBoxOptions = { x: 140, y: 640, width: 600, height: 150, textAlign: "left", borderWidth: 0, textContents: getReceiverText() }; const receiverTextBox = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "textBox", receiverTextBoxOptions); function getReceiverText(){ let text = document.getElementById("receiverName").value + "\n"; text = text + document.getElementById("receiverPhone").value + "\n"; text = text + document.getElementById("receiverAddressLineOne").value + "\n"; if (document.getElementById("receiverAddressLineTwo").value) { text = text + document.getElementById("receiverAddressLineTwo").value + "\n"; } text = text + document.getElementById("receiverCity").value + ", " + document.getElementById("receiverState").value + " " + document.getElementById("receiverPostalCode").value; return [{content: text, fontSize: 22}] }
-
Draw the line between the receiver’s info and the package number’s barcode.
const secondLineOptions = { startPoint: {x:margin, y:870}, endPoint: {x:width+margin, y:870}, borderWidth: 2, borderColor: "black", background: "black" } const secondline = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "line", secondLineOptions);
-
Draw the Code128 barcode representing the package number.
const barcodeBlob = await getBarcodeImageBlob("code128CVS"); const code128Canvas = document.getElementById("code128CVS"); const barcodeWidth = width*0.7 const barcodeHeight = code128Canvas.height/(code128Canvas.width/barcodeWidth); const barcodeStampOptions = { x: 90, y: 940, width: barcodeWidth, height: barcodeHeight, stamp: barcodeBlob } const barcodeStamp = await Dynamsoft.DDV.annotationManager.createAnnotation(pageUid, "stamp", barcodeStampOptions);
Save the Shipping Label as a PDF
We can save the shipping label as a PDF file using the document instance’s saveToPdf
function.
const pdfSettings = {
saveAnnotation: "annotation"
};
const blob = await doc.saveToPdf(pdfSettings);
Print the Shipping Label
We can also directly print it using the document instance’s print
function.
doc.print({
printAnnotation: true
});
Source Code
Check out the source code of the demo to have a try.