Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Print Canvas Pattern for Every Label - Canvas inside Canvas

0.00/5 (No votes)
19 Nov 2014 1  
Address or Barcode Labels by HTML Canvas

Introduction

This article is for developing labels for address or for barcodes by HTML Canvas. There are two parts in the article:

  1. Inner Canvas with fields
  2. Outer Canvas with repeat of inner canvas aligned

Background

I have an assignment in my web project to develop pattern for various label sizes. I found that it can be done by HTML Canvas. I also found many samples for canvas but none of them completely solved my requirement as I have to first develop inner canvas with fields and then with that canvas in repeat mode I want to form the outer canvas. After taking samples here and there, I was able to complete the assignment. I felt that sharing the complete assignment here would be helpful in future for developers to refer.

Using the Code

Now we will directly go to the code. I will post my MVC controller, HTML page and JavaScript code and will explain each.

Let us have a class for Label having properties for dimensions for the labels called LabelType.

public class LabelType
{
    public string LabelTypeName;              //eg:Avery5160
    public int NoofLabelsperLine;
    public int NoofLines;
    public float LabelHeight;
    public float LabelWidth;
    public float LabelSpacingWidth;
    public float LabelSpacingHeight;
    public float LabelSpacingTop;
    public float LabelSpacingLeft;
    public Shape LabelShape;            //Rectangle,Round Rectangle,Circle

    public List<LabelItem> LabelItems;       //Dimensions for each field inside label 
                                             //(for name, address)
}

public class LabelItem : LabelAttribute
{
    public string LabelItemname;           
}

Now let us have the class for each field inside the label called LabelItem.

public class LabelItem : LabelAttribute
{
    public string LabelItemname;     //eg:Name,Address,Country
}

public class LabelAttribute
{
    public float HorizontalPosition;    //Position of field inside label in inches
    public float VerticalPosition;
    public string FontName;            //eg:Arial,Times New Roman
    public float FontSize;             //eg:8 pt,9 pt,10 pt
    public bool IsBoldApplied;     
    public bool IsItalicApplied;
    public bool IsActive;
}

Here is the enum for shape:

public enum Shape
{
    Rectangle,
    RoundRectangle,
    Circle
}

Below is the Post method in MVC controller that sets the dimension of the label.

 [HttpPost]
        public JsonResult GetLabelType(string data, string option)
        {
            LabelType param = new JavaScriptSerializer().Deserialize<LabelType>(data);

            LabelType labelType = SetLabelType(option);

            labelType.LabelItems = new List<LabelItem>();

            for (int i = 0; i < 5; i++)
            {
                LabelItem labelItem = new LabelItem();
                switch (i)
                {
                    case 0:
                        labelItem.LabelItemname = "Dinesh Karthik";
                        break;
                    case 1:
                        labelItem.LabelItemname = "1st Street";
                        break;
                    case 2:
                        labelItem.LabelItemname = "Perungudi";
                        break;
                    case 3:
                        labelItem.LabelItemname = "Chennai";
                        break;
                    case 4:
                        labelItem.LabelItemname = "600103";
                        break;
                }
                labelItem.HorizontalPosition = param.LabelItems[i].HorizontalPosition * 96; 
                labelItem.VerticalPosition = param.LabelItems[i].VerticalPosition * 96;
                labelItem.FontName = param.LabelItems[i].FontName;
                labelItem.FontSize = param.LabelItems[i].FontSize;
                labelItem.IsBoldApplied = param.LabelItems[i].IsBoldApplied;
                labelItem.IsItalicApplied = param.LabelItems[i].IsItalicApplied;
                labelItem.IsActive = param.LabelItems[i].IsActive;
                if (labelItem.IsActive) labelType.LabelItems.Add(labelItem);
            }

            return new JsonResult 
              { Data = labelType, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        }

The Positions are multiplied by 96 for inch to pixel conversion.

The function for Setlabeltype is as below:

  private LabelType SetLabelType(string labelName)
        {
            LabelType labelType = new LabelType();
            
            switch (labelName)
            {
                case "lbAV5167":
                case "lbAV5267":
                case "lbAV5927":
                    labelType = SetLabelDims(0.5, 0.281, 0.5, 2.063, 0.5, 1.75, 4, 20);
                    break;                
                case "lbAV5295":
                    labelType = SetLabelDims(0.5, 0.625, 3.333, 3.937, 3.333, 3.333, 2, 3);
                    labelType.LabelShape = Shape.Circle;
                    break;
///Like this give for all label types
            }
            return labelType;
        }

The code for SetLabelDims is as follows:

 private LabelType SetLabelDims(double SpacingTop, double SpacingLeft, 
double SpacingHeight, double SpacingWidth, 
   double LabelHeight, double LabelWidth, int NumAcross, int NumDown)
        {
            LabelType labelType = new LabelType();
            labelType.LabelSpacingTop = (float)SpacingTop * 96;
            labelType.LabelSpacingLeft = (float)SpacingLeft * 96;
            labelType.LabelSpacingHeight = (float)SpacingHeight * 96;
            labelType.LabelSpacingWidth = (float)SpacingWidth * 96;
            labelType.LabelHeight = (float)LabelHeight * 96;
            labelType.LabelWidth = (float)LabelWidth * 96;
            labelType.NoofLabelsperLine = NumAcross;
            labelType.NoofLines = NumDown;
            labelType.LabelShape = Shape.RoundRectangle;  //default is RoundRectangle
            return labelType;
        }

Now we will see the HTML and JavaScript for the scenario:

Below is the HTML code for controls to change the label dimensions by the user:

<div>
    <label>Name</label>
    <input id="isActiveName" type="checkbox" checked />
    <input id="horizontalName" 
    class="customwidth" value=".1" type="number" />
    <input id="verticalName" 
    class="customwidth" value=".25" type="number" />
    <select id="fontNameName"></select>
    <input id="fontSizeName" 
    class="customwidth" value="8" type="number" />
    <input id="checkBoldName" type="checkbox" />
    <input id="checkItalicName" type="checkbox" />
    
///Like the same give controls for Address 1,Address 2, City and Zip.

</div>

The id of each control will explain its purpose and I think there is no need to explain them in detail.

The screenshot is attached in Controls.png.

Now we will have two canvases. One is for outer div which holds numeric labels inside and another one which is the inner label.

<canvas id="canvas1" 
style="border:1px solid #d3d3d3;background-color:white"></canvas>

<canvas id="canvas" 
style="border:1px solid #d3d3d3;display:none"></canvas>

The dropdown for label type selection is as below:

<select id="Labels"></select>

The dropdown is binded with label names. I think the code for this is out of scope of this article and hence avoided to give here.

Now, we will see the JavaScript code for our case:

 var selectLabel = document.getElementById('Labels').value;

        var sample = {};
        var LabelSample = {};

        LabelSample.HorizontalPosition = document.getElementById("horizontalName").value;
        LabelSample.VerticalPosition = document.getElementById("verticalName").value;
        LabelSample.FontName = document.getElementById("fontNameName").value;
        LabelSample.FontSize = document.getElementById("fontSizeName").value;
        LabelSample.IsBoldApplied = $("#checkBoldName").prop('checked');
        LabelSample.IsItalicApplied = $("#checkItalicName").prop('checked');;
        LabelSample.IsActive = $("#isActiveName").prop('checked');
        sample.LabelItems = [LabelSample];

       ///Like the same get values from Address 1, Address 2,City and Zip

        sample = JSON.stringify(sample);

        $.ajax({
            type: 'POST',
            url: '/Home/GetLabelType',
            data: { data: sample, option: selectLabel },
            dataType: "json",
            async: false,
            success: function (data) {
                promise = data;

                var can = document.getElementById('canvas1');
                var ctx = can.getContext('2d');
                can.width = 816;     //width of a4 size paper
                can.height = 1056;  //height of a4 size paper

                var pattern = document.getElementById('canvas');

                var pctx = pattern.getContext('2d');
                pattern.width = Math.round(promise.LabelWidth);
                pattern.height = Math.round(promise.LabelHeight);

                for (i = 0; i < promise.LabelItems.length; i++) {
                    pctx.font = promise.LabelItems[i].FontSize + "pt " + promise.LabelItems[i].FontName;
                    if (promise.LabelItems[i].IsBoldApplied) {
                        pctx.font = "bold" + " " + pctx.font;
                    }
                    if (promise.LabelItems[i].IsItalicApplied) {
                        pctx.font = "italic" + " " + pctx.font;
                    }
                    pctx.fillText(promise.LabelItems[i].LabelItemname, 
                    promise.LabelItems[i].HorizontalPosition, promise.LabelItems[i].VerticalPosition);
                }

              //DRAW RECTANGE LABEL
                if (promise.LabelShape == "0") {
                    pctx.beginPath();
                    pctx.moveTo(0, 0);
                    pctx.lineTo(promise.LabelWidth, 0);
                    pctx.moveTo(promise.LabelWidth, 0);
                    pctx.lineTo(promise.LabelWidth, promise.LabelHeight);
                    pctx.moveTo(promise.LabelWidth, promise.LabelHeight);
                    pctx.lineTo(0, promise.LabelHeight);
                    pctx.moveTo(0, promise.LabelHeight);
                    pctx.lineTo(0, 0);
                    pctx.closePath();
                    pctx.stroke();
                }

               //DRAW CIRCLE LABEL
                else if (promise.LabelShape == "2") {
                    pctx.beginPath();
                    pctx.arc(promise.LabelWidth / 2, 
                    promise.LabelHeight / 2, promise.LabelWidth / 2, 0, 2 * Math.PI);
                    pctx.closePath();
                    pctx.stroke();
                }

              //DRAW ROUNDED RECTANGLE
                else {
                    pctx.beginPath();
                    pctx.moveTo(0 + 19.2, 0); //0.2 INCH ROUNDED CORNER IS CONVERTED TO 19.2 PX
                    pctx.lineTo(0 + promise.LabelWidth - 19.2, 0);
                    pctx.quadraticCurveTo(0 + promise.LabelWidth, 0, 0 + promise.LabelWidth, 0 + 19.2);
                    pctx.lineTo(0 + promise.LabelWidth, 0 + promise.LabelHeight - 19.2);
                    pctx.quadraticCurveTo(0 + promise.LabelWidth, 0 + 
                    promise.LabelHeight, 0 + promise.LabelWidth - 19.2, 0 + promise.LabelHeight);
                    pctx.lineTo(0 + 19.2, 0 + promise.LabelHeight);
                    pctx.quadraticCurveTo(0, 0 + promise.LabelHeight, 0, 0 + promise.LabelHeight - 19.2);
                    pctx.lineTo(0, 0 + 19.2);
                    pctx.quadraticCurveTo(0, 0, 0 + 19.2, 0);
                    pctx.lineWidth = .5;
                    pctx.closePath();
                    pctx.stroke();
                }

              //LOGIC FOR PRINTING LABELS INSIDE OUTER CANVAS

                var a = 0;
                var b = 0;
                for (i = 1; i <= promise.NoofLines; i++) {
                    for (j = 1; j <= promise.NoofLabelsperLine; j++) {
                        a = ((j - 1) * promise.LabelSpacingWidth + promise.LabelSpacingLeft);
                        b = ((i - 1) * promise.LabelSpacingHeight + promise.LabelSpacingTop);
                        ctx.drawImage(pattern, a, b, promise.LabelWidth, promise.LabelHeight);
                    }
                }
            }
        })
    }

I think the code is self explanatory and so did not explain each line of code.

  • I have not used Canvaspattern because giving uniform space between patterns is difficult.
  • I have referred in net and get the code for Rounded Rectangle in Canvas.
  • Converting Check box value to boolean required prop('checked') function.
  • There are many more difficulties I faced during the development of this project. I have integrated all and presented here.
  • I have not aligned any controls properly in HTML as this is a mere sample and I think the logic is more important as this is not for end user.

I have attached the Label Pattern screenshot in the file Label_Pattern.png.

Please comment for any clarifications.

History

  • 19th November, 2014: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here