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:

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:

Online demo

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.

screenshot

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

  1. 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(); 
    }
    
  2. 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.

  1. 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
    });
    
  2. 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.

  1. 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);
    });
    
  2. 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);
    
  3. 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)
        });
      })
    }
    
  4. 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);
    
  5. 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}]
    }
    
  6. 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}]
    }
    
  7. 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);
    
  8. 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);

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.

https://github.com/tony-xlh/shipping-label-generator