{"id":398,"date":"2015-02-24T18:12:06","date_gmt":"2015-02-24T12:12:06","guid":{"rendered":"http:\/\/promincproductions.com\/blog\/?p=398"},"modified":"2015-02-26T09:28:09","modified_gmt":"2015-02-26T03:28:09","slug":"html5-canvas-element-and-its-clipto-property-using-fabricjs-and-nodejs","status":"publish","type":"post","link":"https:\/\/promincproductions.com\/blog\/html5-canvas-element-and-its-clipto-property-using-fabricjs-and-nodejs\/","title":{"rendered":"HTML5 Canvas Element and it&#8217;s clipTo property using FabricJS and NodeJS"},"content":{"rendered":"<figure id=\"attachment_716\" aria-describedby=\"caption-attachment-716\" style=\"width: 500px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2014\/07\/html5-canvas-node-js-fabric-js.jpg\" rel=\"attachment wp-att-76\" data-lasso-id=\"309\" data-rel=\"lightbox-gallery-XHJp77Lx\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img decoding=\"async\" class=\"size-medium wp-image-716\" src=\"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2014\/07\/html5-canvas-node-js-fabric-js-500x224.jpg\" alt=\"Using the clipTo function in the HTML5 canvas with FabricJS and NodeJS\" width=\"500\" height=\"224\" \/><\/a><figcaption id=\"caption-attachment-716\" class=\"wp-caption-text\">This article discusses how to use HTML5, FabricJS, and NodeJS to make a dynamic web app for interacting with the HTML5 Canvas. Also, how to clip an image to a bounding box to create a crop function in FabricJS.<\/figcaption><\/figure>\n<p>Sometime ago I was new to the HTML5 canvas &#8211; it sounded cool with unlimited possibilities\u00a0but I had no use case for it at the time and no time to dabble with it. \u00a0But then a project came along and I didn&#8217;t just dip my toe into the canvas world, I jumped head first in! \u00a0Well sort of &#8211; I utilized\u00a0the <a href=\"http:\/\/fabricjs.com\/\" target=\"_blank\" data-lasso-id=\"310\" rel=\"noopener\">FabricJS library<\/a> to try and ease my way in. \u00a0Then, shortly after that, I had to dive into setting up <a href=\"http:\/\/nodejs.org\/\" target=\"_blank\" data-lasso-id=\"311\" rel=\"noopener\">NodeJS<\/a> and created a webserver in NodeJS. \u00a0The NodeJS webserver is used to generate high-resolution print quality images from the design created on the HTML5 canvas.<\/p>\n<p>A quick side note: In this\u00a0application, the website owners print the high resolution images for the client. \u00a0While HTML5 and the canvas could create the print quality images in the browser with out using the NodeJS server, I ran into issues in transferring the images to the web server for the business to print. \u00a0The biggest issue came from mobile devices and file size and memory limitations set there.<\/p>\n<p>So my first dive into HTML5 Canvas and FabricJS, I needed to utilize the clipTo property. \u00a0And I got it to work, but after a ton of fumbling and struggling. \u00a0In hindsight that I learned this week, I didn&#8217;t understand what was happening. \u00a0So hopefully I can help clear that up for some others.<\/p>\n<h2>What is the HTML5 Canvas?<\/h2>\n<p>We need to understand this first. \u00a0At it&#8217;s base level, the &lt;canvas&gt; is nothing more than another HTML element really&#8230; \u00a0If you add this tag you won&#8217;t get anything cool or fancy happening on your page. \u00a0But it&#8217;s more of a powerful placeholder for what is yet to come.<\/p>\n<p>The way you &#8220;paint&#8221; on your canvas (which you actually can with free hand options) is typically through Javascript code. \u00a0This can be done &#8216;statically&#8217;, or dynamically through user interactions. \u00a0And this is where you should get excited. \u00a0Users can modify the canvas through HTML controls you offer them. \u00a0This is what brings the canvas alive and opens the door to some amazing interactivity on your website!<\/p>\n<p>What is unique about the &lt;canvas&gt; tag is that the elements you put on\u00a0the canvas do NOT become a part of the DOM structure. \u00a0So anything that lives on the canvas kind of lives in no mans land so to speak&#8230; \u00a0So what this means is that from a developers standpoint, trying to inspect the contents of the canvas and doing debugging is rather difficult. \u00a0(Again, I&#8217;ve never worked in native Canvas, so I may be wrong here and welcome comments if I&#8217;m off base on this.)<\/p>\n<p>Also,\u00a0since I come from an SEO mindset, I&#8217;ll point out that the canvas will have zero SEO benefit for you, and if your entire\u00a0page is built on the canvas, that means that you will kill your SEO value. \u00a0BUT, adding canvas elements through out your page and site won&#8217;t be a problem &#8211; I&#8217;m just saying you still need traditional text and image content for Search Engines to be able to understand what your page is about. \u00a0Think of this much like Flash &#8211; search engines struggled to understand Flash elements, partially because they were dynamic components and thus the contents of the page would change. \u00a0In essence, canvas is the direct replacement to Flash both in functionality and purpose, so they see it the same way.<\/p>\n<p>I should note that there is a way to view the Canvas in your debugger (this method is for Chrome; I believe something similar can be done in Firebug), but I don&#8217;t find it to be too overly helpful. \u00a0Using the profiling features you can see how the canvas renders and some other details. \u00a0Here is a great tutorial on <a href=\"\/www.html5rocks.com\" target=\"_blank\" data-lasso-id=\"312\" rel=\"noopener\">profiling the canvas\u00a0from HTML5 Rocks<\/a>.<\/p>\n<p>Reference: <a href=\"http:\/\/www.w3schools.com\/html\/html5_canvas.asp\" target=\"_blank\" data-lasso-id=\"313\" rel=\"noopener\">W3Schools<\/a><\/p>\n<h2>FabricJS Brings A Lot to Canvas Development<\/h2>\n<p>I mentioned above that you can use Javascript to write to the canvas and build interactive controls. \u00a0As with most programming tasks, there are various methods to approach this.\u00a0 In my case, I&#8217;ve using\u00a0the FabricJS library to simplify the programming tasks\u00a0&#8211;\u00a0FabricJS is designed to make it a bit easier to work with the &lt;canvas&gt; element.<\/p>\n<p>Seeing as I haven&#8217;t dabbled too deeply into the raw canvas methods I&#8217;m not sure, just how much FabricJS really simplifies things. \u00a0But I will say this &#8211; what would take 5 lines of raw canvas code can be accomplished in 1 line of FabricJS code. \u00a0I did look at some other libraries as well for manipulating the canvas, but they didn&#8217;t seem as robust or as friendly for working with images and text.<\/p>\n<p>As stated in the section above, seeing what is on the canvas and debugging\u00a0it can be tough. \u00a0But this is one of the benefits of working with FabricJS. \u00a0What FabricJS does behind the scenes is builds the contents that go onto the canvas into JSON objects. \u00a0The JSON objects then get rendered into Canvas elements. \u00a0SO, this means that the JSON objects are now javascript variables, which means you can use the Javascript console in your developers tools to see what is on the canvas. \u00a0Additionally, you can easily manipulate your canvas object by modifying the JSON object and calling the render method. \u00a0In other-words, you have full insight and control over your\u00a0canvas element!<\/p>\n<p>I do have to give huge props to <a href=\"http:\/\/fabricjs.com\/team\/\" target=\"_blank\" data-lasso-id=\"314\" rel=\"noopener\">Kangax and Kienz<\/a> for their efforts in developing the FabricJS library though. \u00a0The documentation isn&#8217;t always as clear or abundant as I may like at times, however it is still growing in community and usership and StackOverflow has been a great resource for information. \u00a0The basics are pretty well documented, but as you try to get more advanced and flex what FabricJS can do you need to pull up your sleeves and dig in deep.<\/p>\n<h2>Debugging Canvas with FabricJS<\/h2>\n<p>Using your Javascript console, or via console.log in your scripts, you can output the JSON objects that FabricJS is using for the canvas.<\/p>\n<pre><code>console.log( canvasVariableName.canvas );\r\n<\/code><\/pre>\n<p>I forget the reason, but I have had to use a slightly modified method to do this in my webapp &#8211; I believe it&#8217;s simply because I have two canvases on the same page and one script that auto-detects which canvas you are working on. \u00a0So I&#8217;m using this script instead to accomplish the same thing:<\/p>\n<pre><code>console.log( document.getElementById('CanvasID').fabric );\r\n<\/code><\/pre>\n<p>So now you&#8217;ll output the JSON object that is powering your Canvas. \u00a0Also, from your browsers debugger you can copy this object to the clipboard if you&#8217;d rather view it in a text editor.<\/p>\n<pre><code>copy( document.getElementById('CanvasID').fabric );\r\n<\/code><\/pre>\n<h2>So HTML5 Canvas is JSON, right? No.<\/h2>\n<p>This is where my headaches were&#8230; I worked with FabricJS enough and inspected the JSON objects and just assumed that HTML5 Canvas was built on JSON and JSON alone. \u00a0But I&#8217;m finding that I&#8217;m quite wrong here. \u00a0How it really works is that the JSON object is sent to FabricJS to interpret how to display the HTML5 Canvas. \u00a0So to reiterate this, because this can become important, JSON is nothing more than instructions &#8211; it&#8217;s NOT HTML5 Canvas. \u00a0Keep reading if you don&#8217;t get why that&#8217;s important.<\/p>\n<h2>Wasn&#8217;t this article going to talk about the clipTo property?<\/h2>\n<p>Where I learned that canvas and JSON are not the same\u00a0the hard way, is I was trying to set the clipTo property for an image. \u00a0So my task at hand was to have an image in a bounding box &#8211; so you can resize and reposition the image but it will never spill outside of the box that it lives in. \u00a0In other-words, I&#8217;m trying to build a cropping or picture framing method. \u00a0To do this, you need to clip the image to the bounding box using the clipTo property on the image &#8211; so cut off\u00a0the edges of the image that fall outside of the bounding box. \u00a0Sounds simple, right? \u00a0Well not so much&#8230; (and on a side note, HTML5 has a default method for this that FabricJS does not recognize &#8211; it&#8217;s called the\u00a0<a href=\"http:\/\/www.w3schools.com\/tags\/canvas_globalcompositeoperation.asp\" target=\"_blank\" data-lasso-id=\"315\" rel=\"noopener\">globalCompositeOperation<\/a>. \u00a0There are 12 methods of how you can composite two laters together.) \u00a0<a href=\"http:\/\/jsfiddle.net\/PromInc\/ZxYCP\/4\/\" target=\"_blank\" data-lasso-id=\"316\" rel=\"noopener\">I did find a solution for the bounding box with the clipTo property, and you can find that here<\/a>.<\/p>\n<p>After much work, I was able to accomplish this task, and you can find a working example of how I used <a href=\"http:\/\/jsfiddle.net\/PromInc\/ZxYCP\/\" target=\"_blank\" data-lasso-id=\"317\" rel=\"noopener\">FabricJS to clip and image to a bounding box<\/a> on JS Fiddle.<\/p>\n<p>The concept is this though &#8211; you have an image element, and you have a bounding box element (a rectangle object). \u00a0A function then calculates the offsets for\u00a0the clip to object, which is in essence an\u00a0inverse dimension that accounts for relative position within the canvas and rotation angles. \u00a0Something like that at least. \u00a0;) \u00a0It works and it&#8217;s been a while since I&#8217;ve really dug into the code till I write this, so hopefully this all makes sense still.<\/p>\n<p>This solution does utilize lodash as a method to bind processes together.<\/p>\n<p>There are some limitations to this however:<\/p>\n<ul>\n<li>This will work with text, however when you rotate the text the bounding box seems to drift one way or another&#8230;<\/li>\n<li>The example shown is a rectangle bounding box. \u00a0I&#8217;ve done work with a polygon, however that introduces a whole new set of issues and I was not able to accomplish a full solution at this time.<\/li>\n<\/ul>\n<p>Part of me thinks that it&#8217;s something to do with the version of FabricJS I&#8217;m using &#8211; I think Kangax has sone some bug fixes in the library that may help with these limitations, but I haven&#8217;t had a chance to fully explore correcting these issues. \u00a0(I welcome any insight others may have)<\/p>\n<h2>Don&#8217;t forget about FabricJS on NodeJS!<\/h2>\n<p>When I went to implement this on NodeJS as well for my final rendering, I had to ensure that I was adding in the clipTo property prior to rendering the canvas. \u00a0Since you are not displaying the canvas in NodeJS and only doing a single render of it for output, you just need to update the JSON, render the canvas with FabricJS for Node, and save your image. \u00a0Just that simple.<\/p>\n<p>To expand a bit, what you are doing is sending the JSON object to NodeJS which is running FabricJS. \u00a0So the same process that happens in the browser where FabricJS translates the JSON object into a canvas object happens in the NodeJS server. \u00a0But since this is a server, you can&#8217;t visually see the canvas. \u00a0But I&#8217;m saving this out to an image file. \u00a0This can be done via several methods, but I&#8217;ve found the best method to be to use ImageMagick in NodeJS.<\/p>\n<p>But the moral of the story here is that the NodeJS server needs a similar stack of libraries as the browser &#8211; similar version of FabricJS, lodash, etc. \u00a0Figuring out the right configuration for the NodeJS server was a project in itself for me and someday I may publish what I have going there. \u00a0But for now, the high-level information is here on how to pass the info back and forth.<\/p>\n<p>If you are in need of the NodeJS setup, here is a set of instructions on how to <a title=\"Installing Fabric for NodeJS on Linux\" href=\"https:\/\/promincproductions.com\/blog\/installing-fabricjs-for-nodejs-on-linux\/\" data-lasso-id=\"318\">install NodeJS with FabricJS on a Linux server<\/a>.<\/p>\n<p>I hope this article helps to get you started in the right direction or to clear up some confusion you may have about how to work with the HTML5 canvas element, FabricJS, and how you can utilize NodeJS in your canvas development. \u00a0Feel free to comment or ask questions &#8211; I enjoy having conversations about this setup.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>Sometime ago I was new to the HTML5 canvas &#8211; it sounded cool with unlimited possibilities\u00a0but I had [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":716,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"wprm-recipe-roundup-name":"","wprm-recipe-roundup-description":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[51,12,5],"tags":[],"class_list":["post-398","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fabricjs","category-javascript-jquery","category-website-development"],"jetpack_featured_media_url":"https:\/\/promincproductions.com\/blog\/wp-content\/uploads\/2014\/07\/html5-canvas-node-js-fabric-js.jpg","jetpack_shortlink":"https:\/\/wp.me\/p4BbcR-6q","jetpack_sharing_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/comments?post=398"}],"version-history":[{"count":10,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/398\/revisions"}],"predecessor-version":[{"id":748,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/posts\/398\/revisions\/748"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/media\/716"}],"wp:attachment":[{"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/media?parent=398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/categories?post=398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/promincproductions.com\/blog\/wp-json\/wp\/v2\/tags?post=398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}