Creating Dynamic Cards using Angular JS

in #utopian-io7 years ago (edited)

Repository: https://github.com/angularjs

What will I Learn?

In this tutorial, you will learn the following

  • Implement a dynamic Complimentary card for business
  • Use Angular JS to write text to HTML Canvas
  • Use Angular JS to draw objects / images to Canvas
  • Position elements within a Canvas
  • Download Canvas image

Requirements

For this tutorial, you will need the following

Difficulty

  • Basic

Tutorial Content

Angular JS framework which operates exactly as Javascript, makes coding more simplified and easy to use with other programming languages.

Angular JS framework can be used to achieve variety of functionality and gives user more options and flexibility in implementing their designs and functionalities.

We might already know how to use the HTML Canvas using JavaScript but we intend using Angular JS framework for speed and efficiency. In this tutorial we intend creating dynamic ID card that can be generated by staffs of an organization.

Step 1: Getting Started

For this tutorial, we need to design a template of the ID card carrying fixed element contents for example:

  • Company Logo
  • Company Name
  • Image placeholder

The fixed elements are contents of the ID card that are not meant to change from one staff/user to another.


template.png


Sample.png

You can design your own ID card template using any design tool that you are familiar with and then export the design as either PNG (Portable Network Graphics) or JPEG (Joint Photograph Export Group). But for this project I exported my design as PNG (Portable Network Graphics). A sample of my ID card template is located in assets/img/patterns/template.png and the complete preview is located in assets/img/patterns/sample.png. Those can serve as a guide in designing your own card temple for this tutorial.

Step 2: Starting out template

To begin, we start with the default html template with the head and body tags. We link all necessary script files within the head tag, including our angularjs script. We also need another JS file called app.js where all our angular implementation details will be performed and also another JS script file for Javascript implementation details.

index.html

<!DOCTYPE html>
<html ng-app = "myApp">
  <head>
    <meta charset="utf-8">
    <title>Bussiness Design</title>
    <link rel="shortcut icon" href="assets/img/patterns/dimimpMask.png">
    (html comment removed:  Bootstrap itself )
    <link rel="stylesheet" href="assets/font-awesome/css/font-awesome.min.css">
    <link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    (html comment removed:  Custom styles )
    <link rel="stylesheet" href="assets/css/main.css">
    (html comment removed:  Load js libs only when the page is loaded. )
    <script src="assets/js/jquery.min.js"></script>
    <script src="assets/js/angular.min.js"></script>
    <script src="assets/js/bootstrap.min.js"></script>
    (html comment removed:  Custom template scripts )
    <script src="assets/js/app.js"></script>
    <script src="assets/js/script.js"></script>

  </head>
  <body ng-controller="MainCtrl">

    

  </body>
</html>

Note: Our index.html file contains some new attributes within the html tag and another within the body tag.

  • ng-app="myApp" is an angular directive that triggers angular js to function with the HTML DOM that it covers. It tells angular JS the area of the HTML to take charge of.
  • ng-controller="MainCtrl" is an angular controller created within the angular script app.js for manipulation of a particular area of the HTML DOM.

app.js

(function (){

  var app = angular.module('myApp', []);

  app.controller('MainCtrl', ['$scope', function($scope) {

    
  }]);


}());

We first have to create a directive in our blank app.js script file which allows us create a controller which is in-charger of a particular area of our html file. To create a directive, you call the angular.module() which requires the following parameters;

  • a name which is myApp and;
  • an empty array [] for dependencies such as $scope, $http, $log and so on.

The controller is then built based on the app directive that has been created earlier. We begin the controller with a controller name MainCtrl, a single dependency $scope and then a function with $scope as the only parameter of the function.

NOTE: The $scope parameter can be accessed anywhere within the confines of the MainCtrl controller in the html. Our script.js file will be blank for the mean time and check your console to find out if we have any errors generated before proceeding to the next step.

Step 3: HTML Canvas

The HTML Canvas is an element which is used to draw graphics on a web page, We learn to utilize it better by drawing multiple graphics within the canvas element, including text. We want to create a canvas that draws the template into the canvas. For the design of the site, we will be using bootstrap.

<section>
    <div class="container">
        <h1 class="text-center">Sample Preview and Canvas</h1>
        <div class="col-md-6">
            (html comment removed: <img src="assets/img/patterns/sample.png" class="img img-responsive center-block" alt="Sample ID Card">)
        </div>
        <div class="col-md-6">
            <canvas id="myCanvas" width="555.753" height="344.471" style="border: 1px solid #000"></canvas>
            <button type="button" class="btn btn-success btn-md" ng-click="draw()">Upload Image</button>
        </div>
    </div>
</section>

Within the body tag, we have in container that holds two separate columns. One carries the sample image and the other the canvas element where we will be drawing the template for further manipulations.

  • The canvas element carries and id = "myCanvas" with specified width and height as well as a border so we can see its size.
  • The button tag below the canvas element uses the angular ng-click directive to trigger the draw() function within the angular MainCtrl controller.


Sample and Canvas.JPG

app.js

$scope.draw = function draw () {
    //Draw canvas
    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext("2d");
    // Create Objects
    var imageObj = new Image();
    // Declare objects sources
    imageObj.src = 'assets/img/patterns/template.png';
    // Specify Width and height of each object
    var width = 555.753;
    var height = 344.471;
    // Draw the image objects into the canvas
    imageObj.onload = function() {
    context.drawImage(imageObj, 0, 0, width, height);
    }
};

When the button is clicked, angular executes the draw() to draw the template to the canvas we have created within the HTML tag.

  • Line 3: Gets the canvas element using the canvas id myCanvas

  • Line 4: Creates a drawing object using an HTML built in function getContext() which has properties and methods

  • Line 6 & 8: This steps defines an object to be drawn on the canvas and sets the object / image source.

  • Line 10 & 11: You can also then specify the width and height of the objects should incase they are bigger in size than desired.

  • Line 13 & 14: Draws the image unto the canvas once the object or image loads using the drawImage() providing the following properties:

    context.drawImage(imageObj, hPoint, vPoint, width, height);
    
    • imageObj: The image source to be drawn on the canvas
    • hPoint: The starting point of the imageObj on the horizontal axis
    • vPoint: The starting point of the imageObj on the vertical axis
    • width: The width of imageObj to be drawn
    • height: The height of imageObj to be drawn


Canvas Image.JPG

Step 4: Draw Uploaded Image on Canvas

The template design and sample design now looks similar, but the only difference is the image of the staff, name and other details below the staff image. We will modify our code snippet so we can upload different images and draw the image to the canvas.

First we will remove the previous upload button, and create a new section that will house the upload button which will re-implemented to upload the selected image and then draw the image on the canvas at our specified position.

<section id="upload">
    <div class="container">
        <h1 class="text-center">Upload Image Section</h1>
        <div class="col-md-6 col-md-offset-3">
            <div id='clock' style="margin: auto"></div>
            <input type='file' id='getval' name="background-image" onchange="readURL(event)" style="margin: auto"/><br/>
            <button type="button" id="imageUploadBtn" class="btn btn-success btn-md uploadBtn" ng-click="write()" style="margin: auto">Upload Image</button>
            (html comment removed: <img ng-src="" id="imageP" style="display:none">)
        </div>
    </div>
</section><

Also we need to add the following JavaScript event to help fix the image to the clock div and as well upload the image to the image tag with id="imageP" so we can pick the image source for upload to the canvas.


upload preview.JPG

The code snippet can be added below the body tag.

<script type="text/javascript">
    $("#details").hide();
    $("#final").hide();
    function readURL(event){
        var getImagePath = URL.createObjectURL(event.target.files[0]);
        $('#clock').css('background-image', 'url(' + getImagePath + ')');
        $("#imageP").attr('src', getImagePath);
        $('#imageUploadBtn').css("display", "none");
    }
</script>

Note: This script executes on when the value of the input file type changes using the jquery onchange().

  • This script first gets the image file path to be uploaded and then sets it as a background-image to the div with id="clock" through CSS which acts as a preview to the user.
  • Then the invisible trick not know to the user is the fact that we set the image path as a source to the img tag with id="imgeP" which is hidden by default from the user.

app.js

$scope.draw = function draw () {

    var x = $("#imageP").attr('src');
    //Draw canvas
    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext("2d");
    // Create Objects
    var imageObj = new Image();
    var imageObj_01 = new Image();
    var imageObj_02 = new Image();
    // Declare objects sources
    imageObj.src = 'assets/img/patterns/template.png';
    imageObj_01.src = x;
    imageObj_02.src = 'assets/img/patterns/Logomask.png';
    // Specify Width and height of each object
    var width = 555.753;
    var height = 344.471;
    var width1 = 133;
    var width2 = 57;
    var height1 = 130.6;
    var height2 = 49;
    // Draw the image objects into the canvas
    imageObj.onload = function() {
        context.drawImage(imageObj, 0, 0, width, height);
        context.drawImage(imageObj_01, 339.5, 82, width1, height1);
        context.drawImage(imageObj_02, 373, 195, width2, height2);
    }
    
    $("#upload").hide();
    $("#details").show();

};

NOTE: The upload button looks similar to the previous one, but the difference is that we added new objects to be drawn to the canvas at various positions.

  • For every object to be drawn, we create a new image() and give it a value.
  • Two of the objects (imageObj and imageObj_02) to be drawn , has path already defined by the script except the image uploaded. So to get the image, we retrieve the source of id="imageP".
  • The heights and width of each imageObj is specified to fit the desired design.
  • We then carry out a try and error on the vPoint and hPoint of each imageObj based on the design. This is to enable you fit the image at the right position of the design.
  • The object meant to be be above another is drawn last, so it appears above other objects.
  • The last two lines 29 & 30, is to display a form for user details for drawing and hides the upload image form.


uploaded preview.JPG

Step 5: Add the text to the Design

Including the text at various positions of the canvas is actually implemented same way we implement the positioning of graphics or objects on the canvas. We get the text from users as we tend to allow the template content to be dynamic based on the user details. We use HTML form to collect the details and use the angular ng-model directive for two-way data-binding. We also needed to limit the number of characters per input fields.

Then when the form is submitted, we invoke the angular function called submitWriteUp and pass in the form details as parameters (using angular two-way binding) of the function so we can draw each form detail on the already created canvas myCanvas.

index.html

<section id="details">
    <div class="container" style="margin-top: 50px">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <h1>Enter Required Details</h1>
                <form ng-submit="submitWriteUp(name, position, phone, email, website)">
                    <div class="form-group">
                        <label>Name:</label>
                        <input type="text" ng-model="name" value="" required placeholder="Name" class="form-control" maxlength="24">
                    </div>
                    <div class="form-group">
                        <label>Position:</label>
                        <input type="text" ng-model="position" value="" placeholder="Position" required class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Phone:</label>
                        <input type="text" ng-model="phone" value="" placeholder="Phone number" required class="form-control" maxlength="24">
                    </div>
                    <div class="form-group">
                        <label>Email:</label>
                        <input type="email" ng-model="email" value="" required placeholder="Email" class="form-control">
                    </div>
                    <div class="form-group">
                        <label>Website:</label>
                        <input type="text" ng-model="website" value="" required placeholder="Website" class="form-control" maxlength="6">
                    </div>
                    <div class="form-group">
                        <button type="submit" class="btn btn-success btn-md uploadBtn">Submit Details</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</section>


form preview.JPG

When the form is submitted and we receive the form details, we will draw the details on the canvas at various position based on your design. The steps to drawing the text are as follows:

  • First we select the canvas myCanvas we want to draw on

  • Create a drawing object using an HTML built in function getContext() which has properties and methods.

  • We define the middle of the canvas using canvas.width/2. This gives you the middle of the canvas.

  • For each text to be drawn, you can define:

    • context.font: this defines the font and size of the text to drawn.
    • context.fillStyle: this define the color of the text.
    • context.textAlign: this define alignment of the text whether center, left or right.
  • Then, we can now draw the text on the canvas using the context.fillText() function with the following parameters:

    • name: the text to be drawn on the canvas
    • hPoint: The horizontal position of the text to be drawn
    • vPoint: The vertical position of the text to be drawn

    Note: The vPoint and hPoint can always very based on your template design so you tend to change the values and preview if it matches your desire else continue to change the value of the points.

app.js

$scope.submitWriteUp = function (name, position, phone, email, website) {

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

    var context = canvas.getContext("2d");

    var middle = canvas.width/2;

    context.font = "19px ExoRegular";
    context.fillStyle = "#fff";
    context.textAlign = "center";
    context.fillText(name, middle+130, 40);
    // Other  writeups drawn with different style
    context.font = "17px ExoRegular";
    context.fillText(position, middle+130, 60);
    context.font = "12px ExoRegular";
    context.fillText(phone, middle+150, 264);
    context.fillText(email, middle+139, 288);
    context.fillText(website, middle+142, 313);
};

$scope.submitWriteUp();
$("#final").hide();

Note: To specify new fonts, style and textAlign for different details, you need to specify the values of this parameters before drawing the text.


textPreview.JPG

Step 6: Download the Canvas as image

The final step is to download the generated image within the canvas. One simple way is for the user to right click on the canvas and select "save image as" and select a location where it will be saved and the image will be download.

But we want to hide the form details and display a final preview of the image with a button to download the image by clicking on the button. So we can add some code snippet within the submitWriteUp scope function so that we can attach the image to a final <div> and the button for it to be downloaded.

So we create a new section with an id, within it is a div with id="finalPreview" to hold the final image and then a button for downloading the image with id="download".

index.html

<section id="final">
    <div class="container">
        <div class="row">
            <div class="col-md-4 col-md-offset-4">
                <div id="finalPreview"></div>
                <a id="download" href="" download="utopian.png" target="_blank" >
                <input type="button" value="Download" class="btn btn-success btn-md     uploadBtn"/>
                </a>
            </div>
        </div>
    </div>
</section>

We need to modify our submitWriteUp scope to append the image within the canvas to the finalPreview div and also the href of the download button. We will add the code snippet below within the submitWriteUp scope function.

app.js

    img.src = canvas.toDataURL();
    var src = canvas.toDataURL();
    var image = '(html comment removed: <img src="'+src+'" class="img img-responsive"/>)';
    $('#download').attr('href', src);
    $('#finalPreview').prepend(image);
    $("#final").show();
    $("#details").hide();

Note:

  • Line 1 and 2 converts the image within the canvas to a URL which hold the image data.
  • Line 3 we create an image which will be appended to finalPreview as a preview of the canvas image.
  • Then the source src of the image is added as the href of the download button for download.
  • Then we can now hide the details section and display the final section with the download button.


DownloadOption.JPG

SAMPLE PREVIEW OF THE DOWNLOADED IMAGE


steemjet (2).png

Please uncomment all image tags within the code snippets when using them because while uploading this post, I had image upload conflicts. Thanks

Check out full code snippet for this step in index.html, app.js and main.css.

Video of Work Done

ezgif.com-video-to-gif.gif

Previous Tutorials

Proof of Work Done

I hope you find this tutorial very useful and you can access the complete code for this tutorial in the github repo.

Sort:  

Hi @chri5h,

You have a great tutorial and I just found out a part in your code especially in Step 3: HTML Canvas; as seen in the screenshot below:


In line 3, it should be ended with </h1> instead of </h3>, though it is just some sort of cosmetics error, this breaks the DOM structure as per @mcfarhat.

Additionally, in Step 4: Draw Uploaded Image on Canvas, you've mentioned about onchage()? Is it onchange()?

Hi @josephace135,

Thanks for the correction, it was some syntax error and the other one is onchange() not onchage().

Corrections has been effected. Thanks

You're welcome @chri5h. My pleasure to help :)

Hey @josephace135
Here's a tip for your valuable feedback! @Utopian-io loves and incentivises informative comments.

Contributing on Utopian
Learn how to contribute on our website.

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Hey @chri5h
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

I thank you for your contribution. Here are my thoughts;

  • Normally, I don't like tutorials focused on examples about content creation. But, as this is a good example of how to create a unique project, I gave it a higher score. So I suggest keeping your examples high quality and unique like this.

  • There are several punctuation and structure mistakes in your paragraph. Still, even it's understandable, if you can avoid, it would be better.


Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

I am grateful @yokunjon for your review and thoughts, I will continue in my possible best to improve to be at my best practices.

Congratulations @chri5h! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word STOP

Do not miss the last post from @steemitboard!


Participate in the SteemitBoard World Cup Contest!
Collect World Cup badges and win free SBD
Support the Gold Sponsors of the contest: @good-karma and @lukestokes


Do you like SteemitBoard's project? Then Vote for its witness and get one more award!