<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Deon Rich</title>
    <description>The latest articles on Forem by Deon Rich (@zippcodder).</description>
    <link>https://forem.com/zippcodder</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F678971%2F84273886-0c27-4c1d-9b8b-a28558707327.png</url>
      <title>Forem: Deon Rich</title>
      <link>https://forem.com/zippcodder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/zippcodder"/>
    <language>en</language>
    <item>
      <title>Complete Guide to Building Games in the Browser</title>
      <dc:creator>Deon Rich</dc:creator>
      <pubDate>Thu, 09 Dec 2021 03:47:51 +0000</pubDate>
      <link>https://forem.com/zippcodder/complete-guide-to-building-games-in-the-browser-kp6</link>
      <guid>https://forem.com/zippcodder/complete-guide-to-building-games-in-the-browser-kp6</guid>
      <description>&lt;p&gt;Back in the early days when I first started out in web development, I eventually stumbled across &lt;strong&gt;HTML Canvas&lt;/strong&gt;, and I was immediately &lt;em&gt;hooked&lt;/em&gt;. This discovery would prompt me to create many projects, from things like art programs to photo applications, and eventually even &lt;em&gt;games&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Often I've been revisiting HTML Canvas, and combining it with some of my newer skills like Node.js. Using the two, I've been able to create full blown online games, and honestly have impressed myself with how much I've improved since I first came across the technology, becoming a kind of "canvas connoisseur" if I do say so myself! 😌&lt;/p&gt;

&lt;p&gt;I thought it was about time I shared some of the knowledge I've gained over the years, and figured this was a good way to do it. So, today Im going to share with you my process and methods for &lt;strong&gt;creating games from scratch using HTML Canvas&lt;/strong&gt;, showing you everything you need to know to get started building and designing your own!&lt;/p&gt;

&lt;p&gt;Since this post will be a little lengthy, heres an overview of all of the topics I'll be covering:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
What is HTML Canvas?

&lt;ul&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;li&gt;Drawing Graphics&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Sizing the Game Area

&lt;ul&gt;
&lt;li&gt;Applying a Static Fit&lt;/li&gt;
&lt;li&gt;Applying a Theator Fit&lt;/li&gt;
&lt;li&gt;Applying a Fullscreen Fit&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Creating a Rendering Pipeline&lt;/li&gt;
&lt;li&gt;
Building Sprites

&lt;ul&gt;
&lt;li&gt;Background Sprites&lt;/li&gt;
&lt;li&gt;Object Sprites&lt;/li&gt;
&lt;li&gt;Character Sprites&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Movement and Controls

&lt;ul&gt;
&lt;li&gt;Implementing Joysticks&lt;/li&gt;
&lt;li&gt;Joystick Movement&lt;/li&gt;
&lt;li&gt;Keyboard Controls&lt;/li&gt;
&lt;li&gt;Character Rotation&lt;/li&gt;
&lt;li&gt;Static vs Dynamic Movement&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Collision Detection

&lt;ul&gt;
&lt;li&gt;Squares and Rectangles&lt;/li&gt;
&lt;li&gt;Circles&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;Putting it All Together&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just as a heads up, Im going to assume you have somewhat strong knowledge of Javascript and the DOM as I go through this guide, so I wont be explaining any syntax or basic concepts, only concepts related to HTML Canvas. Throughout this post I'll be explaining the key concepts used in my personal process, and then lastly in the final chapter I'll show a simple game I've created to showcase those concepts. But with that out of the way, lets get into it! 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HTML Canvas? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The HTML &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element, or &lt;strong&gt;Canvas API&lt;/strong&gt; as it's also called, is a special HTML Element used for creating graphics, similar to its counterpart &lt;strong&gt;SVG&lt;/strong&gt; which is also used for creating graphics on the web. Unlike SVG however, HTML Canvas is built for &lt;em&gt;speed&lt;/em&gt; and the rendering of graphics programmatically on the fly.&lt;/p&gt;

&lt;p&gt;The API consists of the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element, which is used as a container for our graphics, and contains a whole plethora of properties and methods used for drawing things like shapes, images, text, 3d models and more onto it, as well as applying transformation on said elements.&lt;/p&gt;

&lt;p&gt;Because its so simple, fast and versatile its applied in a wide range of web applications like games (2D and 3D), video chat, animations, art programs and everything in between. But before we start applying it for &lt;em&gt;our&lt;/em&gt; game, let's get into how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To get started with HTML Canvas, we'll need to first add it into our HTML. The &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element has no children, but text can be added between its tags to serve as the text to be shown to a user in the case that their browser dosen't support Canvas.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;canvas&amp;gt;&lt;/span&gt;Sorry, your browser dosen't support HTML Canvas!&lt;span class="nt"&gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By default, the dimensions of the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element are &lt;strong&gt;300x150&lt;/strong&gt;(px), but it can be resized in CSS. Note that this may alter the aspect ratio of the canvas's content, and it may be stretched as a result of resizing, but I'll get more into that later.&lt;/p&gt;

&lt;p&gt;To breifly give you an introduction to the use of HTML Canvas (before we jump into the good stuff), I'll quickly go over each of the most important methods and properties you need to know to get started. Before we can render anything however, we first need to get a reference to the canvas's &lt;strong&gt;context&lt;/strong&gt; using the &lt;code&gt;canvasElement.getContext()&lt;/code&gt; method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// get a reference to our canvas's context&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;canvasElement.getContext()&lt;/code&gt; method takes 2 parameters. One is the &lt;strong&gt;context type&lt;/strong&gt;, and another is the &lt;strong&gt;context attributes&lt;/strong&gt;, however context attributes are irrelevant in our case, and can be ommited. The main two values for the context type are &lt;code&gt;"2d"&lt;/code&gt; and &lt;code&gt;"webgl"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Passing it a &lt;code&gt;"2d"&lt;/code&gt; context specifies that we want a 2D rendering context, and &lt;code&gt;canvasElement.getContext()&lt;/code&gt; will return a &lt;code&gt;CanvasRenderingContext2D&lt;/code&gt; object, containing properties and methods for rendering 2D graphics onto our canvas. Passing &lt;code&gt;"webgl"&lt;/code&gt;, will return a &lt;code&gt;WebGLRenderingContext&lt;/code&gt; object, which contains properties and methods for rendering 3D graphics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://webglfundamentals.org/" rel="noopener noreferrer"&gt;WebGL&lt;/a&gt; as you may have heard of before, is a Javascript API for rendering 3D graphics, and is a very popular choice for creating 3D games on the web. The API however is very complex, which is why people usually opt to use libraries like &lt;a href="https://threejsfundamentals.org/threejs/lessons/threejs-fundamentals.html" rel="noopener noreferrer"&gt;Three.js&lt;/a&gt; to interact with it. &lt;/p&gt;

&lt;p&gt;In this guide, we'll be using a 2D rendering context which is much simpler, but if you're interested in either Three.js or WebGL, you can check out some of the resources linked at the end of this article.&lt;/p&gt;

&lt;p&gt;Anyway, let's take a look at some properties and rendering methods..👇&lt;/p&gt;

&lt;h3&gt;
  
  
  Drawing Graphics &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Quickly, lets go over the main rendering methods and properties we'll be using to create our game. If any of these properties or methods dont seem clear, they'll become clearer as we apply them later in this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;beginPath()&lt;/code&gt;: Starts a new "path", which means ties with previous renderings are cut. The path is all of the drawing commands that have been called up untill the current point. If you were to stroke a rectangle using &lt;code&gt;rect()&lt;/code&gt; and &lt;code&gt;stroke()&lt;/code&gt;, and then fill a rectangle using &lt;code&gt;rect()&lt;/code&gt; and &lt;code&gt;fill()&lt;/code&gt;, the stroked rectangle would get filled as well because both rectangles are part of the same path. Thus when &lt;code&gt;fill()&lt;/code&gt; is called both rectangles are filled. This method prevents this from ocurring by starting a new path. Later you'll see this in action. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;stroke()&lt;/code&gt;: Used to stroke (or line) the current path. Lines and shapes wont be stroked by default, so this should always be called explicitly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fill()&lt;/code&gt;: Used to fill the current path. Lines and shapes wont be filled by default, so this should be always called explicitly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;moveTo(x,y)&lt;/code&gt;: Moves the pen (the current coordinates from which to start drawing from) to &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;lineTo(x,y)&lt;/code&gt;: Draws a line form the current pen coordinates to &lt;code&gt;x&lt;/code&gt;and &lt;code&gt;y&lt;/code&gt; coordinates. Line wont show unless &lt;code&gt;stroke()&lt;/code&gt; is used after.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;rect(x,y,width,height)&lt;/code&gt;: Draws a rectangle whose top left corner is located at &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, and whose dimensions are &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;. Wont show unless &lt;code&gt;stroke()&lt;/code&gt; or &lt;code&gt;fill()&lt;/code&gt; are explicitly called after.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;strokeRect(x,y,width,height)&lt;/code&gt;: Same as &lt;code&gt;rect()&lt;/code&gt; but strokes (lines) the rectangle in the same function call (no need to call &lt;code&gt;stroke()&lt;/code&gt; afterwards).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fillRect(x,y,width,height)&lt;/code&gt;: Same as &lt;code&gt;strokeRect()&lt;/code&gt;, but fills the rectangle in the same function call instead of stroking it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;clearRect(x,y,width,height)&lt;/code&gt;: Same as &lt;code&gt;fillRect()&lt;/code&gt;, but fill clear out (erase) the area of space specified. This is often used to clear the canvas for the next frame, as you'll see later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;drawImage(image,x,y,width,height)&lt;/code&gt;: Renders a given image (&lt;code&gt;image&lt;/code&gt;) onto the canvas located at x and y width the given &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt;. Usually an &lt;code&gt;HTMLImageElement&lt;/code&gt; created through the &lt;code&gt;Image()&lt;/code&gt; constructor is used as the &lt;code&gt;image&lt;/code&gt; value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fillText(text,x,y)&lt;/code&gt;: Creates text specified by &lt;code&gt;text&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. Settings such as font and text alignment can be set using additional properties, which i wont go over here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;arc(x,y,radius,startAngle,endAngle,direction)&lt;/code&gt;: Draws an arc centered at &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates, which has a radius of &lt;code&gt;radius&lt;/code&gt;, starts at the angle &lt;code&gt;startAngle&lt;/code&gt; and ends at the angle &lt;code&gt;endAngle&lt;/code&gt; (both given in radians).&lt;strong&gt;To create a circle, set &lt;code&gt;startAngle&lt;/code&gt; to 0 and &lt;code&gt;endAngle&lt;/code&gt; to &lt;code&gt;2*Math.PI&lt;/code&gt;&lt;/strong&gt;. &lt;code&gt;direction&lt;/code&gt; specifies weather the arc is drawn counter clockwise, the default being clockwise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;strokeStyle&lt;/code&gt;: This property sets the color which will be used in strokes (lines). Can be any valid CSS color value. The new stroke color will be applied to everything drawn after its been set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;fillStyle&lt;/code&gt;: Sets the fill color. The new fill color will be applied to everything drawn after its been set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;globalAlpha&lt;/code&gt;: Sets the opacity. The new opacity will be applied to everything drawn after its been set.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the principle methods and properties that we'll be using to render our game onto the canvas, and draw each element from backgrounds, to characters and even on-screen controls for mobile users.&lt;/p&gt;

&lt;p&gt;To keep this section as short as possible, i've only gone over the essencials. But, theres a &lt;em&gt;ton&lt;/em&gt; of additional useful properties and methods you can use to acheive all kinds of stuff (some of which we will see later on). You can explore them &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you're interested. &lt;/p&gt;

&lt;p&gt;Don't worry about it if it's hard to visualize any of these, as you'll see them in action further along. Any tips or other relevant information will be explained as this guide progresses. But now that we understand &lt;em&gt;what&lt;/em&gt; we're using to create our game and a little about how to use it, let's look at the first step in implementing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sizing the Game Area &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The first step we need to take before drawing any game elements onto our canvas is to determine what kind of sizing we'll use, and how we want the game area to behave on different screen sizes. Before I show the methods I have for doing so, it's important we go over the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes of the canvas.&lt;/p&gt;

&lt;p&gt;As before mentioned, the default dimensions of the canvas are &lt;strong&gt;300x150&lt;/strong&gt;, but this also serves as the default dimensions of the canvas's &lt;em&gt;content&lt;/em&gt;. Using the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes we can change these inner content dimensions, and control how many units the canvas uses for rendering on it's &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; axis. Below is a further example and explination of how this works:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/RwZJQLB?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The canvas dimensions and it's content dimensions can also be set in one go, using it's &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes in HTML: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="c"&gt;&amp;lt;!-- canvas itself and its content is 300x250 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"250"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Sorry, your browser dosen't support HTML Canvas!&lt;span class="nt"&gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What option you choose for sizing will determine how or weather or not you'll use these two attributes. But now that this concept is understood, let me show you what I think are the three best and most common methods for sizing your game. &lt;/p&gt;

&lt;h3&gt;
  
  
  Applying a Static Fit &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;"Static Fit"&lt;/strong&gt; (for the lack of a better term) is when you apply permanent default dimensions to your canvas, and then simply position it somewhere on your webpage. Generally, this is used for larger screens and desktops where you want other content to be visible without maximizing the game area, or you want to maintain the aspect ratio of the game area and dont care about maximizing it.&lt;/p&gt;

&lt;p&gt;For some games, aspect ratio is important because if it's altered, the content of the game could squish or stretch. A good example of a static fit is the online game &lt;a href="https://tanktrouble.com/" rel="noopener noreferrer"&gt;Tank Trouble&lt;/a&gt; (one i used to play quite a bit 😊). You can see they've simply positioned their game area onto the page, maintain it's aspect ratio, and keep it minimized as to keep the rest of the webpage content visible.&lt;/p&gt;

&lt;p&gt;When applying this type of fit, you'll want to set the default &lt;strong&gt;content dimensions&lt;/strong&gt; of the canvas &lt;strong&gt;once&lt;/strong&gt; and never change them. They should have the same aspect ratio as the &lt;strong&gt;physical canvas dimensions&lt;/strong&gt; in CSS, and whenever you want to scale the canvas, always keep it's aspect ratio and inner dimensions the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applying a Theator Fit &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;"theator fit"&lt;/strong&gt; or &lt;strong&gt;"theator mode"&lt;/strong&gt; method, is one of the most common ways used to maximize the size of content which must maintain its aspect ratio. This is when you stretch the height of the content to the full height of the device, and keep the width proporcionate, optionally filling in any gaps with black (or vice-versa, based on the client device dimenisons).&lt;/p&gt;

&lt;p&gt;This method is usually applied when the game area has to maintain a certain aspect ratio and you want to maximize it as much as possible without cutting off any of the canvas. I could'nt find a good example in a game, but the Youtube video player serves as a good example. As seen when you try to fullscreen the video, black bars may cover the top or bottom of the video player in order to cover gaps not filled my the video itself.&lt;/p&gt;

&lt;p&gt;Below, I show an example and full explination on how you can apply this:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/ZEJMxyB?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Notice how the canvas adapts to the viewport changing, that way our game content wont end up stretching or being altered if a user resizes, and always provides the most optimum presentation possible. Similar to a static fit, you should set the content dimensions once and never change them, only changing the canvas's CSS dimensions to scale it, and maintain aspect ratio. It would also be smart to encourage your users to flip their device (if possible) to get as close to the aspect ratio of the game area as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applying a Fullscreen Fit &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;fullscreen&lt;/strong&gt; fit can be simple, or a tad more complicated. It's when you stretch the canvas dimension's (&lt;strong&gt;and it's content dimensions&lt;/strong&gt;) to the exact dimensions of the user's device, as to leave no gaps. &lt;strong&gt;When using a fullscreen and theator fit, I would recommend fullscreening the canvas on touchscreen devices via the &lt;code&gt;HTMLElement.requestFullscreen()&lt;/code&gt; method to lock it in place, because the browser may scroll and move as the player interacts with the screen to play the game&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A fullscreen fit should usually only be applied when the dimensions of your game area dont matter, and or the full game area within the canvas dosen't have to be visible. A good example of this is the online game &lt;a href="http://narwhale.io/" rel="noopener noreferrer"&gt;Narwhale.io&lt;/a&gt;, where the character is centered and the map moves into view naturally.&lt;/p&gt;

&lt;p&gt;A small pitfall if this is that the sizing of your game may vary slightly in terms of how much of the map certain clients will see. If your game is drawn on a phone with smaller dimensions than a tablet, the content is drawn using the same amount of units for each rendering (meaning a 2x2 square on the phone is also 2x2 on the tablet), except the tablet uses more units since the canvas's content dimensions will adapt to its larger screen size. &lt;strong&gt;This means that users on larger screens will end up seeing significantly more of the map than users with smaller screens&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Depending on your game, this may not matter to you, but if it's somthing you care about, I have a solution. I found to get around this was not to use pixels (the default units) as units when sizing renderings, but instead inventing my own &lt;em&gt;"viewport unit"&lt;/em&gt; based on the dimensions of the device. &lt;strong&gt;Think of it as using "%" units instead of "px" units in CSS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When applying this in an online game I had started a while back which used a &lt;em&gt;fullscreen fit&lt;/em&gt;, it proved very effective at maintaining consistent proporcionality between devices. Below, you can see two screenshots I took, comparing the the size of the game area relative to the screen of my phone, and my tablet.&lt;/p&gt;

&lt;h4&gt;
  
  
  Phone game area (720x1520):
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsyt7omtfkiidma9owsv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsyt7omtfkiidma9owsv.jpg" alt="phone game area"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Tablet game area (1920x1200):
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5oewfys49cqwvq6qada.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5oewfys49cqwvq6qada.png" alt="tablet game area"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how the elements of the game dont seem smaller on the tablet screen, and the distance between the benches from the edge of the screen is almost the same. Of course, some devices will inevadablely see slightly more or less of the map than others, because of slight differences in aspect ratio, but it's nothing to worry about.&lt;/p&gt;

&lt;p&gt;In short, if you use pixel units (the default units) with a fullscreen fit you'll probably see large changes in the sizing of the map between devices (which isn't a problem, if you dont care), but if you use "viewport" units, the sizing of your game will stay consistent. &lt;a href="https://codepen.io/ZippCodder/pen/yLoRGab" rel="noopener noreferrer"&gt;Here&lt;/a&gt; I show an example and explination of how to apply these percentage units if you're interested.&lt;/p&gt;

&lt;p&gt;On another note, if you're on a touch screen device and you're interested in checking out the unfinished multiplayer game where I took the screenshots from, you can check that out &lt;a href="https://zippcodder.github.io/runners/pages/index.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;. You can also dig through the &lt;a href="https://github.com/ZippCodder/runners/blob/master/src/index.ts" rel="noopener noreferrer"&gt;code&lt;/a&gt; if you'd like to see how I apply some of the techniques I talk about here.&lt;/p&gt;

&lt;p&gt;But with all that out of the way, lets finally start building our game, shall we? 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Rendering Pipeline &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before creating any characters, objects or backgrounds, we first need to define an order and structure through which each of these entities will be rendered and managed. Since we're building our game from scratch and HTML Canvas provides no kind of framework, we'll have to define ourselves a structure. I call this my &lt;strong&gt;rendering pipeline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Generally it'll look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// get canvas 2D context object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// object for storing globally accessable states&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GLOBALS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;


&lt;span class="c1"&gt;// Array where all props will be stored&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PROPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="c1"&gt;// Array where all characters will be stored&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CHARS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="c1"&gt;// function for applying any initial settings&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// function for rendering background elements&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderBackground&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// function for rendering prop objects in PROPS&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderProps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// function for rendering character objects in CHARS&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderCharacters&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// function for rendering onscreen controls &lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderControls&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// main function to be run for rendering frames&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startFrames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// erase entire canvas&lt;/span&gt;
&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// render each type of entity in order, relative to layers&lt;/span&gt;
&lt;span class="nf"&gt;renderBackground&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;renderProps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;renderCharacters&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;renderControls&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// rerun function (call next frame)&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;startFrames&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// initialize game settings&lt;/span&gt;
&lt;span class="nf"&gt;startFrames&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// start running frames&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This provides us with an orderly process we can use to draw all of the elements of our game. The process goes as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We create a container for any states that we want to be accessable globally. For example, if we wanted to create a "pet" that follows our character around, we could store the character's coordinates in our global container, for the pet object to access and use as a relative point to follow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two arrays are defined, one which will store all objects for props (objects that move or can be interacted with by the user), and another that will store all objects for characters (objects controlled by the user). Objects for props and characters will be created using classes, as we'll see later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An initialization function is defined, which will set any initial states, like setting the canvas's dimensions, colors, fonts, etc. This is typically where you'd put the logic for your initial canvas sizing, like discussed in the previous section, or perhaps register an event listener for adjusting the game area on resize (depending on your prefered sizing method).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A function for rendering the backdrop is defined. Here we can either render an image, or separate background elements (more on that later).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We create a function which will render each prop in the &lt;code&gt;PROPS&lt;/code&gt; array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We create a function which will render each character in the &lt;code&gt;CHARS&lt;/code&gt; array.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We create a function which will render onscreen controls (for mobile devices) line buttons and joysticks, as well as any other displays like showing the number of lives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The main function is created. This function when called will begin running frames. It starts by erasing the canvas using &lt;code&gt;clearRect()&lt;/code&gt;, then calls the render function for each type of entity. If somthing is drawn onto the canvas, and then we draw somthing directly ontop of it, the first rendering will be covered, meaning we'll have to think in layers. Thus, the render function for each type of entity is called in a logical order (background-&amp;gt; objects-&amp;gt; characters-&amp;gt; controls), with the background being on the bottom layer, and the onscreen controls being on the top. The last thing this function dose is run a special method &lt;code&gt;requestAnimationFrame&lt;/code&gt;. This method takes in a function, which it will run as soon as the browser is ready to render new content, so we pass it &lt;code&gt;startFrames&lt;/code&gt;. We call it in a loop, so that our frames run indefinitly (note that &lt;code&gt;requestAnimationFrame&lt;/code&gt; isn't blocking, like if you were to run a &lt;code&gt;for&lt;/code&gt; loop indefinitely, making the page unresponsive).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We call &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;startFrames&lt;/code&gt;, to initialize our game, and begin running frames.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course, you can personalize this process however you please if you're actively following along, as this is just my personal process and none of this is set in stone (though I'd recommed still using &lt;code&gt;requestAnimationFrame&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;The purpose of this section was to explain that you should have some kind of structure for rendering your game, and managing states, animations and user interactions. This is the most important part, as it'll prevent our game from becoming a confusing, clunky mess in the long run.&lt;/p&gt;

&lt;p&gt;Hopefully by now the fundamentals have more or less stuck, but now that the scafolding for our game is all set up, we can finally start filling our rendering pipeline with actual backgrounds, objects and characters (etc) to render!&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Sprites &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;"sprite"&lt;/strong&gt; refers to any rendered object or character that can be moved around, interected with, or hold some type of state or animation. Some can be represented as objects, and others with functions, both of which should typically be stored in a separate file, to keep the file where your rendering pipeline lives clean. Usually I split these into three categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Background Sprites&lt;/li&gt;
&lt;li&gt;Object Sprites&lt;/li&gt;
&lt;li&gt;Character Sprites&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As implied, they function as a tangible rendered elements of the game, each of which serves a different purpose. Below, I explain exactly the application of these, and how to create each of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background Sprites &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;When creating a background for your game (as we'll dive deeper into later) there are generally two options. The background can be rendered as a single pre-created image, or, it can be rendered as a collection of &lt;strong&gt;"background sprites"&lt;/strong&gt;. This can be multiple renderings, or a collection of multiple images. &lt;/p&gt;

&lt;p&gt;Because background elements cant be interected with and hold no state, usually these are created as functions which do nothing but render the sprite, rather than objects with render methods and properties as used in character and object sprites (more on that later). These functions will take in an &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinate as parameters (optionally any other parameters regarding display as well), and will simply be called inside the &lt;code&gt;renderBackground()&lt;/code&gt; function of our rendering pipeline.&lt;/p&gt;

&lt;p&gt;Heres an example of a simple flower pot sprite ive created:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/bGryQeE?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here I draw each flower from scratch using rendering methods. If you do this its important that you draw each peice of the sprite relative to the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; parameters that are passed into the function. I wouldn't recommend doing this however, as its tedious and using a prepared image generally will look alot better. I'm just using rendering methods to examplify their use.&lt;/p&gt;

&lt;p&gt;Again, you can just as easily skip all of the building of the flower yourself, and simply use the &lt;code&gt;drawImage(x,y)&lt;/code&gt; method to draw a pre-build image or PNG (one that hopefully looks better than my flowers) onto the canvas for a single background sprite, or even skip everything all together and render a single image for the entire background in the &lt;code&gt;renderBackground()&lt;/code&gt; function.&lt;/p&gt;

&lt;h3&gt;
  
  
  Object Sprites &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Object sprites are like background sprites, except they usually hold some kind of state (for user interactions), movement or have an animation, and may have access to certain global states in &lt;code&gt;GLOBALS&lt;/code&gt;, like a ceiling fan, or a door that opens and closes when the user touches it. Usually these are made with classes and objects, which are stored in the &lt;code&gt;PROPS&lt;/code&gt; array, which is later iterated through to render each object in it, inside the &lt;code&gt;renderProps()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Classes for object sprites will always carry a &lt;code&gt;render()&lt;/code&gt; method containing the commands to render the sprite, which will be accessed and called in &lt;code&gt;renderProps&lt;/code&gt;. Of course you dont have to call it that, but you should have some kind of standard method for rendering each prop. Inside the &lt;code&gt;render()&lt;/code&gt; method, state can be used to influence how the sprite is displayed. Similar to background sprites, these can also accept an &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; parameter, and any other additional parameters regarding interaction or display. Below I create animated spikes as an example of a simple object sprite:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/eYEabvX?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The movement works because we're constantly changing the coordinates (our state) where the rendering is drawn, and because frames are running indefinitely, any changes we apply to the rendering will be immediately reflected since the sprite is being redrawn with new state repeatedly, which means it's up to us to control timing in animations. Again, my spikes are fairly ugly, and I'm just using render methods to demonstrate their use and prove the concept. You can make your sprites as pretty as you'd like.&lt;/p&gt;

&lt;p&gt;This is a good example of the types of elements you should render as object sprites, such as obstacles or things a character can interact with or be affected by. As shown, typically you should make these as a class in which you'll specify its default functionality and give it a &lt;code&gt;render&lt;/code&gt; method, then simply envoke it whenever you need to place a new object sprite of the same type, keeping our code nice and DRY.&lt;/p&gt;

&lt;h3&gt;
  
  
  Character Sprites &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Character sprites function essencially the same as object sprites, accept they usually have state thats controlled by outside factors like keyboard controls or a joystick, and are rendered on a higher layer than objects. Character sprites are created as objects from a standard class which have state and a &lt;code&gt;render&lt;/code&gt; method, and are added to the &lt;code&gt;CHARS&lt;/code&gt; array which will be iterated through in &lt;code&gt;renderCharacters()&lt;/code&gt; to call the render method of each existing character. This can include the player's character as well as other players, like in an online game. &lt;/p&gt;

&lt;p&gt;Though they're similar, it's best to keep them separated, because usually you'll want your characters to be rendered on a higher layer than the objects and background.&lt;/p&gt;

&lt;p&gt;In the next section I'll show how you can implement controls with a character sprite, and explain how to create different types of movements in your game like having the character look towards the mouse, making joysticks and using keyboard controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Movement and Controls &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In this section I'll explain and demonstrate how to implement common controls and character movements that you'll typically apply in a 2D game, many of the methods I use to implement which can be used to create other types of controls and movements. Below I explain each one by one, and provide code and an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Joysticks &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Joysticks are a common type of control used for mobile games and typically have two applications in regards to character actions: 1) &lt;strong&gt;Controlling a character's angle&lt;/strong&gt; 2) &lt;strong&gt;Controlling a character's movement direction&lt;/strong&gt;. Apart from display, a joystick's primary purpose is to keep track of each of these, so that we can apply them to whatever entity(s) it's controling. Typically it'll keep it's angle and &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; direction in &lt;code&gt;GLOBALS&lt;/code&gt; so that they're accessible to every sprite that needs it.&lt;/p&gt;

&lt;p&gt;These properties will allow us to specify certain directions in which sprites will travel on the game area, and the angle at which they're facing. Usually these are applied as character controls, and &lt;em&gt;dual-joysticks&lt;/em&gt; are used, &lt;strong&gt;one for the character's angle and one for the character's direction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Below I show an example and full explination on how to create a joystick. I've made this example so that you can interact using a mouse or a touchscreen device. Try not to resize to much, as it could break the example:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/NWvQMmy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you can see iv'e created a class for creating joysticks just like I would've made an object sprite, then &lt;strong&gt;instanciate and render it inside &lt;code&gt;renderControls()&lt;/code&gt;&lt;/strong&gt;. They technically aren't sprites however, because the joystick isn't an element of the game itself. I've rendered it simply as two circles, one serving as the &lt;strong&gt;thumbstick&lt;/strong&gt; and one as the &lt;strong&gt;base&lt;/strong&gt; (again, you can make these peices look however you want).&lt;/p&gt;

&lt;p&gt;Within it's &lt;code&gt;render&lt;/code&gt; method I added logic to draw the thumbstick towards the user's finger, while keeping it inside of the base (the &lt;code&gt;distance()&lt;/code&gt; helper function, which measures the distance between two points, aids in this). Using one of the helper functions I've added to &lt;code&gt;GLOBALS&lt;/code&gt; (&lt;code&gt;angle()&lt;/code&gt;), the center coordinates of the base and the center coordinates of the thumbstick, Im also able to determine the angle between the two coordinates, and the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; offset the thumbstick is from the base (the formula for which will be covered later), which is the information shown above the joystick. &lt;strong&gt;The formula used by &lt;code&gt;angle()&lt;/code&gt; and &lt;code&gt;distance()&lt;/code&gt; can be found commented in the above pen.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The formula I've used to calculate the angle will output radians, because that's the unit used by the &lt;code&gt;rotate()&lt;/code&gt; method of the canvas's context. This will be used later to rotate our character.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This information can be kept in &lt;code&gt;GLOBALS&lt;/code&gt; to later be accessed by our main character sprite, to control it's movements. Another important note to mention is how im giving the joystick class access to the mouse actions through &lt;code&gt;GLOBALS&lt;/code&gt;, and then implementing it's logic within it's own class instead of inside the event listeners for mouse/touch events. This keeps things much more orderly, rather than cramming the logic of each sprite who needs mouse events inside the same event listeners. This is why inside &lt;code&gt;init()&lt;/code&gt; I've registered mouse/touch event listeners which when fired just add that information to &lt;code&gt;GLOBALS&lt;/code&gt; to be globally accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Joystick Movement &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Below is an example of integrating a joystick with a character sprite to allow movement. Our character sprite is the red circle in the top left corner. Simply use the joystick to move it across the screen with your finger or mouse. Again, try not to resize the window:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/ExwYpVg?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here our character sprite is accessing the &lt;code&gt;charX&lt;/code&gt; and &lt;code&gt;charY&lt;/code&gt; properties on &lt;code&gt;GLOBALS&lt;/code&gt;, which are being continuously updated by and based on our joystick's state. Again, this is better than directly updating our character sprite's coordinates inside of the joystick's class, because if we we're to add more sprites for the joystick to control, we would have to cram a ton of code inside it. Instead, any sprite can simply access the information via &lt;code&gt;GLOBALS&lt;/code&gt; and keep its implementation within it's own class.&lt;/p&gt;

&lt;p&gt;The way this movement works is a bit different than implementing keyboard controls, because our character sprite is moving in very smooth angles rather than simply &lt;em&gt;up&lt;/em&gt; or &lt;em&gt;left&lt;/em&gt;. &lt;strong&gt;Here's how it works&lt;/strong&gt;: First we declare &lt;code&gt;charX&lt;/code&gt; and &lt;code&gt;charY&lt;/code&gt; onto &lt;code&gt;GLOBALS&lt;/code&gt;, which serve as the &lt;em&gt;horizontal&lt;/em&gt; and &lt;em&gt;vertical&lt;/em&gt; amount of units a character will move over time. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The way the joystick determines both of these values is by mesuring the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; offset of the thumbstick of the joystick from the center of it's base. These are determined by subtracting the base's &lt;code&gt;x&lt;/code&gt; coordinate from the thumbstick's &lt;code&gt;x&lt;/code&gt; coordinate to get &lt;code&gt;charX&lt;/code&gt;, and then subtracting the base's &lt;code&gt;y&lt;/code&gt; coordinate from the thumbstick's &lt;code&gt;y&lt;/code&gt; coordinate to get &lt;code&gt;charY&lt;/code&gt;. You might want to only use a fraction of the result of both of these calculations, like a &lt;strong&gt;10%&lt;/strong&gt;, because if the result of calculating &lt;code&gt;charX&lt;/code&gt; for exmaple is -56.09, your character will be moving alot of units to the left very quickly. You can fraction each of these however (as long as you fraction both the same). It's all about the ratio between the amount of units our character sprite is moving in one direction vs the other overtime, to apply movement at dynamic angles.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a user had the joystick positioned at the bottom right (as far as it could go in each direction), this would mean our character would move diagonally downwards to the right. Why? Because since &lt;code&gt;charX&lt;/code&gt; and &lt;code&gt;charY&lt;/code&gt; are the same value (&lt;strong&gt;because the width and height of the joystick are equal and thus if the thumbstick is at the bottom right it has equal &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; offset&lt;/strong&gt;) &lt;code&gt;charX&lt;/code&gt; and &lt;code&gt;charY&lt;/code&gt; would be set the same, and the character would move &lt;em&gt;down&lt;/em&gt; and &lt;em&gt;right&lt;/em&gt; at the same rate, causing our character to move &lt;strong&gt;diagonally downwards towards the right&lt;/strong&gt;. Hopefully that made sense, but lucky for you implementing keyboard controls is 10x simpler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyboard Controls &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Unlike joystick controls keyboard movements are much simpler to implement. It's as simple as registering a &lt;code&gt;keydown&lt;/code&gt; and &lt;code&gt;keyup&lt;/code&gt; event inside &lt;code&gt;init()&lt;/code&gt;, and then keeping track of weather or not the &lt;strong&gt;keycodes&lt;/strong&gt; you're listening for are pressed down or released. That information is kept inside &lt;code&gt;GLOBALS&lt;/code&gt;, where our character sprite has easy access, and depending on weather a key is currently being pressed, the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates of the character sprite will be incremented or decremented by a certain amount (the character sprite's &lt;code&gt;speed&lt;/code&gt; property).&lt;/p&gt;

&lt;p&gt;Below is an example of a character sprite (the red circle) which you can control using the arrow keys:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/VwMwvjM?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Simple right? As it's name implies, the &lt;code&gt;speed&lt;/code&gt; property of the character sprite controls how many units our character will move when it dose, allowing us to control how much ground it covers in each movement. The same can be done with joystick controls by either multiplying &lt;code&gt;charX&lt;/code&gt; and &lt;code&gt;charY&lt;/code&gt; to go faster, or dividing them to go slower (&lt;strong&gt;as long as they're multiplied or divided by the same factor&lt;/strong&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Character Rotation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the below example I've made a small rocketship character sprite using the &lt;code&gt;drawImage()&lt;/code&gt; method. Not only dose it &lt;em&gt;move&lt;/em&gt; in the direction of the joystick, but also mimics the &lt;em&gt;angle&lt;/em&gt; of the joystick. The joystick's angle is kept in &lt;code&gt;GLOBALS.roation&lt;/code&gt;, which our character sprite has easy access to for it to rotate that amount.&lt;/p&gt;

&lt;p&gt;Below is an example and explination of how to apply rotation to a character sprite:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/jOGOBxB?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The key part here is the &lt;code&gt;angle()&lt;/code&gt; method on &lt;code&gt;GLOBALS&lt;/code&gt;, which takes in two sets of coordinates and returns the angle between them (in &lt;strong&gt;radians&lt;/strong&gt;). &lt;strong&gt;The formula for which is &lt;code&gt;atan2(y2 - y1, x2 - x1)&lt;/code&gt;&lt;/strong&gt;. We use &lt;code&gt;angle()&lt;/code&gt; to measure the angle between the center of the joystick's thumbstick, and the center of the joystick's base, and then put the result into &lt;code&gt;GLOBALS.rotation&lt;/code&gt;. This formula (and every other I cover in this post) has a ton of applications when building a game, and you can use it to control rotation with the mouse as well, by mesuring the angle between the mouse coordinates and the center of the screen.&lt;/p&gt;

&lt;p&gt;The second primary part which allows this to work is the &lt;code&gt;rotate()&lt;/code&gt; method of the canvas's context, which is what's used to apply the rotation to the character sprite. &lt;strong&gt;The way this method works is by rotating the canvas from its top left corner by the specified amount of radians&lt;/strong&gt;. The rotation only applies to everything drawn &lt;strong&gt;after&lt;/strong&gt; the method is called. Of course this works alot differently than you would expect, but we can normalize it by doing the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We want to rotate the canvas by the center of the thing we want to rotate (our character sprite) rather then the top left corner. The way to do this is by using the &lt;code&gt;translate(x,y)&lt;/code&gt; method to move the canvas's top left corner to the center coordinates of the thing we want to rotate, rotate our desired amount using &lt;code&gt;rotate(radians)&lt;/code&gt;, undo the translation (&lt;code&gt;translate(-x,-y)&lt;/code&gt;), redraw our sprite with the applied canvas rotation, and then call the &lt;code&gt;resetTransform()&lt;/code&gt; method to &lt;strong&gt;reset the canvas transformations we just did, so that everything drawn after the thing we wanted to rotate dosen't become part of the rotation or translation&lt;/strong&gt;. This process can be seen in the render method of our character sprite.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can read more on the &lt;code&gt;rotate()&lt;/code&gt; and &lt;code&gt;translate()&lt;/code&gt; methods &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/rotate" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static vs Dynamic Movement &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In 2D games typically there exists two major types of character movement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Static Movement&lt;/strong&gt;: This is when the map is fixed on the game area, and the character moves relative to the map. Like in &lt;a href="https://tanktrouble.com/" rel="noopener noreferrer"&gt;Tank Trouble&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Movement&lt;/strong&gt;: This is when the character is fixed to the center of the screen, and the &lt;em&gt;map&lt;/em&gt; moves relative to the &lt;em&gt;character&lt;/em&gt;. Like in &lt;a href="http://narwhale.io/" rel="noopener noreferrer"&gt;Narwhale.io&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far the type of movement I've examplified has all been &lt;strong&gt;static movement&lt;/strong&gt;, but in this section I'll give an example and explination on how to apply &lt;strong&gt;dynamic movement&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/oNGXZMy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;See how the "camera" follows our character as the map moves relative to it. The way we do this is by applying the joystick's &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; offset to coordinates which will serve as a &lt;strong&gt;map anchor&lt;/strong&gt;, which our background sprites will be drawn relative to (and of course remove the &lt;code&gt;charX&lt;/code&gt; and &lt;code&gt;charY&lt;/code&gt; implementation from our main character sprite).&lt;/p&gt;

&lt;p&gt;First what I do is store the joystick's &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; offset in &lt;code&gt;GLOBALS.anchorX&lt;/code&gt;and &lt;code&gt;GLOBALS.anchorY&lt;/code&gt;, and then declare &lt;code&gt;GLOBALS.mapAnchor&lt;/code&gt; to store the "map anchor" coordinates. Inside &lt;code&gt;renderBackground()&lt;/code&gt; before rendering each sprite, I update &lt;code&gt;GLOBALS.mapAnchor.x&lt;/code&gt; and &lt;code&gt;GLOBALS.mapAnchor.y&lt;/code&gt; by &lt;em&gt;subtracting&lt;/em&gt; &lt;code&gt;GLOBALS.anchorX&lt;/code&gt; from &lt;code&gt;GLOBALS.mapAnchor.x&lt;/code&gt;, and &lt;em&gt;subtracting&lt;/em&gt; &lt;code&gt;GLOBALS.anchorY&lt;/code&gt; from &lt;code&gt;GLOBALS.mapAnchor.y&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here we subtract instead of add like we did in static movement, because the map has to flow the opposite direction from where the character is moving towards.&lt;/strong&gt; Then finally, inside our &lt;code&gt;Pot()&lt;/code&gt; sprite, I add &lt;code&gt;GLOBALS.mapAnchor.x&lt;/code&gt; and &lt;code&gt;GLOBALS.mapAnchor.y&lt;/code&gt; to it's &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinate, to draw the sprite relative to the current map anchor coordinates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Collision Detection &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Collision detection is typically an essencial when it comes to games, weather it's stopping a character from walking through a wall, or killing a character when a bullet hits them.&lt;/p&gt;

&lt;p&gt;In this section I'll touch base on basic collision detection, and explain how to detect collision between &lt;strong&gt;squares&lt;/strong&gt;, &lt;strong&gt;circles&lt;/strong&gt; and &lt;strong&gt;rectangles&lt;/strong&gt; as well as give examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Squares and Rectangles &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Collision detection is all about &lt;strong&gt;using the dimensions and coordinates of two shapes, to mathematically determine weather or not both are in contact&lt;/strong&gt;. Depending on the shapes themselves (square, circle, etc.), the way you'll determine this will vary.&lt;/p&gt;

&lt;p&gt;Below I give an example and explination on how to apply collision detection with squares (same exact method can be used with rectangles of any size). Simply drag the pink square into the blue square, and the blue square will turn red when the pink square comes into contact in the following example:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/poWJprJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;p&gt;The first thing I did was implement some logic for dragging the pink square. That isn't as relevant but if your interested in how I implemented it just take a look at the code. Next, onto the base class for our squares (which is the one the &lt;em&gt;blue&lt;/em&gt; square instanciates) I attach an object inside the constructor called &lt;code&gt;collisions&lt;/code&gt;. On this object, we'll keep a sub object for every sprite we want to detect collision for, thus, I add &lt;code&gt;pinkSquare&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On &lt;code&gt;pinksquare&lt;/code&gt; (and every other collision object in &lt;code&gt;collisions&lt;/code&gt;) there exists a &lt;code&gt;conditions&lt;/code&gt; property which holds &lt;strong&gt;the boolean for mathematically determining contact with the pink square&lt;/strong&gt; (which we're about to dig into), and then an &lt;code&gt;inContact&lt;/code&gt; property which specifies weather not the sprite is in contact, though here we aren't using this property. This is a good standard to use when implementing collision detection, since its simple and keeps things orderly. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;collisions.pinkSquare.conditions&lt;/code&gt; is a &lt;em&gt;string&lt;/em&gt; rather than a boolean, so that we can revaluate it constantly with &lt;code&gt;eval()&lt;/code&gt;, and we dont have to hard code it into &lt;code&gt;if&lt;/code&gt; statements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the pseudo-code for determining collision between two rectangles/squares, exactly the same structures as the boolean in &lt;code&gt;collisions.pinkSquare.conditions&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

A = {x: ... y: ..., width: ..., height: ...}
B = {x: ..., y: ..., width: ..., height: ...}

if (A.x + A.width) &amp;gt; B.x 
 and A.x &amp;lt; (B.x + B.width)
 and (A.y + A.height) &amp;gt; B.y
 and A.y &amp;lt; (B.y + B.height) 
...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Try visualizing this boolean in action as you read through it, and eventually you'll get the gist.&lt;/p&gt;
&lt;h3&gt;
  
  
  Circles &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Determining contact between two circles (&lt;em&gt;not&lt;/em&gt; ovals, we'll get to that) is very straight forward and simple to understand. Because Im lazy, just imagine the shapes in the above example I showed are now two circles. The pseudo code for &lt;code&gt;collisions.pinkCircle.conditions&lt;/code&gt; would be the following, to determine weather the two circles are in contact:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

A = {x: ..., y: ..., radius: ...}
B = {x: ..., y: ..., radius: ...}

if
 distance between A and B &amp;lt; (A.radius + B.radius) 

...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Here, "distance between A and B" refers to the distance between the two points where each circle is centered. If you remember, you determine this with the handy-dandy formula: &lt;code&gt;√(x2 − x1)^2 + (y2 − y1)^2&lt;/code&gt;. Simple right? &lt;/p&gt;

&lt;p&gt;These two examples are pretty simple, but collision detection with more complex and irregular shapes can require much more advanced methods of determining collisions. Of course here I've only gone over the basics, but if you do plan on implementing collision detection for complex shapes, I highly recommend you check out these resources: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gamedeveloper.com/programming/advanced-collision-detection-techniques" rel="noopener noreferrer"&gt;https://www.gamedeveloper.com/programming/advanced-collision-detection-techniques&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects" rel="noopener noreferrer"&gt;https://www.toptal.com/game/video-game-physics-part-ii-collision-detection-for-solid-objects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Events &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Keeping track of certain events, such as when a door is opened or when the character is hit in a game is important. This allows us to globally listen for (and trigger) when certain things happen our game no matter what sprite we're in.&lt;/p&gt;

&lt;p&gt;Below I've edited the previous example to use events to run two &lt;code&gt;alert()&lt;/code&gt;s every time the squares are in contact:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/mdBVLqp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Basically the way I've implemented events is exactly how DOM events are implemented, by adding an &lt;code&gt;addEventListener()&lt;/code&gt; and &lt;code&gt;dispatchEvent()&lt;/code&gt; method to &lt;code&gt;GLOBALS&lt;/code&gt;. That way both methods are globally accessible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GLOBALS&lt;/code&gt; also includes an &lt;code&gt;events&lt;/code&gt; property, and each of its sub properties are the name of an existing event which points to an array where callbacks for that event will be stored. I simply call &lt;code&gt;GLOBALS.addEventListener(name,callback)&lt;/code&gt; to add a callback to the array for the specified event, and then call &lt;code&gt;dispatchEvent(name)&lt;/code&gt; to call each callback inside the array of the specified event name. And of course we can all new events by adding a new property to &lt;code&gt;GLOBALS.events&lt;/code&gt;. Easy-peasy! 🍋&lt;/p&gt;

&lt;p&gt;Despite how simple it is, I just wanted to clarify that its important that you implement some kind of event system within your game, otherwise you'll be hardcoding alot of stuff, which isn't good practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it All Together &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Finally let me go down the list of each integral concept that makes this process possible. If any of what I explained previously seemed unclear, I recommend you try to examine where and how each concept is implemented within the code to gain a better understanding of how this all functions. Let us first again go down the list of each of the steps of the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose a sizing for the game area (apply it in &lt;code&gt;init()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Create your rendering pipeline&lt;/li&gt;
&lt;li&gt;Fill your rendering pipeline with sprites (in their respective locations depending on the sprite)&lt;/li&gt;
&lt;li&gt;Apply movement and controls&lt;/li&gt;
&lt;li&gt;Apply collision detection&lt;/li&gt;
&lt;li&gt;Integrate events&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each of these concepts can be seen applied in this simple game I've created, named "Drift". The objective is to last as long as possible without being hit by a barrier or leaving the map, steering a car by tapping the left or right half of the game area or using arrow keys. I found it about as frustrating as playing Flappy Bird, my highest score being 33. &lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/PoJNzQz?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This game greatly examlifies the process and methods I've explained throughout, and hopefully with this guide and example to throw it all together, you'll be equiped with the knowledge to build your own games using HTML Canvas, and the techniques I've gone over in this post. &lt;/p&gt;

&lt;p&gt;I hope you've managed to gain somthing from this article, and if you're still thirsty for more related to game development, definitely checkout the resources below.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and happy coding! 👍&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML Canvas API - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Advanced Collision Detection - &lt;a href="https://www.gamedeveloper.com/programming/advanced-collision-detection-techniques" rel="noopener noreferrer"&gt;https://www.gamedeveloper.com/programming/advanced-collision-detection-techniques&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/march/game-development-a-web-game-in-an-hour" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/archive/msdn-magazine/2015/march/game-development-a-web-game-in-an-hour&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>gamedev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Speech Recognition and Building a Voice Controlled To-Do List</title>
      <dc:creator>Deon Rich</dc:creator>
      <pubDate>Wed, 03 Nov 2021 02:37:53 +0000</pubDate>
      <link>https://forem.com/zippcodder/understanding-speech-recognition-and-building-a-voice-controlled-to-do-list-3e5</link>
      <guid>https://forem.com/zippcodder/understanding-speech-recognition-and-building-a-voice-controlled-to-do-list-3e5</guid>
      <description>&lt;p&gt;One of the biggest and most important building blocks of modern technology, hands-down, is AI. Machine learning is a completly different animal when it comes to how machines process information. I consider it to be one of the key stepping stones for bridging the gap between the way machines process and understand data, and the way we humans think and take in information.&lt;/p&gt;

&lt;p&gt;It can seem rather impossible for a machine to emulate the capabilities that our human minds do, with the unique way we have of learning, understanding, mapping information and extracting context from data. This especially applies when talking about &lt;strong&gt;human language and speech&lt;/strong&gt;. But as always, technology has found a way!&lt;/p&gt;

&lt;p&gt;In this post, I thought it would be interesting for us to take a look at how modern speech recognition technology works, as examplified by technologies such as Google Assistant, Amazon's Alexa and Apple's Siri. Then lastly, we'll look at an example of how we can utilize this tech in our projects by building a &lt;strong&gt;voice controlled to-do list&lt;/strong&gt; using the &lt;strong&gt;Web Speech API&lt;/strong&gt;! 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  The Building Blocks of Speech Recognition
&lt;/h2&gt;

&lt;p&gt;When it comes to how machines understand and process language, more specifically in the form of audio, there exsists two fundamental concepts that must be implemented for speech recognition to be possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Speech Recognition (ASR)&lt;/strong&gt;: Though ASR is usually used as an umbrella term for the concepts behind speech recognition, it primarily refers to the process of breaking down speech in the form of audio, and applying algorithms to transcribe the peices of audio. This is the main concept behind Speech-To-Text programs, and allows a machine to know &lt;em&gt;what&lt;/em&gt; you're saying, but not the meaning behind it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Natural Language Processing (NLP)&lt;/strong&gt;: Refers to the process of understanding or emulating language. The act of constructing and or deconstructing key points in natural speech. This is the main player behind programs like Alexa, which are able to not only know &lt;em&gt;what&lt;/em&gt; you're saying, but &lt;em&gt;understand&lt;/em&gt; it based on the summary it formulates from your speech (NLU), or even respond back (NLG). The concepts used in NLP are applyed in both &lt;strong&gt;NLG (Natural Language Generation)&lt;/strong&gt; and &lt;strong&gt;NLU (Natural Language Understanding)&lt;/strong&gt;, as its used as an umbrella term for both.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both NLP and ASR are implemented using algorithms based on machine learning, neural networks and deep learning, and are heavily based on linguistics, semantics and statistics. And considering how complex human language is, this is the right approach.&lt;/p&gt;

&lt;p&gt;These technologies aren't perfect, however. Human language cannot be simply analized like any other set of data. There exists anthimeria, sarcasm, slang, implication, words with double meaning, figures of speech and a whole lot of other quirks that a machine is going to have to learn to identify over time. Not to mention, this all varies from language to language.&lt;/p&gt;

&lt;p&gt;So how do ASR and NLP acomplish what they do? Lets take a bit of a closer look..👇&lt;/p&gt;

&lt;h3&gt;
  
  
  The Process of ASR
&lt;/h3&gt;

&lt;p&gt;The main steps behind ASR that a program will take go as follows. Note that the process may vary depending on a specific programs end goal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The program receives an audio input.&lt;/li&gt;
&lt;li&gt;This audio is refined, as the program attempts to isolate the speech from background noise.&lt;/li&gt;
&lt;li&gt;The resulting speech is split into
&lt;a href="https://en.m.wikipedia.org/wiki/Phoneme"&gt;phonemes&lt;/a&gt;. Phonemes are small units of sounds unique to a language that are commonly used to construct words, and can be used to differentiate one word from another, or where one word may start or where another may end.&lt;/li&gt;
&lt;li&gt;The phonemes are then analysed, and the AI uses its aquired knowledge of that language to determine the most likely word that would follow based on the sequence of sounds. Once it forms words, the same probability analysis is applied to determine what a sentence might be.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Process of NLP
&lt;/h3&gt;

&lt;p&gt;The main steps behind NLP &lt;strong&gt;(or more specifically NLU)&lt;/strong&gt; that a program will take go as follows. Note that the process may vary depending on a specific programs end goal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The input speech is separated into sentences. The resulting sentences are then split into separate words, this is called &lt;em&gt;tokenization&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The tokenized words are then analysed and given roles (nouns, verbs or adjectives) based on the surrounding sentence.&lt;/li&gt;
&lt;li&gt;Non &lt;a href="https://searchenterpriseai.techtarget.com/definition/lemmatization#:~:text=Lemmatization%20is%20the%20grouping%20together%20of%20different%20forms%20of%20the%20same%20word.&amp;amp;text=Complex%20algorithms%20use%20the%20rules,and%20writing%20by%20inflected%20forms."&gt;lemmas&lt;/a&gt; are then lemmatized, meaning they're mapped to their basic form, to signal that they pose the same meaning (broken -&amp;gt; break).&lt;/li&gt;
&lt;li&gt;Common words such as "and","or" and "a" are removed, as to isolate the words which hold the primary meaning.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://towardsdatascience.com/natural-language-processing-dependency-parsing-cf094bbbe3f7#:~:text=Dependency%20Parsing%20is%20the%20process,dependent%20that%20modifies%20the%20head."&gt;Dependency Parsing&lt;/a&gt; is then preformed, and a tree is created, associating words which depend on each other together (chocolate -&amp;gt; best -&amp;gt; icecream -&amp;gt; flavor).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/mysuperai/what-is-named-entity-recognition-ner-and-how-can-i-use-it-2b68cf6f545d"&gt;Named Entity Recognition (NER)&lt;/a&gt; is preformed, labeling each noun based on the real world thing they're meant to represent (Peter Parker -&amp;gt; fictional character).&lt;/li&gt;
&lt;li&gt;Lastly, &lt;a href="https://nlp.stanford.edu/projects/coref.shtml#:~:text=Coreference%20resolution%20is%20the%20task,question%20answering%2C%20and%20information%20extraction."&gt;Coreference Resolution&lt;/a&gt; is done on pronouns such as "it", "she", "he" and "they", in order to link them to the noun that they're refering to. Once this is done, the program can properly deduce the meaning behind the speech sample (she -&amp;gt; Lisa Ross).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Of course its important to remember that there is much more that goes into these proceses within a real implementation of NLP and ASR. In order to actually execute each of these steps advanced algorithms and methods are utilized, such as &lt;strong&gt;Hidden Markov Models&lt;/strong&gt;, &lt;strong&gt;Dynamic Time Warping&lt;/strong&gt;, and &lt;strong&gt;Neural Networks&lt;/strong&gt; to list a few. &lt;/p&gt;

&lt;p&gt;Anyway, now that we've got a good idea of how ASR functions, lets get our hands dirty at look at how we can use it in our code by utilizing the &lt;strong&gt;Web Speech API&lt;/strong&gt;, and building a &lt;strong&gt;Voice Controlled To-Do List&lt;/strong&gt;! 😁&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The Web Speech API is still in an experimental phase. It may not support a given browser and its implementation is still incomplete. That being said it should be used in personal projects only. There already exists stable STT APIs out there such as those listed &lt;a href="https://nordicapis.com/5-best-speech-to-text-apis/"&gt;here&lt;/a&gt;, but im going with the Web Speech API as its extreamly simple, easily accessable and suffices our needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Voice Controlled To-Do List
&lt;/h2&gt;

&lt;p&gt;Before I walk you through our example, let me first show you the finished product. Here however, the embed isn't allowed media access, which breaks its functionality. If you want to see how it functions you can view it &lt;a href="https://codepen.io/ZippCodder/full/wvqrBOe"&gt;here&lt;/a&gt;. Anyway, heres what it will look like:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/ZippCodder/embed/wvqrBOe?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The functionality is pretty simple. Once the switch is flipped, the speech recognition service will start listening for speech. Our program will first expect the user to give a title, and once thats given it will then expect a description. After the description is spoken, a new task will be added to the UI, containing the title and description the user entered. The state of the program (weather its active, or what peice of information its expecting next) will be expressed in the message above the switch.&lt;/p&gt;

&lt;p&gt;Simple, right? Lets go over the code..&lt;/p&gt;

&lt;h3&gt;
  
  
  Using the Speech Recognition Service
&lt;/h3&gt;

&lt;p&gt;First, lets cover the most important step, which is starting the speech recognition service through the Web Speech API. When I say "speech recognition service", im refering to the default speech recognition service build into Chrome. Our audio will be captured and sent to a server (the speech recognition service) where it will be processed, and then sent back. &lt;/p&gt;

&lt;p&gt;First, we need to establish a connection with it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="c1"&gt;// Setup recognition service&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechRecognition&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;SpeechRecognition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechRecognition&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;SpeechRecognition&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;grammarList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechGrammarList&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;SpeechGrammarList&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grammars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;grammarList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Alert user if API isnt supported&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sorry, your browser dosen't support the WebSpeech API!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here all we do is first ensure that the API exists within the &lt;code&gt;window&lt;/code&gt; object. Once thats done we instantiate a new &lt;code&gt;SpeechRecognition&lt;/code&gt; object, which is the interface for interacting with the speech recognition service.&lt;/p&gt;

&lt;p&gt;Its primary events and methods are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;start()&lt;/code&gt;: Begin listening for speech.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stop()&lt;/code&gt;: Stop listening for speech.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;abort()&lt;/code&gt;: Stop listing for speech without returning result.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;result&lt;/code&gt;:  Fires when a result is returned from the recognition service. The result is passed to the callback.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;end&lt;/code&gt;: Fires when the speech recognition service is stopped.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start&lt;/code&gt;: Fires when the speech recognition service is started.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;speechstart&lt;/code&gt;: Fires when speech is detected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;speechend&lt;/code&gt;: Fires when speech is no longer detected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I attach a &lt;code&gt;SpeechGrammarList&lt;/code&gt; to it via &lt;code&gt;SpeechRecognition.grammars&lt;/code&gt;. &lt;code&gt;SpeechGrammarList&lt;/code&gt; is an object which is meant to hold a list of grammars. A grammar (though through this API is given as a string) is a special file that is sent to the speech recognition service, which gives it the grammar or key words or phrases that it should be listening for. Through grammars you're also able to tell it which phrases it should listen for more than others, by specifying their "weight".&lt;/p&gt;

&lt;p&gt;Grammars are typically specified using the &lt;a href="https://en.m.wikipedia.org/wiki/Speech_Recognition_Grammar_Specification"&gt;SRGS&lt;/a&gt;(Speech Recognition Grammar Specification) format, or the &lt;a href="https://www.ibm.com/docs/en/wvs/6.1.1?topic=editor-what-is-jsgf"&gt;JSGF&lt;/a&gt;(Java Speech Grammar Format). However, at the moment this API dosen't support grammars very well, as they have little effect on the results of the speech recognizer. Thus, I give it an empty &lt;code&gt;SpeechGrammarList&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;After that, we set the language the recognizer should listen for via the &lt;code&gt;SpeechRecognizer.lang&lt;/code&gt; property, which in this case is english.&lt;/p&gt;

&lt;p&gt;And thats really all there is to it to get up and running. Now we just need to fill in the gaps we need to integrate it into our to-do list!&lt;/p&gt;

&lt;h3&gt;
  
  
  Putting it All Together
&lt;/h3&gt;

&lt;p&gt;Because the UI isn't as important i'll only be going over the javascript, but you can give it a closer look &lt;a href="https://codepen.io/ZippCodder/full/wvqrBOe"&gt;here&lt;/a&gt; or in the embed I showed earlier. You can of course make the UI look however you want if you intend on following along. &lt;/p&gt;

&lt;p&gt;The main idea is that we simply have a main button to toggle the speech recognition service, a message to indicate the state of the program (active, listening, or what info its expecting), and an area where the resulting tasks will appear. &lt;/p&gt;

&lt;p&gt;To wrap up, i'll breifly go over each segment of functionality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Only proceed if API is Supported...&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechRecognition&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;SpeechRecognition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="cm"&gt;/*
"active" will be used to keep track of weather 
or not the service is active.

"phase" will be used to keep track of what 
information is currently being 
expected (either the title or description).

"task" is simply a container for our information 
when results are received.
*/&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="c1"&gt;//________________________________________&lt;/span&gt;

&lt;span class="cm"&gt;/*
Listen for when the switch is toggled. 
If the service is inactive, start the service 
and set the phase to "title" since 
this is the first peice of info once 
the service is listening. 
If the service is active, do the opposite.
*/&lt;/span&gt;

&lt;span class="c1"&gt;// select message element above switch&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.container__message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// select toggle switch&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.container__button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waiting for title...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Flip switch to toggle speech recognition&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// ________________________________________&lt;/span&gt;

&lt;span class="cm"&gt;/*
"addTask()" will be after both the title and description are 
spoken. This will hide the placeholder 
and fill a copy of the tasks template with the 
respective information. It'll then be 
appended to the tasks container
*/&lt;/span&gt;

&lt;span class="c1"&gt;// Select container where tasks will appear, its placeholder and the template for the tasks.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.container__tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;placeholder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.container__tasks__placeholder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#task-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Function for appending tasks&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;summary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//________________________________________&lt;/span&gt;

&lt;span class="cm"&gt;/* Setting up the recognition service, 
as already explained previously */&lt;/span&gt;

 &lt;span class="c1"&gt;// Setup recognition service&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechRecognition&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;SpeechRecognition&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;grammarList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webkitSpeechGrammarList&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;SpeechGrammarList&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grammars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;grammarList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//________________________________________&lt;/span&gt;

&lt;span class="cm"&gt;/* Inform user that service is listening when speech s detected */&lt;/span&gt;

  &lt;span class="c1"&gt;// Let user know recognition service is listening&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;speechstart&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;listening...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;//________________________________________&lt;/span&gt;

&lt;span class="cm"&gt;/*  
Register an event listener for when the result comes in, 
which will be each time the user stops 
speaking and speech was recognized. 

In the callback, if the phase is currently 
"title" (the program is waiting for the title) 
add the title to the "task" object and 
switch phase to "desc".

If the the phase is currently "desc" 
(we already have the title, and are waiting for the description) 
add the description to the "task" object, call "addTask()" 
and inform the user that the task was successfully added.
*/&lt;/span&gt;

  &lt;span class="c1"&gt;// Determine what to do with result once it comes in&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;result&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waiting for description...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;task added!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;waiting for title...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;addTask&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;//________________________________________&lt;/span&gt;

  &lt;span class="c1"&gt;// Keep service open by restarting it, since it ends after each speech segment it receives.&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Cancel service if error occurs&lt;/span&gt;
  &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;recog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Alert user if API isnt supported&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sorry, your browser dosen't support the WebSpeech API!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And there you have it folks! An introduction to how ASR works, and a small example of how you can implement it into your projects. If you want to dive deeper into ASR, NLP or the Web Speech API, you should check out these resources below..👇&lt;/p&gt;

&lt;p&gt;ASR: &lt;a href="https://verbit.ai/asr-and-the-next-generation-of-transcription/"&gt;https://verbit.ai/asr-and-the-next-generation-of-transcription/&lt;/a&gt;&lt;br&gt;
NLP: &lt;a href="https://medium.com/@ritidass29/the-essential-guide-to-how-nlp-works-4d3bb23faf76"&gt;https://medium.com/@ritidass29/the-essential-guide-to-how-nlp-works-4d3bb23faf76&lt;/a&gt;&lt;br&gt;
Web Speech API: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API"&gt;https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API&lt;/a&gt;;&lt;/p&gt;

&lt;p&gt;Thanks for reading..😊!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>speechrecognition</category>
    </item>
    <item>
      <title>A Quick Guide to Custom HTML Elements</title>
      <dc:creator>Deon Rich</dc:creator>
      <pubDate>Sun, 24 Oct 2021 05:08:09 +0000</pubDate>
      <link>https://forem.com/zippcodder/a-quick-guide-to-custom-html-elements-5f3b</link>
      <guid>https://forem.com/zippcodder/a-quick-guide-to-custom-html-elements-5f3b</guid>
      <description>&lt;p&gt;After getting to know the component based system of modern frameworks such as React and Angular, i was immediately interested when i came across the term "Web Components". After taking a deep dive into the subject, i thought it would be worth sharing. So, today im going to provide a quick guide to Web Components, how they operate, and how we can create our own custom HTML elements by applying this concept!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Web Components?
&lt;/h2&gt;

&lt;p&gt;A Web Component serves as a label for any HTML Element that possesses its own underlying DOM tree, CSS styles, and even scripts, that are separate from the reset of the DOM and encapsulated completely by that element. This underlying DOM tree is refered to as the &lt;code&gt;Shadow DOM&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Shadow DOM
&lt;/h3&gt;

&lt;p&gt;To further understand the &lt;code&gt;Shadow DOM&lt;/code&gt;, take the contents of the following HTML &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; as an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft67wxs0xcf6qvbyfqwo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft67wxs0xcf6qvbyfqwo9.png" alt="shadow DOM of an input element of type "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside of the &lt;code&gt;input&lt;/code&gt; the first thing we see is &lt;code&gt;#shadow-root&lt;/code&gt;. This simply represents the root of the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element's shadow DOM, much like how &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; is the root element of the document. The element containing the &lt;code&gt;#shadow-root&lt;/code&gt; itself is refered to as the "shadow host", which in this example is the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;. Everything that comes after &lt;code&gt;#shadow-root&lt;/code&gt; is the contents of the element's shadow DOM. Simple, right? :) &lt;/p&gt;

&lt;p&gt;Not all, but many elements are capable of having a &lt;code&gt;Shadow DOM&lt;/code&gt; attached to them, which can serve useful if you require a quick way to provide encapsulation and abstraction in your code.&lt;/p&gt;

&lt;p&gt;In this particular case, the &lt;code&gt;Shadow DOM&lt;/code&gt; of the input element contains only two &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; elements. As you may have been able to tell by the ids of each element, these are used to create the track, and thumb peices of the range slider.&lt;/p&gt;

&lt;p&gt;This is a &lt;em&gt;perfect&lt;/em&gt; example of the &lt;code&gt;Shadow DOM&lt;/code&gt; in action. It allows things like &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; elements to hide their moving parts and functionality away from the rest of the document, simplifying and keeping the program organized. &lt;/p&gt;

&lt;p&gt;We can take this a step further, by implementing the Shadow DOM API to create our own custom HTML components..😁&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating our first Custom HTML Element
&lt;/h2&gt;

&lt;p&gt;Before starting to build our custom element, we first need to understand some criteria it has to meet to be considered one: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; It has to have a constructor (usually via a &lt;code&gt;class&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;It needs to posses a &lt;code&gt;Shadow DOM&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It must be registered within the &lt;code&gt;CustomElementRegistry&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It can &lt;strong&gt;optionally&lt;/strong&gt; use a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any of these steps dont immediately make sence, dont sweat it, everything will become clear as i walk you through it.&lt;/p&gt;

&lt;p&gt;For demonstration in this short tutorial ill be making a custom HTML element named &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt;. The final product will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3ierny0lt51eh1q73ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3ierny0lt51eh1q73ys.png" alt="my custom "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I decided to make a simple custom element which consists of a &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt;, and a some &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; elements to serve as keys to show text onto the screen.&lt;/p&gt;

&lt;p&gt;An easy example that should clearly demonstrate how we can create somewhat complex custom elements using this API.&lt;/p&gt;

&lt;p&gt;Without further ado, lets start with the first step..👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Web Component Constructor
&lt;/h2&gt;

&lt;p&gt;Before we do anything else, its mandatory that we create a constructor function for our custom element. Its purpose is to initiate our component and attach any functionality it might have to it, and will be called each time a new instance of our web component is created.&lt;/p&gt;

&lt;p&gt;Below i create the constructor for our &lt;code&gt;&amp;lt;typewriter&amp;gt;&lt;/code&gt; element using a class:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Extend generic HTMLElement interface&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Typewriter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// implement functionality...&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I've named the class &lt;code&gt;Typewriter&lt;/code&gt;, though this dosent serve as the name we'll use to write it into our HTML (&lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt;), so you can call it whatever you want. Ill show how you can define a tagname for it in a later section.&lt;/p&gt;

&lt;p&gt;When creating your constructor, its required that you extend the functionality of an existing built-in HTML element, or the generic &lt;code&gt;HTMLElement&lt;/code&gt; interface. This is so that your custom element inherits all of the same required properties that all built-in elements do. Otherwise your custom element wouldn't be compatible with the DOM.&lt;/p&gt;

&lt;p&gt;There are two types of web components that can be created, based on the interface that you're extending:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Customizable components&lt;/strong&gt;: Custom elements where the constructor of which, extends upon the functionality and properties of an already existing built in element. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its constructor would be similar to -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Extend functionality of a &amp;lt;div&amp;gt; element&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Superdiv&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLDivElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And would be shown in HTML as -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;is=&lt;/span&gt;&lt;span class="s"&gt;"super-div"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autonomous components&lt;/strong&gt;: Custom elements where the constructor of which, extends the functionality of the generic &lt;code&gt;HTMLElement&lt;/code&gt; interface. These elements apply their own functionality, and share no properties in common with other built-in HTML elements other than those defined in the &lt;code&gt;HTMLElement&lt;/code&gt; interface (which serves as the bare-bones, or, minimum required properties for every HTML element). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its constructor would be similar to -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Extend the generic HTMLElement interface&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyElement&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And would be shown in HTML as -&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;my-element&amp;gt;&amp;lt;/my-element&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this case, our &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt; element is an &lt;strong&gt;autonomous&lt;/strong&gt; component, because it extends the &lt;code&gt;HTMLElement&lt;/code&gt; interface. I decided on an autonomous component because i didn't find it nesessary to extend another elements functionality, but mainly because i find writing &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt; into HTML rather than somthing like &lt;code&gt;&amp;lt;div is="type-writer"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; much more attractive..👌😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Attaching a Shadow DOM
&lt;/h2&gt;

&lt;p&gt;Now that we've got a container for our elements functionality, we need to attach a Shadow DOM onto our element upon its initiation.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Extend generic HTMLElement interface&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Typewriter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// attach shadow DOM to element&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;shadow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;closed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// implement functionality...&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After calling &lt;code&gt;super&lt;/code&gt;, i call the &lt;code&gt;attachShadow&lt;/code&gt; method of our new element (which was inherited from &lt;code&gt;HTMLElement&lt;/code&gt;) which returns the newly created &lt;code&gt;#shadow-root&lt;/code&gt;, which i store in the variable &lt;code&gt;shadow&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The one parameter it takes in is an object which contains a couple of configuration options. The &lt;code&gt;mode&lt;/code&gt; property indicates weather or not the elements within the &lt;code&gt;#shadow-root&lt;/code&gt; of our  element are accessable outside of the shadow host. Ive set it to &lt;code&gt;"closed"&lt;/code&gt; so that they aren't accessable, but you can use &lt;code&gt;"open"&lt;/code&gt; as well depending on your programs reqirements.&lt;/p&gt;

&lt;p&gt;We now have a reference to our shadow root, so we can go ahead and start appending content to it to construct our element!&lt;/p&gt;

&lt;h2&gt;
  
  
  Filling Our Shadow DOM
&lt;/h2&gt;

&lt;p&gt;I would say theres two good ways to go about adding content to the &lt;code&gt;Shadow DOM&lt;/code&gt; once its attached; you can create elements and append them to the &lt;code&gt;#shadow-root&lt;/code&gt; via normal DOM methods, or you could utilize a &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; Element
&lt;/h3&gt;

&lt;p&gt;The HTML template element is a unique element, used to hold content which will later be implemented.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="c"&gt;&amp;lt;!-- a simple template example --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"my-template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;&amp;lt;!-- template content --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;A simple template!&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; elements are parsed in HTML, but not rendered. Each &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; will have its own &lt;code&gt;content&lt;/code&gt; property, which is &lt;code&gt;DocumentFragment&lt;/code&gt;(much like a React fragment) of its contents. We can then clone this content and append it to our elements &lt;code&gt;#shadow-root&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;template&amp;gt;&lt;/code&gt; element can also be used in conjunction with the &lt;code&gt;&amp;lt;slot&amp;gt;&lt;/code&gt; element, which serves as a placeholder for you to add dynamic content into a template. Its a tad out of the scope of this guide, but you can read more about it &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below i create a template containing the content that will be inside of the &lt;code&gt;#shadow-root&lt;/code&gt; of my &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt; element, and append it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

  &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"typewriter-template"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;/* applying default styles to our element */&lt;/span&gt;
      &lt;span class="nt"&gt;textarea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;limegreen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5em&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;270px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt; 
    &lt;span class="c"&gt;&amp;lt;!-- screen --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- button container --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Typewriter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// attach shadow DOM to element&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;shadow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;closed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// Apply template&lt;/span&gt;
   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typewriter-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="c1"&gt;// implement functionality...&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Lastly, before implementing the final step, i'll add in all of the functionality for my custom &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt; element, completing our constructor:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Typewriter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// attach shadow DOM&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;shadow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attachShadow&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;closed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typewriter-template&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// implement template&lt;/span&gt;
&lt;span class="nx"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Adding keys and additional functions&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shadow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;textarea&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;typed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;backspc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;del&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nx"&gt;spc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;del&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DEL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;backspc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;del&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;backspc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nf"&gt;backspc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;del&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;spc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SPC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;spc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;backspc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;spc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Registering our &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt; Element
&lt;/h2&gt;

&lt;p&gt;Before we can use our new &lt;code&gt;&amp;lt;type-writer&amp;gt;&lt;/code&gt; tag in our HTML code, we lastly need to register our component within the &lt;code&gt;CustomElementRegistry&lt;/code&gt;. The &lt;code&gt;CustomElementRegistry&lt;/code&gt; interface is implemented by the &lt;code&gt;customElements&lt;/code&gt; object, which is where constructors for custom elements are stored, and can be accessed.&lt;/p&gt;

&lt;p&gt;We can register our new element by using the &lt;code&gt;customElements.define()&lt;/code&gt; method:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type-writer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;Typewriter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The first parameter is the tagname we want for our new element. This can be anything as long as a dash (-) is included within it. And then our second parameter is simply the constructor thats associated with our new custom element.&lt;/p&gt;

&lt;p&gt;Once thats done, you can use it in your HTML and refer to it in your CSS and Javascript just as you would with any other built-in element! Pretty cool, huh?&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="nt"&gt;&amp;lt;type-writer&amp;gt;&amp;lt;/type-writer&amp;gt;&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;And there you have it! I hoped this guide served useful for understanding how Web Components work, and how we can use the Shadow DOM and Custom elements APIs to create our own HTML elements.&lt;/p&gt;

&lt;p&gt;Good luck, and happy coding! 😁&lt;/p&gt;

</description>
      <category>html</category>
      <category>javascript</category>
      <category>webcomponents</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
