In this tutorial, you will learn the following
For this tutorial, you will need the following
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.
For this tutorial, we need to design a template of the ID card carrying fixed element contents for example:
The fixed elements are contents of the ID card that are not meant to change from one staff/user to another.
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.
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">
<link rel="stylesheet" href="assets/font-awesome/css/font-awesome.min.css">
<link href="assets/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="assets/css/main.css">
<script src="assets/js/jquery.min.js"></script>
<script src="assets/js/angular.min.js"></script>
<script src="assets/js/bootstrap.min.js"></script>
<script src="assets/js/app.js"></script>
<script src="assets/js/script.js"></script>
</head>
<body ng-controller="MainCtrl">
</body>
</html>
Note: Our
index.htmlfile 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 scriptapp.jsfor 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;
myApp and;[] 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.
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">
</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.
id = "myCanvas" with specified width and height as well as a border so we can see its size.ng-click directive to trigger the draw() function within the angular MainCtrl controller.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 on the horizontal axisimageObj on the vertical axisimageObj to be drawnimageObj to be drawnThe 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>
</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.
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().
id="clock" through CSS which acts as a preview to the user.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.
new image() and give it a value.id="imageP".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>
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:
Then, we can now draw the text on the canvas using the context.fillText() function with the following parameters:
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.
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 = '';
$('#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
finalPreviewas a preview of the canvas image.- Then the source
srcof the image is added as thehrefof the download button for download.- Then we can now hide the
detailssection and display thefinalsection with the download button.
Please uncomment all image tags within the code snippets when using them because while uploading this post, I had image upload conflicts. Thanks
I hope you find this tutorial very useful and you can access the complete code for this tutorial in the github repo.