<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Michael Karén's Blog]]></title><description><![CDATA[I'm a web developer in Oslo.
I mostly write about JavaScript and Angular.
Sometimes about React and DevOps or other things.]]></description><link>https://blog.michaelkaren.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 15:12:48 GMT</lastBuildDate><atom:link href="https://blog.michaelkaren.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Angular Error Interceptor]]></title><description><![CDATA[When applications make HTTP requests and fail, we need to handle them. Ideally, we take care of these errors in one place in our code. In this article, we discover how to handle these exceptions in Angular by using an interceptor. We look into the be...]]></description><link>https://blog.michaelkaren.dev/angular-error-interceptor</link><guid isPermaLink="true">https://blog.michaelkaren.dev/angular-error-interceptor</guid><category><![CDATA[Angular]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[error handling]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 31 Jan 2022 10:10:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/XWar9MbNGUY/upload/v1644055822682/A0JKN_Zo5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When applications make HTTP requests and fail, we need to handle them. Ideally, we take care of these errors in one place in our code. In this article, we discover how to handle these exceptions in Angular by using an interceptor. We look into the best steps to take directly in the interceptor before sending errors on their way to the error handler.</p>
<h2 id="heading-what-are-angular-interceptors">What are Angular interceptors?</h2>
<p>Interceptors are unique Angular services that we can implement to add behavior to HTTP requests in our application. <a target="_blank" href="https://angular.io/api/common/http/HttpInterceptor">HttpInterceptor</a> provides a way to intercept HTTP requests and responses. In this sense, each interceptor can handle the request entirely by itself.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644055688435/MgKowzGiX.png" alt="interceptors diagram" /></p>
<p>As the diagram above shows, the interceptors are always in the middle of an HTTP request. As middlemen, they allow us to perform operations on the requests on their way to and back from the server, making it a perfect place to centralize code for things like adding headers, passing tokens, caching, and error handling.</p>
<h3 id="heading-what-is-an-error-interceptor">What is an error interceptor?</h3>
<p>An error interceptor is a special kind of interceptor used for handling errors that happen when making HTTP requests. Errors come either from the client-side (browser) or the server-side when the request fails for some reason. If the request fails on the server, <a target="_blank" href="https://angular.io/api/common/http/HttpClient">HttpClient</a> returns an error object instead of a successful response. When an error occurs, you can inform the user by reacting to the error details, or in some cases, you might want to retry the request.</p>
<p>If you are looking into more ways of using interceptors, then this article has plenty of them:</p>
<ul>
<li><a target="_blank" href="https://medium.com/angular-in-depth/top-10-ways-to-use-interceptors-in-angular-db450f8a62d6">Top 10 ways to use Interceptors in Angular</a></li>
</ul>
<h2 id="heading-implementing-the-interceptor">Implementing the interceptor</h2>
<p>To create an interceptor, declare a class that implements the <code>intercept()</code> method of the <code>HttpInterceptor</code> interface:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> {Injectable} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> {Observable} <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ErrorInterceptor <span class="hljs-keyword">implements</span> HttpInterceptor {

  intercept(request: HttpRequest&lt;<span class="hljs-built_in">any</span>&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;<span class="hljs-built_in">any</span>&gt;&gt; {
    <span class="hljs-keyword">return</span> next.handle(request);
  }
}
</code></pre>
<p>The <code>intercept()</code> method lets us inspect or alter a <code>request</code>. The <code>next</code> object represents the next interceptor in the chain of interceptors.</p>
<h3 id="heading-providing-the-interceptor">Providing the interceptor</h3>
<p>The ErrorInterceptor is a service that we must provide before the app can use it:</p>
<pre><code class="lang-ts"><span class="hljs-meta">@NgModule</span>({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: <span class="hljs-literal">true</span> }
  ]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppModule {}
</code></pre>
<p>Now that we set up the interceptor, we can start powering it up with some error handling capabilities.</p>
<h2 id="heading-the-retry-strategy">The retry strategy</h2>
<p>As an alternative to re-throwing errors, we can <em>retry</em> to subscribe to the errored out Observable. For example, network interruptions can happen in mobile scenarios, and trying again can produce a successful result. RxJS offers several retry operators. For example, the <code>retry()</code> operator automatically re-subscribes a specified number of times, in effect reissuing the HTTP request. The following example shows how to retry a failed request:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> {Injectable} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> {Observable} <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;
<span class="hljs-keyword">import</span> {retry} <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs/operators'</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ErrorInterceptor <span class="hljs-keyword">implements</span> HttpInterceptor {

  intercept(request: HttpRequest&lt;<span class="hljs-built_in">any</span>&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;<span class="hljs-built_in">any</span>&gt;&gt; {
    <span class="hljs-keyword">return</span> next.handle(request)
      .pipe(retry(<span class="hljs-number">3</span>)); <span class="hljs-comment">// Retry failed request up to 3 times.</span>
  }
}
</code></pre>
<p>This strategy might save us from a few errors, but more often than not, it creates unneeded requests. Let’s see how we can minimize them.</p>
<h3 id="heading-retry-when">Retry when?</h3>
<p>To make our retry strategy smarter, we can use <code>retryWhen()</code>, which provides a mechanism for retrying errors based on custom criteria. We have three conditions for our smart retry:</p>
<ul>
<li>Retry twice at most</li>
<li>Only retry 500 internal server errors</li>
<li>Wait before retrying</li>
</ul>
<p>With these conditions, we figure we give whatever is causing the exception a chance to recover and only retry to errors that can succeed if we try again.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> {Injectable} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> {Observable, <span class="hljs-keyword">of</span>, throwError} <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;
<span class="hljs-keyword">import</span> {mergeMap, delay, retryWhen} <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs/operators'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> maxRetries = <span class="hljs-number">2</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> delayMs = <span class="hljs-number">2000</span>;

<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ErrorInterceptor <span class="hljs-keyword">implements</span> HttpInterceptor {

  intercept(request: HttpRequest&lt;unknown&gt;, next: HttpHandler): Observable&lt;HttpEvent&lt;unknown&gt;&gt; {
    <span class="hljs-keyword">return</span> next.handle(request).pipe(
      retryWhen(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> 
        <span class="hljs-keyword">return</span> error.pipe(
          mergeMap(<span class="hljs-function">(<span class="hljs-params">error, index</span>) =&gt;</span> {
            <span class="hljs-keyword">if</span> (index &lt; maxRetries &amp;&amp; error.status == <span class="hljs-number">500</span>) {
              <span class="hljs-keyword">return</span> <span class="hljs-keyword">of</span>(error).pipe(delay(delayMs));
            }

            <span class="hljs-keyword">throw</span> error;
          })
        )
      )
    )
  }
}
</code></pre>
<p>The <code>index</code> from <code>mergeMap()</code> tells us which try we are on to stop retrying when we reach our limit. We can then check the <strong>status of the exception</strong>. And depending on the error <code>status</code>, we can decide what to do. In this example, we retry twice with a delay when we get the error status 500. All remaining errors are re-thrown for further handling.</p>
<p>If you are interested in the whole picture, check out my article:</p>
<ul>
<li><a target="_blank" href="https://medium.com/angular-in-depth/expecting-the-unexpected-best-practices-for-error-handling-in-angular-21c3662ef9e4">Expecting the Unexpected — Best practices for Error handling in Angular</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this guide, we looked at different ways to handle failed HTTP requests using the power of RxJS. Applying different retry strategies can help us specify what should happen and when if the unexpected happens. All this might seem like a small detail, but saving users from errors will make both them, the support personnel, and in the end, the developers happy.</p>
]]></content:encoded></item><item><title><![CDATA[How to Combine Add and Edit Forms in Angular]]></title><description><![CDATA[This article demonstrates how to build a reusable form component that supports add and edit modes. We do this by using the container and presentation components architecture. The goal is not about teaching forms, so we keep it as simple as possible u...]]></description><link>https://blog.michaelkaren.dev/how-to-combine-add-and-edit-forms-in-angular</link><guid isPermaLink="true">https://blog.michaelkaren.dev/how-to-combine-add-and-edit-forms-in-angular</guid><category><![CDATA[Angular]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[forms]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 24 Jan 2022 08:27:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/ldDmTgf89gU/upload/v1642958054493/2njBVTDCG.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article demonstrates how to build a reusable form component that supports add and edit modes. We do this by using the container and presentation components architecture. The goal is not about teaching forms, so we keep it as simple as possible using reactive forms.</p>
<hr />
<h2 id="heading-the-form">The form</h2>
<p>We create a simplified form without any validation to add and edit medals. The medal has three properties:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> Medal {
  name: <span class="hljs-built_in">string</span>;
  <span class="hljs-keyword">type</span>: <span class="hljs-built_in">string</span>;
  sport: <span class="hljs-built_in">string</span>;
}
</code></pre>
<p>With reactive forms, the <code>[formGroup]</code> is a directive that we bind to and pass the <code>form</code> object in:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"!medal"</span>&gt;</span>Add Medal<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> *<span class="hljs-attr">ngIf</span>=<span class="hljs-string">"medal"</span>&gt;</span>Edit Medal<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">form</span> [<span class="hljs-attr">formGroup</span>]=<span class="hljs-string">"form"</span> (<span class="hljs-attr">ngSubmit</span>)=<span class="hljs-string">"submit()"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"name"</span> /&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Type<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"type"</span> /&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Sport<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">formControlName</span>=<span class="hljs-string">"sport"</span> /&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Submit<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>We inject the <code>FormBuilder</code> service and use the <code>group()</code> method to create the <code>form</code> controls matching the template:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { 
  ChangeDetectionStrategy, Component, EventEmitter, 
  Input, OnInit, OnChanges, Output, SimpleChanges
} <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { FormGroup, FormBuilder } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/forms'</span>;
<span class="hljs-keyword">import</span> { Medal } <span class="hljs-keyword">from</span> <span class="hljs-string">'../app.component'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'medal-form'</span>,
  templateUrl: <span class="hljs-string">'medal-form.component.html'</span>,
  changeDetection: ChangeDetectionStrategy.OnPush
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> MedalFormComponent <span class="hljs-keyword">implements</span> OnInit, OnChanges {
  <span class="hljs-meta">@Input</span>() medal: Medal;
  <span class="hljs-meta">@Output</span>() submitted = <span class="hljs-keyword">new</span> EventEmitter&lt;Medal&gt;();
  form: FormGroup;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> fb: FormBuilder</span>) {}

  ngOnInit() {
    <span class="hljs-built_in">this</span>.form = <span class="hljs-built_in">this</span>.fb.group({
      name: [<span class="hljs-string">''</span>],
      <span class="hljs-keyword">type</span>: [<span class="hljs-literal">null</span>],
      sport: [<span class="hljs-literal">null</span>],
    });
  }

  ngOnChanges(changes: SimpleChanges) {
    <span class="hljs-keyword">if</span> (changes.medal?.currentValue) {
      <span class="hljs-built_in">this</span>.form?.patchValue(<span class="hljs-built_in">this</span>.medal);
    }
  }

  submit() {
    <span class="hljs-built_in">this</span>.submitted.emit(<span class="hljs-built_in">this</span>.form.getRawValue());
    <span class="hljs-built_in">this</span>.form.reset();
  }
}
</code></pre>
<p>We use the <code>Input()</code> decorator for the <code>medal</code> property. Then we use it when we have data that we can send to the child component. To watch for changes on an <code>Input()</code> property, we use the <code>OnChanges</code> lifecycle hook. Whenever it detects changes to the medal property, we populate the form with <code>patchValue()</code>. When submit is pressed, we emit the form values through the <code>Output()</code> property <code>submitted</code>.</p>
<p>We have implemented our reusable form component as a dumb component. Now let us talk more about the architecture we chose and how we use the form component we created.</p>
<hr />
<h2 id="heading-the-problem-area">The problem area</h2>
<p>Let us first consider why we want to split into these two components. When using only one, we need to <code>subscribe()</code> to the observable data that Angular is keen for us to use. There are disadvantages to manually subscribing to observables. Some can lead to bugs that can be hard to debug. Using <code>subscribe()</code> also requires us to unsubscribe at the end of the component lifecycle to avoid memory leaks.</p>
<p>Subscribing to the observable manually in the <code>ngOnInit()</code> doesn't always work with the preferred <code>OnPush</code> change detection strategy out of the box. We sometimes need to tell Angular change detection manually when we want it to run. Needless to say, when someone comes to me for help with code where the data is not updating for some reason, the first thing I do is look for a <code>subscribe()</code> in the code.</p>
<h2 id="heading-async-pipe-to-the-rescue">Async pipe to the rescue?</h2>
<p>The next, better solution is to use the <code>async</code> pipe. But, this also has some downsides. Objects have to be unwrapped, sometimes multiple times, in the template using <code>*ngIf="data$ | async as data"</code>. </p>
<p>Properties unwrapped using <code>*ngIf</code> or <code>*ngFor</code> are not accessible in the component's methods. We have to pass these properties to the methods from the template as method parameters which makes the code harder to read. And let me not get started about the testing.</p>
<p>So how can we then solve this better?</p>
<hr />
<h2 id="heading-smartdumb-components">Smart/dumb components</h2>
<p>For a better architecture, we split components into two types of specialized components:</p>
<ul>
<li><strong>Smart components:</strong> also known as container components.</li>
<li><strong>Dumb components:</strong> also known as presentation components.</li>
</ul>
<p>The responsibility of the dumb component is to present the data, while the smart one is responsible for fetching and managing the data. Presentation components should be child components of the container components on your page.</p>
<p>Interaction between smart and dumb components is done by:</p>
<ul>
<li><code>Input</code> -presentation component receives data from parent</li>
<li><code>Output</code> -presentation component triggers actions that parent listens to</li>
</ul>
<p>By doing this, the presentation component remains isolated from the parent container component via a clearly defined interface.</p>
<h2 id="heading-using-the-form">Using the form</h2>
<p>For the final piece of the puzzle, here are the ways we can use our presentational form as a <em>create form</em>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">medal-form</span>
  (<span class="hljs-attr">submitted</span>)=<span class="hljs-string">"onSubmitted($event)"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">medal-form</span>&gt;</span>
</code></pre>
<p>We don't send any data in, so we get an empty form from which we get notified when it is submitted. Then the only thing left for us to do is call the backend through our store or service.</p>
<p>In the <em>edit form</em> we fetch the data and send it into the form through an <em>async pipe</em>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">medal-form</span> 
  [<span class="hljs-attr">medal</span>]=<span class="hljs-string">"medal$ | async"</span>
  (<span class="hljs-attr">submitted</span>)=<span class="hljs-string">"onSubmitted($event)"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">medal-form</span>&gt;</span>
</code></pre>
<p>Now, we let the framework handle the subscriptions for us. The presentational component manages the data as objects instead of observables.</p>
<p>I have created a playground for you to play with the code. There is no data fetching or <em>async pipe</em> used, but it gives you an idea of how it works.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://stackblitz.com/edit/angular-ivy-c87lvm">https://stackblitz.com/edit/angular-ivy-c87lvm</a></div>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we combined two forms by making a presentational component. When we send it data with an async pipe, it receives the unwrapped object and populates the form with it. This architecture gives us a cleaner, more robust solution that hopefully keeps the bugs away.</p>
]]></content:encoded></item><item><title><![CDATA[Game Development: Breakout in JavaScript]]></title><description><![CDATA[In this article, we create a complete Breakout-style game. The HTML Canvas provides the game container where we draw graphics via JavaScript. After learning how to use the Canvas for graphics and animations, we go through the algorithms behind collis...]]></description><link>https://blog.michaelkaren.dev/game-development-breakout-in-javascript</link><guid isPermaLink="true">https://blog.michaelkaren.dev/game-development-breakout-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[HTML Canvas]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Tue, 11 Jan 2022 19:55:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1642535641765/j_ztjlVSB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we create a <strong>complete</strong> Breakout-style <strong>game</strong>. The HTML <strong>Canvas</strong> provides the game container where we draw graphics via <strong>JavaScript</strong>. After learning how to use the Canvas for graphics and animations, we go through the algorithms behind collisions using basic shapes like circles and rectangles. With these concepts and a sprinkle of game loops and sound, we will soon have a game ready to be played!</p>
<p>Check out the code in my <a target="_blank" href="https://github.com/melcor76/js-breakout">GitHub repository js-breakout</a> or <a target="_blank" href="https://affectionate-shockley-c3f5d7.netlify.app/">play the game</a>!</p>
<p>If you like JavaScript games, you might like my article about Tetris:</p>
<ul>
<li><a target="_blank" href="https://michael-karen.medium.com/learning-modern-javascript-with-tetris-92d532bcd057">Learning Modern JavaScript with Tetris</a></li>
</ul>
<p>When we talk about legendary games, <strong>Breakout</strong> is on the list. And not only because it is Atari’s single-player sequel to Pong, but also because both Steve Jobs and Steve Wozniak worked on it and later founded Apple with some of the money. By modern standards, the game is pretty simple but in 1976, the year I was born, it was revolutionary. Ten years later, the concept found new legs with Taito’s 1986 <a target="_blank" href="http://shot97retro.blogspot.com/2019/10/arkanoid-in-depth-written-amiga-review.html">Arkanoid</a>, which itself spawned dozens of imitators. The genre is known as block breaker games.</p>
<p>The game’s success continues to this day, and Atari continues to port it to new platforms. Indeed, you can find an official port on Android, iPhone, and iPad. Breakout is one of the most cloned games of all time. Let’s see if we can add to that statistics with the help of this course.</p>
<h2 id="heading-game-design">Game design</h2>
<p>All Breakout-style games have at least three things in common — each contains <strong>paddles, balls, and bricks</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528667451/L5iozA3WL.png" alt="design of ball, bricks, and paddle" /></p>
<p>The player has to break through rows of brick walls by bouncing a ball against it with a paddle. The bricks are in different colors. Depending on the color, bricks can award more points and be harder to break. And to make the game more challenging, at some points in the game, the speed might increase. And as the final hurdle, the paddle can decrease its size when the player breaks through the last row. If the player loses the ball three times, it’s game over.</p>
<hr />
<h2 id="heading-getting-started">Getting started</h2>
<p>Before starting with the game’s functionality, we need to create a basic structure to render the game inside. We can do this with HTML and the <code>&lt;canvas&gt;</code> element.</p>
<p>It’s good practice to split code into different files even if the project is not that big:</p>
<ul>
<li><code>index.html</code> — The main file with links to the others. The order of the scripts that we add at the end is essential.</li>
<li><code>styles.css</code> — Contains the styles.</li>
<li><code>breakout.js</code> — JavaScript code for the game.</li>
</ul>
<p>We can consider splitting the JavaScript into multiple files when it grows bigger.</p>
<h3 id="heading-html-and-css">HTML and CSS</h3>
<p>The HTML document structure is quite simple, as the game renders on the <code>&lt;canvas&gt;</code> element. The only other part that we need to worry about is the button that starts the game.</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Breakout Game<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"styles.css"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"breakout"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"600"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"400"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">br</span>/&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"play-button"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"play()"</span>&gt;</span>Play<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"breakout.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<pre><code class="lang-css"><span class="hljs-selector-id">#breakout</span> {
  <span class="hljs-attribute">background-color</span>: black;
}

<span class="hljs-selector-id">#play-button</span> {
  <span class="hljs-attribute">background-color</span>: green;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<h2 id="heading-the-javascript">The JavaScript</h2>
<p>At the end of the HTML file, we add references to our JavaScript files. <code>&lt;script&gt;</code> elements contain JavaScript code executed by the browser.</p>
<p>For now, we can add an empty function corresponding to the <code>onclick</code> event that we add to the play button:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{}
</code></pre>
<p>With this, we have our game container styled and ready, awaiting code.</p>
<hr />
<h2 id="heading-canvas">Canvas</h2>
<p>Drawing graphics and creating animations in the browser can be done in a few different ways. In this course, we use <strong>HTML5 Canvas</strong>, with a feature set ideal for producing 2D and 3D games. The canvas element is defined in HTML code using <code>width</code> and <code>height</code> attributes. Then we can use the HTML5 Canvas API by writing JavaScript. We access the canvas through drawing functions to dynamically generate graphics.</p>
<h3 id="heading-canvas-context">Canvas context</h3>
<p>The canvas has a <strong>2D drawing context</strong> used for drawing shapes, text, images, and other objects. First, we choose the color and brush, and then we paint. We can change the brush and color before drawing or continue with what we have.</p>
<p>The <code>HTMLCanvasElement.getContext()</code> method returns a drawing context, where we render the graphics. By supplying <code>'2d'</code> as the argument we get the canvas 2D rendering context:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ctx = canvas.getContext(<span class="hljs-string">'2d'</span>);
</code></pre>
<blockquote>
<p>There are other available contexts, like <code>webgl</code> for a three-dimensional rendering context, outside the scope of this article.</p>
</blockquote>
<h3 id="heading-coordinate-system">Coordinate system</h3>
<p>The HTML canvas is a two-dimensional grid. The upper-left corner of the canvas has the coordinates (0, 0).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528669053/YlfgO7nwn.png" alt="Canvas coordinate system" /></p>
<p>If you are interested in more detail about the Canvas, you can check my article:</p>
<ul>
<li><a target="_blank" href="https://medium.com/dailyjs/how-to-get-started-with-canvas-animations-in-javascript-cb2ccf37515c">How to Get Started with Canvas Animations in JavaScript</a></li>
</ul>
<h2 id="heading-graphics">Graphics</h2>
<p>We can draw the ball using an image for a better-looking game. But, before we do that, we need to keep track of the position and other values connected to the ball. To do this, we can define a <code>ball</code> object. We start by defining the only constant value we know at the moment it will have, the <code>radius</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ball = {  
  <span class="hljs-attr">radius</span>: <span class="hljs-number">10</span>  
}
</code></pre>
<p>When the game starts, we want to give the ball some initial values, like its position. We define the starting <code>x</code> and <code>y</code> coordinates of the ball to the bottom center part of the canvas in the function <code>resetBall()</code> that we then call from the <code>play()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetBall</span>(<span class="hljs-params"></span>) </span>{  
  ball.x = canvas.width / <span class="hljs-number">2</span>,  
  ball.y = canvas.height — <span class="hljs-number">100</span>  
}
</code></pre>
<p>It will be helpful later on to have a function for resetting the starting values for the ball instead of defining them in the ball object.</p>
<p>Next, we <strong>define the images</strong> we use for the ball and background. For each object property, we first create it as a <code>new Image()</code> and then set its <code>src</code> to the files we are using:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> images = {  
  <span class="hljs-attr">background</span>: <span class="hljs-keyword">new</span> Image(),  
  <span class="hljs-attr">ball</span>: <span class="hljs-keyword">new</span> Image()  
}

images.background.src = <span class="hljs-string">'bg-space.webp'</span>;  
images.ball.src = <span class="hljs-string">'ball.webp'</span>;
</code></pre>
<blockquote>
<p>The images are in the <strong>WebP</strong> format, yielding smaller files of the same quality as PNG or JPEG.</p>
</blockquote>
<p>To draw the images, we use <code>drawImage()</code>, which provides different ways to draw an image onto the canvas:</p>
<pre><code class="lang-js">ctx.drawImage(image, x, y, width, height);
</code></pre>
<p>We provide the coordinates to the top left corner of the image and then the size of the image. For the <strong>background,</strong> we use the width and height of the canvas to have the background image cover the whole playing field. For the <strong>ball,</strong> we double the radius to get the diameter, which acts as both the width and height of the ball image:</p>
<pre><code><span class="hljs-comment">// draw background  </span>
ctx.drawImage(images.background, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);

<span class="hljs-comment">// draw ball  </span>
ctx.drawImage(images.ball, ball.x, ball.y, <span class="hljs-number">2</span><span class="hljs-operator">*</span>ball.radius, <span class="hljs-number">2</span><span class="hljs-operator">*</span>ball.radius);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528670854/RHr1vUMXZ.png" alt="Ball and background" /></p>
<hr />
<h2 id="heading-animation">Animation</h2>
<p>Now that we know how to draw on the canvas, we are ready to take the next step — making the ball move. To do this, we paint the ball on the screen, clear it, and then draw it again in a different position. Doing animations on Canvas is like making a stop-motion movie. We move the objects a little bit in each frame to animate them.</p>
<h3 id="heading-drawing-loop">Drawing loop</h3>
<p>Canvas uses <strong>immediate rendering</strong> — when we draw, it immediately renders on the screen. But, it is a fire-and-forget system. After we paint something, the canvas forgets about the object and only knows it as pixels. So there is no object that we can move. Instead, we have to draw it again.</p>
<p>To do this, we need to define a drawing function that runs with a different set of variable values each time. We can run functions over and over again using a JavaScript timing function such as <code>requestAnimationFrame()</code>, which has some clear benefits over <code>setInterval()</code>:</p>
<ul>
<li>It enables browser optimizations.  </li>
<li>It handles the frame rate.  </li>
<li>Animations only run when visible.</li>
</ul>
<p>The way to animate with <code>requestAnimationFrame()</code> is to create a function that paints a frame and then schedules itself to invoke again. By doing this, we get an asynchronous loop that executes when we draw on the canvas. We invoke the <code>paint()</code> function repeatedly until we decide to stop.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Start loop</span>
  animate();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Paint frame</span>
  paint();

  <span class="hljs-comment">// Schedule next frame</span>
  requestAnimationFrame(animate); 
}
</code></pre>
<p>We must remember to use the <code>cancelAnimationFrame()</code> method to cancel previously scheduled requests. If we forget to do this, we will notice the game going faster every time we press play since we will have more and more animation loops running in our code.</p>
<p>We can add the <code>requestId</code> to the game object and check for a value before running a new animation. And then, we set this variable each time we run a new <em>requestAnimationFrame</em>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{
  cancelAnimationFrame(game.requestId);
  resetBall();

  animate();
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params"></span>) </span>{
  paint();
  update();

  game.requestId = requestAnimationFrame(animate);
}
</code></pre>
<p>There is one more thing to do. We need to calculate how often the animation will progress a frame, <strong>otherwise the animation will run faster on high refresh rate screens.</strong></p>
<h3 id="heading-timer">Timer</h3>
<p>We call the <code>requestAnimationFrame()</code> function when it’s time to update the animation for the next repaint. But to account for different screen refresh rates, we need to calculate if we should update our game at this call.</p>
<pre><code class="lang-js">requestAnimationFrame(callback);
</code></pre>
<p>The callback function is passed one single argument, a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp"><code>DOMHighResTimeStamp</code></a> similar to the one returned by <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/now"><code>performance.now()</code></a>, indicating the point in time when <code>requestAnimationFrame()</code> starts to execute callback functions. We can use this timestamp to calculate when to paint and update our game.</p>
<p>First, we add a time object to keep track of everything related and set it in the <code>resetGame()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetGame</span>(<span class="hljs-params"></span>) </span>{  
  game.time = {  
    <span class="hljs-attr">start</span>: performance.now(),  
    <span class="hljs-attr">elapsed</span>: <span class="hljs-number">0</span>,  
    <span class="hljs-attr">refreshRate</span>: <span class="hljs-number">16</span>  
  };  
}
</code></pre>
<p>We add a call to <code>resetGame()</code> in the <code>play()</code> function. Then in the animate loop, we add code that checks if the 16ms of the <code>refreshRate</code> have passed to see if it’s time to paint another frame:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params">timestamp</span>) </span>{ 
  game.time.elapsed = timestamp - game.time.start;
  <span class="hljs-keyword">if</span> (game.time.elapsed &gt; game.time.refreshRate) {
    game.time.start = timestamp;

    paint();
    update();
  }    

  game.requestId = requestAnimationFrame(animate);
}
</code></pre>
<p>Now that we have a loop that keeps drawing the game at each frame, we need to change the position before the next paint.</p>
<h3 id="heading-moving-the-ball">Moving the ball</h3>
<p>We defined the starting point at the bottom-center part of the Canvas with the coordinates of the ball object. After drawing the ball, we want to change the <code>x</code> and <code>y</code> to move it to a new position.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528673002/zDh2vcUiM.png" alt="Coordinate system showing changes in x and y." /></p>
<p>Without going too much into the math behind it we can use <code>dx</code> and <code>dy</code> to define the change. The larger the value of the change, the faster the ball moves.</p>
<blockquote>
<p>The Greek letter Δ (delta) means <em>the change in</em> a variable.</p>
</blockquote>
<p>We need a <code>speed</code> setting as a base for other movement-related variables. To speed up the game, we change this property.</p>
<p>When we launch the ball, it should be in a random upwards direction. If we always have the same trajectory, the game would get predictable fast. The ball moves upwards when <code>dy</code> has a negative value, so we set it to <code>-speed.</code> With <code>Math.Random()</code>, we can randomize the direction on the x-axis the ball shoots off:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetGame</span>(<span class="hljs-params"></span>) </span>{
  game.speed = <span class="hljs-number">7</span>;
  game.time = {<span class="hljs-attr">start</span>: performance.now(), <span class="hljs-attr">elapsed</span>: <span class="hljs-number">0</span>, <span class="hljs-attr">refreshRate</span>: <span class="hljs-number">16</span>};
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetBall</span>(<span class="hljs-params"></span>) </span>{
  ball.x = canvas.width / <span class="hljs-number">2</span>;
  ball.y = canvas.height - <span class="hljs-number">100</span>;
  ball.dx = game.speed * (<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">2</span> - <span class="hljs-number">1</span>);  <span class="hljs-comment">// Random trajectory</span>
  ball.dy = -game.speed; <span class="hljs-comment">// Up</span>
}
</code></pre>
<p>Then we update <code>x</code> and <code>y</code> with with the change on every frame. The ball will be painted in the new position on every update. Adding these two lines gives us this <code>update()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span>(<span class="hljs-params"></span>) </span>{  
  ball.x += ball.dx;  
  ball.y += ball.dy;  
}
</code></pre>
<p>We call <code>update()</code> from the <code>animate()</code> function after painting the current frame. This way, we are prepared with the new positions for the next paint.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528674822/vWSBPF0Yd.png" alt="Moving the ball in different directions" /></p>
<p>Before each new frame, we need to clear the canvas. We can do this with the <code>CanvasRenderingContext2D.clearRect()</code> method, which erases the pixels in a rectangular area by setting them to transparent black. But instead, we can start each new frame by drawing the background, which also clears everything from the previous frame. To keep our animate function clean, we can add all the code that has to do with drawing objects to the canvas to a <code>paint()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">paint</span>(<span class="hljs-params"></span>) </span>{
  ctx.drawImage(images.background, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
  ctx.drawImage(images.ball, ball.x, ball.y, <span class="hljs-number">2</span>*ball.radius, <span class="hljs-number">2</span>*ball.radius);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params"></span>) </span>{
  paint();
  update();

  game.requestId = requestAnimationFrame(animate);
}
</code></pre>
<p>Each frame canvas clears by painting the background. Then we draw the ball before updating the x and y values for the next frame. By scheduling a new run of the <code>animate()</code> function with <code>requestAnimationFrame()</code> we create an animation loop.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528677231/8vUMF_BhS.gif" alt="Ball animation" /></p>
<hr />
<h2 id="heading-collision-detection">Collision detection</h2>
<p>In the previous chapter, we got the ball moving. But it quickly travels off the screen and ends the fun. We need to implement <em>collision detection</em> to make the ball bounce off the walls.</p>
<p>First, we need to calculate when a collision happens. After that, we need to think about which direction we were moving when we hit the target object. Then we can send the ball the opposite way after the hit.</p>
<h3 id="heading-boundaries">Boundaries</h3>
<p>For the ball to be inside the game field, all three of the following statements need to be true:</p>
<ul>
<li><strong>X</strong> of the ball is greater than x of the left wall.  </li>
<li><strong>X</strong> of the ball is less than x of the right wall.  </li>
<li><strong>Y</strong> of the ball is greater than y of the roof.</li>
</ul>
<p>The ball is drawn to the canvas at coordinates from the upper left corner. We need to consider the width of the ball. Therefore, we need to consider the ball width when checking for collisions on the opposing sides. The width, or the diameter, equals two times the radius of the ball (2r).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528679234/aVn94a2rF.png" alt="Ball coordinates with radius" /></p>
<h3 id="heading-detecting-collisions">Detecting collisions</h3>
<p>The first wall that the ball flies through is the right one. We can detect when the ball collides with it by checking when <code>x</code> is larger than the width of the canvas. In this case, we need to add <code>2*ball.radius</code> since the collision happens with the right side of the ball.</p>
<p>When the collision happens, we make the ball move in the opposite direction by reversing the movement on the x-axis by negating the delta x (dx):</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (ball.x + <span class="hljs-number">2</span> * ball.radius &gt; canvas.width) {  
  ball.dx = -ball.dx;  
}
</code></pre>
<p>When we hit the left wall, we reverse the direction of the x-axis again. This time we check for when x is less than zero, where the x-axis starts. In this case, the collision happens with the left side of the ball, meaning we don’t need to change the x value:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (ball.x &lt; <span class="hljs-number">0</span>) {  
  ball.dx = -ball.dx;  
}
</code></pre>
<p>Lastly, we need to bounce off the roof. In this case, we reverse the movement on the y-axis when the y value goes below zero. The horizontal movement on the y-axis is represented by delta y:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (ball.y &lt; <span class="hljs-number">0</span>) {  
  ball.dy = -ball.dy;  
}
</code></pre>
<p>We add all these checks together into the function <code>detectCollision()</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params">timestamp</span>) </span>{
  game.time.elapsed = timestamp - game.time.start;
  <span class="hljs-keyword">if</span> (game.time.elapsed &gt; game.time.refreshRate) {
    game.time.start = timestamp;

    paint();
    detectCollision();
    update();
  }    

  game.requestId = requestAnimationFrame(animate);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">detectCollision</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span>(ball.x + <span class="hljs-number">2</span> * ball.radius &gt; canvas.width || ball.x &lt; <span class="hljs-number">0</span>) {
    ball.dx = -ball.dx;
  }

  <span class="hljs-keyword">if</span>(ball.y &lt; <span class="hljs-number">0</span>) {
    ball.dy = -ball.dy;
  }
}
</code></pre>
<p>This code does what it is supposed to, but it can be hard to read. To increase readability, we add function expressions that return the calculations. We also need to make sure the coordinates aren’t outside the playing area. So we make sure to move the coordinates back to the wall:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">detectCollision</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> hitTop = <span class="hljs-function">() =&gt;</span> ball.y &lt; <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> hitLeftWall = <span class="hljs-function">() =&gt;</span> ball.x &lt; <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> hitRightWall = <span class="hljs-function">() =&gt;</span> ball.x + <span class="hljs-number">2</span> * ball.radius &gt; canvas.width;

  <span class="hljs-keyword">if</span> (hitLeftWall()) {
    ball.dx = -ball.dx;
    ball.x = <span class="hljs-number">0</span>;
  }        
  <span class="hljs-keyword">if</span> (hitRightWall()) {
    ball.dx = -ball.dx;
    ball.x = canvas.width - <span class="hljs-number">2</span> * ball.radius;
    }
  <span class="hljs-keyword">if</span> (hitTop()) {
    ball.dy = -ball.dy;
    ball.y = <span class="hljs-number">0</span>;
  }
}
</code></pre>
<p>That’s better! With this code implemented we have taken care of all the walls that we need the ball to bounce off. But as you might have noticed there is one collision that we have not taken care of yet.</p>
<h2 id="heading-game-over">Game over</h2>
<p>When the ball falls down the floor, we don’t want it to bounce back, but instead, this is when we lose the game — Game over.</p>
<p>Before we schedule the next run of <code>animate()</code>, we check if the ball went out of bounds at the bottom of the court. If the game is lost, we show a message to the user. We write text on the screen by setting the <code>fillStyle</code> and telling what and where we want it with <code>fillText()</code>. Here, we compute the message to be in the middle of the canvas:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params">timestamp</span>) </span>{ 
  game.time.elapsed = timestamp - game.time.start;
  <span class="hljs-keyword">if</span> (game.time.elapsed &gt; game.time.refreshRate) {
    game.time.start = timestamp;

    paint();
    update();
    detectCollision();

    <span class="hljs-keyword">if</span> (isGameOver()) <span class="hljs-keyword">return</span>;
  }

  requestId = requestAnimationFrame(animate);
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isGameOver</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> isBallLost = <span class="hljs-function">() =&gt;</span> ball.y &gt; canvas.height;

  <span class="hljs-keyword">if</span> (isBallLost()) {
    gameOver();
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }  
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gameOver</span>(<span class="hljs-params"></span>) </span>{
  ctx.font = <span class="hljs-string">'40px Arial'</span>;
  ctx.fillStyle = <span class="hljs-string">'red'</span>;
  ctx.fillText(<span class="hljs-string">'GAME OVER'</span>, canvas.width / <span class="hljs-number">2</span> - <span class="hljs-number">100</span>, canvas.height / <span class="hljs-number">2</span>);
}
</code></pre>
<p>We use the <code>return</code> statement to short-circuit the <code>animate()</code> loop. If <code>isGameOver()</code> returns true, we don’t request the next frame. Now, if we run the code, the ball bounces off the walls as it should, and we get a game over screen when the ball falls out of bounds.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528681333/j3dS3GopK.png" alt="Game over screen" /></p>
<hr />
<h2 id="heading-paddle">Paddle</h2>
<p>Now that we have a ball bouncing off the walls, it’s time to evolve this demo into a game by adding player interaction. Let’s add a paddle that the player can control and bounce the ball off!</p>
<p>As per usual we start by adding some variables to define a <code>paddle</code> object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> paddle = {
  <span class="hljs-attr">height</span>: <span class="hljs-number">20</span>,
  <span class="hljs-attr">width</span>: <span class="hljs-number">100</span>,
  <span class="hljs-keyword">get</span> <span class="hljs-title">y</span>() { 
    <span class="hljs-keyword">return</span> canvas.height - <span class="hljs-built_in">this</span>.height; 
  }
}
</code></pre>
<p>The paddle moves at the bottom of the court, so the value on the y-axis is constant. There is a dependency on the height property of the same object, which means we need to use a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get">getter</a>.</p>
<p>However, we need to keep track of where on the x-axis the paddle is at each moment. We want the paddle to start in the middle of the court every time we start a new life or level, so we define a function <code>resetPaddle()</code> where we compute the x value:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetPaddle</span>(<span class="hljs-params"></span>) </span>{
  paddle.x = (canvas.width - paddle.width) / <span class="hljs-number">2</span>;
  paddle.dx = game.speed + <span class="hljs-number">7</span>;
}
</code></pre>
<p>Finally, the paddle has to be faster than the ball so that we have a chance to catch it, so we set <code>dx</code> for the paddle to an increment of the game speed.</p>
<h3 id="heading-drawing-the-paddle">Drawing the paddle</h3>
<p>Next, we add the code needed to draw the paddle at each frame. We add a <code>paddle</code> property to our <code>images</code> object and set the <code>src</code> to the image of the paddle. Then we use <code>drawImage()</code> as with the background and ball in the <code>paint()</code> function to draw the paddle in the correct position on each frame:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> images = {
  <span class="hljs-attr">background</span>: <span class="hljs-keyword">new</span> Image(),
  <span class="hljs-attr">ball</span>: <span class="hljs-keyword">new</span> Image(),
  <span class="hljs-attr">paddle</span>: <span class="hljs-keyword">new</span> Image() <span class="hljs-comment">// New</span>
}

images.background.src = <span class="hljs-string">'bg-space.webp'</span>;
images.ball.src = <span class="hljs-string">'ball.webp'</span>;
images.paddle.src = <span class="hljs-string">'paddle.webp'</span>; <span class="hljs-comment">// New</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">paint</span>(<span class="hljs-params"></span>) </span>{
  ctx.drawImage(images.background, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
  ctx.drawImage(images.ball, ball.x, ball.y, <span class="hljs-number">2</span> * ball.radius, <span class="hljs-number">2</span> * ball.radius);
  ctx.drawImage(images.paddle, paddle.x, paddle.y, paddle.width, paddle.height); <span class="hljs-comment">// New</span>
}
</code></pre>
<h3 id="heading-controlling-the-paddle">Controlling the paddle</h3>
<p>Now that we have added the drawing logic, we can start with the fun part — giving the user control over the paddle! We should hold the left and right arrow keys down to move the paddle. To achieve this, we need the following:</p>
<ul>
<li>Variables to store the state of the left and right keys.</li>
<li>Event listeners to know when the keys are pressed and released.</li>
</ul>
<p>We can add <code>leftKey</code> and <code>rightKey</code> to our <em>game object</em> with the default value of <code>false</code> since the buttons will not be pressed at the beginning of the game:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> game = {  
  <span class="hljs-attr">speed</span>: <span class="hljs-number">8</span>,  
  <span class="hljs-attr">requestId</span>: <span class="hljs-literal">null</span>,  
  <span class="hljs-attr">leftKey</span>: <span class="hljs-literal">false</span>,  
  <span class="hljs-attr">rightKey</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>Next, we add event listeners for the <code>keydown</code> and <code>keyup</code> events. These will be listening for key presses and releases:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'keydown'</span>, keyDownHandler);  
<span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'keyup'</span>, keyUpHandler);
</code></pre>
<p>When you press a key on your keyboard, the <code>keydown</code> event fires and invokes the <code>keyDownHandler()</code> function. As the key is released, the <code>keyup</code> event fires and invokes the <code>keyUpHandler()</code> function. The following code defines these functions and the keys we use for the left and right movements:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">keyDownHandler</span>(<span class="hljs-params">e</span>) </span>{
  <span class="hljs-keyword">if</span> (e.key === <span class="hljs-string">'ArrowRight'</span>) {
    game.rightKey = <span class="hljs-literal">true</span>;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (e.key === <span class="hljs-string">'ArrowLeft'</span>) {
    game.leftKey = <span class="hljs-literal">true</span>;
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">keyUpHandler</span>(<span class="hljs-params">e</span>) </span>{
  <span class="hljs-keyword">if</span> (e.key === <span class="hljs-string">'ArrowRight'</span>) {
    game.rightKey = <span class="hljs-literal">false</span>;
  } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (e.key === <span class="hljs-string">'ArrowLeft'</span>) {
    game.leftKey = <span class="hljs-literal">false</span>;
  }
}
</code></pre>
<p>Both functions take an event as a parameter, represented by the <code>e</code> variable. The <code>key</code> property holds the information about the key that was pressed. Modern browsers use <code>ArrowRight</code> and <code>ArrowLeft</code> for the left/right arrow keys. When we press a key down, the relevant variable is set to <code>true</code>. When the key is released, the variable is changed back to <code>false</code>.</p>
<h3 id="heading-moving-the-paddle">Moving the paddle</h3>
<p>Now that we have set up the variables, events, and functions to update the variables, we can use these pressed variables to update the x position of the paddle to move it on the screen. We can do this in the <code>update()</code> function where we change the <code>x</code> coordinate if the left or right keys are pressed:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span>(<span class="hljs-params"></span>) </span>{
  ball.x += ball.dx;
  ball.y += ball.dy;

  <span class="hljs-keyword">if</span> (game.rightKey) {
    paddle.x += paddle.dx;
    <span class="hljs-keyword">if</span> (paddle.x + paddle.width &gt; canvas.width){
      paddle.x = canvas.width - paddle.width;
    }
  } 
  <span class="hljs-keyword">if</span> (game.leftKey) {
    paddle.x -= paddle.dx;
    <span class="hljs-keyword">if</span> (paddle.x &lt; <span class="hljs-number">0</span>){
      paddle.x = <span class="hljs-number">0</span>;
    }
  }
</code></pre>
<p>If the keys are pressed, we update the <code>paddle.x</code> variable by adding or subtracting the <code>paddle.dx</code>. We also need to check if we have reached the walls, and in those cases, we keep the <code>x</code> variable at these minimum and maximum values.</p>
<h3 id="heading-bounce-ball-off-the-paddle">Bounce ball off the paddle</h3>
<p>Lastly, we have to add collision detection for the paddle. When the ball hits the paddle, it should bounce off it back into the playing area.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528683506/RuQxuKhGn.png" alt="The ball inside the paddle" /></p>
<p>To do this, we can check whether the ball has reached the paddle and is between the left and right edges of the paddle. Since we measure the ball from the top-left corner, we need to add 2*radius when we check whether the ball has reached the paddle or not. This is why we must update the values for the coordinates before checking for collisions. Likewise, when we check if the ball is hitting the paddle on the horizontal plane, we must remember the radius in our calculations:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">detectCollision</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> hitTop = <span class="hljs-function">() =&gt;</span> ball.y &lt; <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> hitLeftWall = <span class="hljs-function">() =&gt;</span> ball.x &lt; <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> hitRightWall = <span class="hljs-function">() =&gt;</span> ball.x + <span class="hljs-number">2</span> * ball.radius &gt; canvas.width;
  <span class="hljs-keyword">const</span> hitPaddle = <span class="hljs-function">() =&gt;</span>
    ball.y + <span class="hljs-number">2</span> * ball.radius &gt; canvas.height - paddle.height &amp;&amp;
    ball.y + ball.radius &lt; canvas.height &amp;&amp; 
    ball.x + ball.radius &gt; paddle.x &amp;&amp;
    ball.x + ball.radius &lt; paddle.x + paddle.width;

  <span class="hljs-keyword">if</span> (hitLeftWall()) {
    ball.dx = -ball.dx;
    ball.x = <span class="hljs-number">0</span>;
  }        
  <span class="hljs-keyword">if</span> (hitRightWall()) {
    ball.dx = -ball.dx;
    ball.x = canvas.width - <span class="hljs-number">2</span> * ball.radius;
  }
  <span class="hljs-keyword">if</span> (hitTop()) {
    ball.dy = -ball.dy;
    ball.y = <span class="hljs-number">0</span>;
  }
  <span class="hljs-keyword">if</span> (hitPaddle()) {
    ball.dy = -ball.dy;
    ball.y = canvas.height - paddle.height - <span class="hljs-number">2</span> * ball.radius;
  }
}
</code></pre>
<p>Running the code, we can control the paddle and use it to bounce the ball.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528685421/sGsKxWWAz.png" alt="Design of ball bouncing off paddle." /></p>
<hr />
<h2 id="heading-bricks">Bricks</h2>
<p>Bouncing the ball off the walls is fun and all but gets boring fast. What we need is something to destroy! And this is what we are doing in this lesson by creating a field of bricks.</p>
<h3 id="heading-defining-the-bricks">Defining the bricks</h3>
<p>First, we need to set up some variables to define the bricks. Add the following lines to your code to create a brick configuration object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> brick = {  
  <span class="hljs-attr">rows</span>: <span class="hljs-number">5</span>,  
  <span class="hljs-attr">cols</span>: <span class="hljs-number">10</span>,  
  <span class="hljs-keyword">get</span> <span class="hljs-title">width</span>() {  
    <span class="hljs-keyword">return</span> canvas.width / <span class="hljs-built_in">this</span>.cols;  
  },  
  <span class="hljs-attr">height</span>: <span class="hljs-number">30</span>  
}
</code></pre>
<p>Here we define the number of rows and columns of bricks and their height. We use a getter to compute the width of the bricks depending on the number of columns.</p>
<h3 id="heading-brick-field">Brick field</h3>
<p>We hold all our bricks in an array called <code>brickField.</code> It contains all the brick objects with position and size to paint each brick on the screen. We initialize the array with row and column loops. Then we add a brick to the <code>brickField</code> array in each iteration with the following properties:</p>
<ul>
<li>x position</li>
<li>y position</li>
<li>height</li>
<li>width</li>
<li>color</li>
<li>points</li>
<li>hitsLeft</li>
</ul>
<p>We calculate the <code>x</code> and <code>y</code> coordinates from the row and column together with the width and height of bricks. The <code>topMargin</code> leaves some space at the top of the canvas that we will be using later.</p>
<p>Here we set the <code>color</code> by the row, but we could be even more creative when creating new levels. The <code>points</code> are also dependent on the row, giving more points for each row of bricks we get through. Bricks can withstand hits and sometimes require more than one hit before being destroyed. Here we set the bricks on the top row to disappear after two hits with the <code>hitsLeft</code> property:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initBricks</span>(<span class="hljs-params"></span>) </span>{
  brickField = [];
  <span class="hljs-keyword">const</span> topMargin = <span class="hljs-number">30</span>;
  <span class="hljs-keyword">const</span> colors = [<span class="hljs-string">'red'</span>, <span class="hljs-string">'orange'</span>, <span class="hljs-string">'yellow'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'green'</span>];

  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> row = <span class="hljs-number">0</span>; row &lt; brick.rows; row++) {
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> col = <span class="hljs-number">0</span>; col &lt; brick.cols; col++) {
      brickField.push({
        <span class="hljs-attr">x</span>: col * brick.width,
        <span class="hljs-attr">y</span>: row * brick.height + topMargin,
        <span class="hljs-attr">height</span>: brick.height,
        <span class="hljs-attr">width</span>: brick.width,
        <span class="hljs-attr">color</span>: colors[row],
        <span class="hljs-attr">points</span>: (<span class="hljs-number">5</span> - row) * <span class="hljs-number">2</span>,
        <span class="hljs-attr">hitsLeft</span>: row === <span class="hljs-number">0</span> ? <span class="hljs-number">2</span> : <span class="hljs-number">1</span>
      });
    }
  }
}
</code></pre>
<p>The code above will loop through the rows and columns and create the new brick objects that we add into the array of bricks.</p>
<h3 id="heading-drawing-the-bricks">Drawing the bricks</h3>
<p>Now let’s create a function to draw the bricks. First, we check if <code>hitsLeft</code> is more than zero, which means the brick is still visible. If it has hits left, it’s drawn on the screen. We then set the <code>color</code> from the brick properties before using <code>fillRectangle()</code> and <code>strokeRectangle()</code> to paint the bricks:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawBricks</span>(<span class="hljs-params"></span>) </span>{
  brickField.forEach(<span class="hljs-function">(<span class="hljs-params">brick</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (brick.hitsLeft) {
      ctx.fillStyle = brick.color;
      ctx.fillRect(brick.x, brick.y, brick.width, brick.height);
      ctx.strokeRect(brick.x, brick.y, brick.width, brick.height);
    }
  });
}
</code></pre>
<p>Then we need to add a call to <code>drawBricks()</code> in the <code>paint()</code> function to draw the field of bricks in every frame.</p>
<h2 id="heading-brick-collisions">Brick collisions</h2>
<p>Now that we have made the bricks appear on the screen, it’s time to make them disappear when we hit them with the ball.</p>
<p>When we check for collisions between the ball and bricks, we first check if the ball is inside the brick. Then we check from which direction the ball hit the brick to know what direction change to make.</p>
<p>For the ball to be inside the brick, all four of the following statements need to be true:</p>
<ul>
<li>The x position of the ball is greater than the x position of the brick.</li>
<li>The x position of the ball is less than the x position of the brick plus its width.</li>
<li>The y position of the ball is greater than the y position of the brick.</li>
<li>The y position of the ball is less than the y position of the brick plus its height.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528687434/fd8CaJlx8.png" alt="Ball and brick coordinates used in calculations" /></p>
<p>To start, we want to create a collision detection function that loops through all the bricks, comparing the ball with its position. For better readability of the code, we define a function expression <code>isBallInsideBrick</code> with all our calculations:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">detectBrickCollision</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> isBallInsideBrick = <span class="hljs-function">(<span class="hljs-params">brick</span>) =&gt;</span> 
    ball.x + <span class="hljs-number">2</span> * ball.radius &gt; brick.x &amp;&amp;
    ball.x &lt; brick.x + brick.width &amp;&amp; 
    ball.y + <span class="hljs-number">2</span> * ball.radius &gt; brick.y &amp;&amp; 
    ball.y &lt; brick.y + brick.height;

  brickField.forEach(<span class="hljs-function">(<span class="hljs-params">brick</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (brick.hitsLeft &amp;&amp; isBallInsideBrick(brick)) {
      brick.hitsLeft--;
      <span class="hljs-keyword">if</span> (brick.hitsLeft === <span class="hljs-number">1</span>) {
        brick.color = <span class="hljs-string">'darkgray'</span>;
      }
    }
  });
}
</code></pre>
<p>As we saw earlier, when we drew the bricks, we know if the brick is visible or not with the <code>hitsLeft</code> property. We decrease it when the brick gets hit. We also set the color to grey for the top row that requires two hits before being destroyed.</p>
<p>We have the bricks disappearing now when we hit them, but it would also be nice if the ball changes direction as we do so.</p>
<h2 id="heading-collision-direction">Collision direction</h2>
<p>To bounce the ball in the right direction after a collision, we need to know what side of the brick the ball hit.</p>
<p>We can calculate if the ball was coming from the left or right by removing the change <code>ball.dx</code> and find out if the ball was on the left or right side of the brick before impact. If this is true, we negate the <code>dx</code> to make the ball bounce back from where it was coming:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Check if ball is inside from left side</span>
ball.x + <span class="hljs-number">2</span> * ball.radius            &gt; brick x
<span class="hljs-comment">// Decrease by dx and check if position was on left side of brick x</span>
ball.x + <span class="hljs-number">2</span> * ball.radius - ball.dx &lt;= brick.x;

<span class="hljs-comment">// Similarly for right side</span>
ball.x            &lt; brick.x + brick.width
ball.x - ball.dx &gt;= brick.x + brick.width
</code></pre>
<p>If neither of these cases is true, then we know that the ball hit the brick on the top or bottom, and in that case, we negate <code>ball.dy</code> to make the ball bounce back.</p>
<p>Sometimes we hit multiple bricks in the same frame. If we, for example, hit two bricks from the bottom and change the direction twice, the ball will be traveling right through the bricks. For this reason, we need to have a variable <code>directionChanged</code> that keeps track so that we only change direction once per frame:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">detectBrickCollision</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">let</span> directionChanged = <span class="hljs-literal">false</span>;
  <span class="hljs-keyword">const</span> isBallInsideBrick = <span class="hljs-function">(<span class="hljs-params">brick</span>) =&gt;</span>
    ball.x + <span class="hljs-number">2</span> * ball.radius &gt; brick.x &amp;&amp;
    ball.x &lt; brick.x + brick.width &amp;&amp; 
    ball.y + <span class="hljs-number">2</span> * ball.radius &gt; brick.y &amp;&amp; 
    ball.y &lt; brick.y + brick.height;

  brickField.forEach(<span class="hljs-function">(<span class="hljs-params">brick</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (brick.hitsLeft &amp;&amp; isBallInsideBrick(brick)) {
      brick.hitsLeft--;
      <span class="hljs-keyword">if</span> (brick.hitsLeft === <span class="hljs-number">1</span>) {
        brick.color = <span class="hljs-string">'darkgray'</span>;
      }

      <span class="hljs-keyword">if</span> (!directionChanged) {
        directionChanged = <span class="hljs-literal">true</span>;
        detectCollisionDirection(brick);
      }
    }
  });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">detectCollisionDirection</span>(<span class="hljs-params">brick</span>) </span>{
  <span class="hljs-keyword">const</span> hitFromLeft = <span class="hljs-function">() =&gt;</span> ball.x + <span class="hljs-number">2</span> * ball.radius - ball.dx &lt;= brick.x;
  <span class="hljs-keyword">const</span> hitFromRight = <span class="hljs-function">() =&gt;</span> ball.x - ball.dx &gt;= brick.x + brick.width;

  <span class="hljs-keyword">if</span> (hitFromLeft() || hitFromRight()) {
    ball.dx = -ball.dx;
  } <span class="hljs-keyword">else</span> { <span class="hljs-comment">// Hit from above or below</span>
    ball.dy = -ball.dy;
  }
}
</code></pre>
<p>The last thing to do is to add a call to the <code>detectBrickCollision()</code> function to our <code>animate()</code> function, just below the <code>collisionDetection()</code> call. With these changes, we can break bricks. And when we hit one, the ball bounces as expected.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528690697/0997KZF-I.gif" alt="The ball hits bricks and changes direction" /></p>
<hr />
<h2 id="heading-score-levels-and-lives">Score, levels, and lives</h2>
<p>Now that we can destroy the bricks, the game is ready to award points for hitting them and keep a count of the total score. And when all the bricks get obliterated, the game should continue to the next level. And wouldn’t it be nice to have more than one life to get another chance when we can’t catch the ball?</p>
<h3 id="heading-game-variables">Game variables</h3>
<p>To keep track of all of these new states in the game, we add them to the game object. Since these values need to reset at the start of each game, we add them to the <code>resetGame()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetGame</span>(<span class="hljs-params"></span>) </span>{  
  game.speed = <span class="hljs-number">8</span>;  
  game.score = <span class="hljs-number">0</span>;  
  game.level = <span class="hljs-number">1</span>;  
  game.lives = <span class="hljs-number">3</span>;
}
</code></pre>
<h3 id="heading-display-text">Display text</h3>
<p>Drawing text on a canvas is similar to drawing a shape. First, we set the size and type of the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/font"><code>font</code></a>. Next, we use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle"><code>fillStyle</code></a> to set the color of the font and finally <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillText"><code>fillText()</code></a> to tell what text and where we want to display on the canvas.</p>
<p>The next step is to show all these new variables on the screen so that the player has current information available at all times. Let’s add a <code>drawScore()</code> function that creates and updates the display with the <code>level</code> and <code>score</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawScore</span>(<span class="hljs-params"></span>) </span>{
  ctx.font = <span class="hljs-string">'16px Arial'</span>;
  ctx. fillStyle = <span class="hljs-string">'white'</span>;
  <span class="hljs-keyword">const</span> { level, score } = game;
  ctx.fillText(<span class="hljs-string">`Level: <span class="hljs-subst">${level}</span>`</span>, <span class="hljs-number">5</span>, <span class="hljs-number">20</span>);
  ctx.fillText(<span class="hljs-string">`Score: <span class="hljs-subst">${score}</span>`</span>, canvas.width / <span class="hljs-number">2</span> - <span class="hljs-number">50</span>, <span class="hljs-number">20</span>);
}
</code></pre>
<p>The code above prints the current level and the number of points at the top of the screen.</p>
<h3 id="heading-lives-left">Lives left</h3>
<p>We could also write the lives with text, but to make it fancier, we can show a tiny paddle for each life that we have remaining. We can do this by using the same image as for the paddle and drawing it for each life we have left:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">drawLives</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span> (game.lives &gt; <span class="hljs-number">2</span>) ctx.drawImage(images.paddle, canvas.width - <span class="hljs-number">150</span>, <span class="hljs-number">9</span>, <span class="hljs-number">40</span>, <span class="hljs-number">13</span>);
  <span class="hljs-keyword">if</span> (game.lives &gt; <span class="hljs-number">1</span>) ctx.drawImage(images.paddle, canvas.width - <span class="hljs-number">100</span>, <span class="hljs-number">9</span>, <span class="hljs-number">40</span>, <span class="hljs-number">13</span>);
  <span class="hljs-keyword">if</span> (game.lives &gt; <span class="hljs-number">0</span>) ctx.drawImage(images.paddle, canvas.width - <span class="hljs-number">50</span>, <span class="hljs-number">9</span>, <span class="hljs-number">40</span>, <span class="hljs-number">13</span>);
}
</code></pre>
<p>Now, a small paddle shows up on the right top of the screen for each of our lives. To use the functions we created for the game information, we add calls to them in the <code>draw()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">draw</span>(<span class="hljs-params"></span>) </span>{
  ctx.drawImage(images.background, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
  ctx.drawImage(images.ball, ball.x, ball.y, <span class="hljs-number">2</span> * ball.radius, <span class="hljs-number">2</span> * ball.radius);
  ctx.drawImage(images.paddle, paddle.x, paddle.y, paddle.width, paddle.height);
  drawBricks();
  drawScore(); <span class="hljs-comment">// New</span>
  drawLives(); <span class="hljs-comment">// New</span>
}
</code></pre>
<h2 id="heading-updating-values">Updating values</h2>
<p>Now that we display all of our variables on the screen, we need to update them to add to the score and levels while at the same time keeping track of the lives we lose.</p>
<h3 id="heading-score">Score</h3>
<p>Remember when we added what each brick is worth in points in the last chapter? The time has come to add those to our total score each time we destroy one.</p>
<p>To increase the score, we add the points that the brick is worth every time we hit one in <code>detectBrickCollisions()</code>:</p>
<pre><code class="lang-js">game.score += brick.points;
</code></pre>
<p>Now, that was easy! The next value is a bit more complicated.</p>
<p>If you want to add a high score list, read my article:</p>
<ul>
<li><a target="_blank" href="https://michael-karen.medium.com/how-to-save-high-scores-in-local-storage-7860baca9d68">How to Save High Scores in Local Storage</a></li>
</ul>
<h3 id="heading-levels">Levels</h3>
<p>When there are no more bricks, we proceed to the next level. There are no more bricks left when all the bricks have <code>hitsLeft</code> equal to zero. How can we check all elements in an array for a specific value of a property?</p>
<p>The array method best suited for this is <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every">every()</a>. It can check whether all elements in the array pass the tests we provide. Check for when there are no bricks left, and in that case, go to the next level:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isLevelCompleted</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> levelComplete = brickField.every(<span class="hljs-function">(<span class="hljs-params">b</span>) =&gt;</span> b.hitsLeft === <span class="hljs-number">0</span>);

  <span class="hljs-keyword">if</span> (levelComplete) {
    initNextLevel();
    resetBall();
    resetPaddle();
    initBricks();
    game.timeoutId = <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> animate(), <span class="hljs-number">3000</span>);

    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">initNextLevel</span>(<span class="hljs-params"></span>) </span>{
  game.level++;
  game.speed++;
  ctx.font = <span class="hljs-string">'40px Arial'</span>;
  ctx.fillStyle = <span class="hljs-string">'yellow'</span>;
  ctx.fillText(<span class="hljs-string">`LEVEL <span class="hljs-subst">${game.level}</span>!`</span>, canvas.width / <span class="hljs-number">2</span> - <span class="hljs-number">80</span>, canvas.height / <span class="hljs-number">2</span>);
}
</code></pre>
<p>We add a call to <code>isLevelCompleted()</code> in the <code>animate()</code> function that exits before requesting a new frame if the level has been completed:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (isLevelCompleted() || isGameOver()) <span class="hljs-keyword">return</span>;
</code></pre>
<p>When we have no more bricks left, we increase the <code>game.level</code>. When we get better at Breakout, the starting speed gets too easy. And too easy means boring. We increase the difficulty by increasing the <code>game.speed</code> when we advance levels.</p>
<p>Then we reset the playing field, with the result that the ball and paddle move a bit faster on the new level. Remember that we stop the animations if the level completes? The reason is that we want to show a screen for a few seconds before continuing the game. We use <code>setTimeout()</code> and set the number of milliseconds to pause before continuing the game.</p>
<p>Similarly, as we did with <code>cancelAnimationFrame()</code>, we add <code>clearTimeout(game.timeoutId)</code> to the beginning of the <code>play()</code> function to make it possible to start a new game between levels without another animation loop starting up.</p>
<h3 id="heading-lives">Lives</h3>
<p>Lastly, we alter the <code>gameOver()</code> function to check whether we have lives left before going to the game over. We decrease <code>lives</code>, and when we reach zero, the game is over. Otherwise, we get a new ball by calling <code>resetBall()</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isGameOver</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> isBallLost = <span class="hljs-function">() =&gt;</span> ball.y - ball.radius &gt; canvas.height;

  <span class="hljs-keyword">if</span> (isBallLost()) {
    game.lives -= <span class="hljs-number">1</span>;
    <span class="hljs-keyword">if</span> (game.lives === <span class="hljs-number">0</span>) {
      gameOver();
      <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
    resetBall();
    resetPaddle();
  }
  <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1642528693003/7j-4miCvL.png" alt="game information" /></p>
<h2 id="heading-sound">Sound</h2>
<p>No game is complete until we at least add some sound effects. There are many free websites to find sound samples to use. I selected some from <a target="_blank" href="https://freesound.org/">freesound.org</a>.</p>
<p>We are going to add sound effects for:</p>
<ul>
<li>The ball hitting the paddle</li>
<li>The ball hitting a brick</li>
<li>Ball launch</li>
<li>Game over</li>
<li>Level completed</li>
</ul>
<p>The <code>Audio()</code> constructor creates and returns a new <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement"><code>HTMLAudioElement</code></a> which can be used to play the audio:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> audioElement = <span class="hljs-keyword">new</span> Audio(url);  
audioElement.play();
</code></pre>
<p>An optional <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/DOMString"><code>DOMString</code></a> contains the URL of the audio file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sounds = {
  <span class="hljs-attr">ballLost</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/ball-lost.mp3'</span>),
  <span class="hljs-attr">breakout</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/breakout.mp3'</span>),
  <span class="hljs-attr">brick</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/brick.mp3'</span>),
  <span class="hljs-attr">gameOver</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/game-over.mp3'</span>),
  <span class="hljs-attr">levelCompleted</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/level-completed.mp3'</span>),
  <span class="hljs-attr">music</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/music.mp3'</span>),
  <span class="hljs-attr">paddle</span>: <span class="hljs-keyword">new</span> Audio(<span class="hljs-string">'./sounds/paddle.mp3'</span>)
}
</code></pre>
<p>We add sounds similar to how we created images, except we can add the URL in the constructor.</p>
<p>Now we can play these elements when finding where in the code they belong. For example, we add the <code>gameOver</code> sound to the <code>gameOver()</code> function. Sometimes we hit multiple bricks. To start the sound over when we hit the next brick, we set <code>currentTime</code> to zero:</p>
<pre><code class="lang-js">sounds.brick.currentTime = <span class="hljs-number">0</span>;  
sounds.brick.play();
</code></pre>
<p>You might have noticed that we added <code>music</code> in the sounds object. The game music starts when we press start and ends at game over. Since we don’t want the music to end we set it to repeat:</p>
<pre><code class="lang-js">sounds.music.loop = <span class="hljs-literal">true</span>;
</code></pre>
<p>We can set the volume of the audio between 0 and 1. To be sure the music is not too loud at the start we can set it a bit lower than max:</p>
<pre><code class="lang-js">sounds.music.volume = <span class="hljs-number">0.5</span>;
</code></pre>
<p>We could also add some keyboard triggers into the <code>keyDownHandler</code> to toggle the music on and off and to control the volume. With all the sounds in place, we truly have something starting to resemble a complete game.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Today we learned how to create a complete game with the HTML Canvas and JavaScript. I hope you enjoyed the article and learned something new.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://github.com/melcor76/js-breakout">GitHub repository with js-breakout</a>.</li>
<li><a target="_blank" href="https://blog.michaelkaren.dev/how-to-get-started-with-canvas-animations-in-javascript">How to Get Started with Canvas Animations in JavaScript</a></li>
<li><a target="_blank" href="https://blog.michaelkaren.dev/how-to-save-high-scores-in-local-storage-7860baca9d68">How to Save High Scores in Local Storage</a></li>
<li><a target="_blank" href="https://blog.michaelkaren.dev/learning-modern-javascript-with-tetris-92d532bcd057">Learning Modern JavaScript with Tetris</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How To Get Started With Canvas Animations In JavaScript]]></title><description><![CDATA[I love playing games. And I love coding too. So, one day, I got thinking, why not use those coding skills to make a game? But it sounds hard. How would one even get started?
With baby steps. 👣
In this article, we learn to draw and animate objects us...]]></description><link>https://blog.michaelkaren.dev/how-to-get-started-with-canvas-animations-in-javascript</link><guid isPermaLink="true">https://blog.michaelkaren.dev/how-to-get-started-with-canvas-animations-in-javascript</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[HTML5]]></category><category><![CDATA[HTML Canvas]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 24 May 2021 07:51:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1621627374206/keFQGtJas.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I love playing games. And I love coding too. So, one day, I got thinking, why not use those coding skills to make a game? But it sounds hard. How would one even get started?</p>
<p>With baby steps. 👣</p>
<p>In this article, we learn to draw and animate objects using HTML5 Canvas and JavaScript before we optimize for performance.</p>
<blockquote>
<p>“Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren</p>
</blockquote>
<p>Banner photo by <a target="_blank" href="https://unsplash.com/@justinlim">Justin Lim</a> on Unsplash </p>
<h2 id="introduction">Introduction</h2>
<p>Apple introduced canvas in 2004 to power applications and the Safari browser. A few years later it was standardized by the <a target="_blank" href="https://en.wikipedia.org/wiki/WHATWG">WHATWG</a>. It comes with finer-grained control over rendering but with the cost of having to manage every detail manually. In other words, it can handle many objects, but we need to code everything in detail.</p>
<p>The canvas has a <strong>2D drawing context</strong> used for drawing shapes, text, images, and other objects. First, we choose the color and brush, and then we paint. We can change the brush and color before every new drawing, or we can continue with what we have.</p>
<p>Canvas uses <strong>immediate rendering</strong>: When we draw, it immediately renders on the screen. But, it is a fire-and-forget system. After we paint something, the canvas forgets about the object and only knows it as pixels. So there is no object that we can move. Instead, we have to draw it again.</p>
<p>Doing animations on Canvas is like making a stop-motion movie. In every frame need to move the objects a little bit to animate them.</p>
<h2 id="canvas-element">Canvas element</h2>
<p>The HTML <code>&lt;canvas&gt;</code> element provides a blank container on which we can draw graphics. We can draw shapes and lines on it via the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">Canvas API</a>, which allows for drawing graphics via JavaScript.</p>
<p>A canvas is a rectangular area on an HTML page that by default has no border or content. The default size of the canvas is 300 pixels × 150 pixels (width × height). However, custom sizes can be defined using the HTML <code>height</code> and <code>width</code> property:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"canvas"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"600"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"300"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
</code></pre>
<p>Specify the <code>id</code> attribute to be able to refer to it from a script. To add a border, use the <code>style</code> attribute or use CSS with the <code>class</code> attribute:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"canvas"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"600"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"300"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"border: 2px solid"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"animate()"</span>&gt;</span>Play<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
</code></pre>
<p>Now that we added the border we see the size of our empty canvas on the screen.
We also have a button with an <code>onclick</code> event to run our <code>animate()</code> function when we click it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621357533321/PF3r7aTph.png" alt="empty canvas" /></p>
<p>We can place our JavaScript code in <code>&lt;script&gt;</code> elements that we place into the document <code>&lt;body&gt;</code> after the <code>&lt;canvas&gt;</code> element:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"canvas.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>We get a reference to the HTML <code>&lt;canvas&gt;</code> element in the DOM (Document Object Model) with the <code>getElementById()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'canvas'</span>);
</code></pre>
<p>Now we have the canvas element available but cannot draw directly on it. Instead, the canvas has rendering contexts that we can use.</p>
<h2 id="canvas-context">Canvas context</h2>
<p>The canvas has a <strong>2D drawing context</strong> used for drawing shapes, text, images, and other objects. First, we choose the color and brush, and then we paint. We can change the brush and color before every new drawing, or we can continue with what we have.</p>
<p>The <code>HTMLCanvasElement.getContext()</code> method returns a drawing context, where we render the graphics. By supplying <code>'2d'</code> as the argument we get the canvas 2D rendering context:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ctx = canvas.getContext(<span class="hljs-string">'2d'</span>);
</code></pre>
<blockquote>
<p>There are other available contexts, like <code>webgl</code> for a three-dimensional rendering context, that is outside the scope of this article.</p>
</blockquote>
<p>The <code>CanvasRenderingContext2D</code> has a variety of methods for drawing lines and shapes on the canvas. To set the color of the line we use <code>strokeStyle</code> and to set the thickness we use <code>lineWidth</code>:</p>
<pre><code class="lang-js">ctx.strokeStyle = <span class="hljs-string">'black'</span>;
ctx.lineWidth = <span class="hljs-number">5</span>;
</code></pre>
<p>Now, we are ready to draw our first line on the canvas. But, before we do that we need to understand how we tell the canvas where to draw. The HTML canvas is a two-dimensional grid. The upper-left corner of the canvas has the coordinates (0, 0).</p>
<pre><code>   <span class="hljs-string">X</span> <span class="hljs-string">→</span>
<span class="hljs-string">Y</span> [<span class="hljs-string">(0</span>,<span class="hljs-number">0</span><span class="hljs-string">)</span>, <span class="hljs-string">(1</span>,<span class="hljs-number">0</span><span class="hljs-string">)</span>, <span class="hljs-string">(2</span>,<span class="hljs-number">0</span><span class="hljs-string">)</span>, <span class="hljs-string">(3</span>,<span class="hljs-number">0</span><span class="hljs-string">)</span>, <span class="hljs-string">(4</span>,<span class="hljs-number">0</span><span class="hljs-string">)</span>, <span class="hljs-string">(5</span>,<span class="hljs-number">0</span><span class="hljs-string">)</span>]
<span class="hljs-string">↓</span> [<span class="hljs-string">(0</span>,<span class="hljs-number">1</span><span class="hljs-string">)</span>, <span class="hljs-string">(1</span>,<span class="hljs-number">1</span><span class="hljs-string">)</span>, <span class="hljs-string">(2</span>,<span class="hljs-number">1</span><span class="hljs-string">)</span>, <span class="hljs-string">(3</span>,<span class="hljs-number">1</span><span class="hljs-string">)</span>, <span class="hljs-string">(4</span>,<span class="hljs-number">1</span><span class="hljs-string">)</span>, <span class="hljs-string">(5</span>,<span class="hljs-number">1</span><span class="hljs-string">)</span>]
  [<span class="hljs-string">(0</span>,<span class="hljs-number">2</span><span class="hljs-string">)</span>, <span class="hljs-string">(1</span>,<span class="hljs-number">2</span><span class="hljs-string">)</span>, <span class="hljs-string">(2</span>,<span class="hljs-number">2</span><span class="hljs-string">)</span>, <span class="hljs-string">(3</span>,<span class="hljs-number">2</span><span class="hljs-string">)</span>, <span class="hljs-string">(4</span>,<span class="hljs-number">2</span><span class="hljs-string">)</span>, <span class="hljs-string">(5</span>,<span class="hljs-number">2</span><span class="hljs-string">)</span>]
</code></pre><p>So, when we say we want to <code>moveTo(4, 1)</code> on the canvas it means we start at the upper-left corner (0,0) and move four columns to the right and one row down.</p>
<h2 id="drawing">Drawing 🔵</h2>
<p>Once we have a canvas context, we can draw on it using the canvas context API. The method <code>lineTo()</code> adds a straight line to the current sub-path by connecting its last point to the specified (x, y) coordinates. Like other methods that modify the current path, this method does not directly render anything. To draw the path onto a canvas, you can use the <code>fill()</code> or <code>stroke()</code> methods.</p>
<pre><code class="lang-js">ctx.beginPath();      <span class="hljs-comment">// Start a new path</span>
ctx.moveTo(<span class="hljs-number">100</span>, <span class="hljs-number">50</span>);  <span class="hljs-comment">// Move the pen to x=100, y=50.</span>
ctx.lineTo(<span class="hljs-number">300</span>, <span class="hljs-number">150</span>); <span class="hljs-comment">// Draw a line to x=300, y=150.</span>
ctx.stroke();         <span class="hljs-comment">// Render the path</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621283728432/OFb_xUlgq.png" alt="canvas with line" /></p>
<p>We can use <code>fillRect()</code> to draw a filled rectangle. Setting the <code>fillStyle</code> determines the color used when filling drawn shapes:</p>
<pre><code class="lang-js">ctx.fillStyle = <span class="hljs-string">'blue'</span>;
ctx.fillRect(<span class="hljs-number">100</span>, <span class="hljs-number">100</span>, <span class="hljs-number">30</span>, <span class="hljs-number">30</span>); <span class="hljs-comment">// (x, y, width, height);</span>
</code></pre>
<p>This draws a filled blue rectangle:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621362040705/O88HvsiJZ.png" alt="image.png" /></p>
<h2 id="animation">Animation 🎥</h2>
<p>Now, let's see if we can get our block to move on the canvas. We start by setting the <code>size</code> of the square to 30. Then, we can move the <code>x</code> value to the right with steps of <code>size</code> and draw the object over and over again. We move the block to the right until it reaches the canvas end:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> size = <span class="hljs-number">30</span>;
ctx.fillStyle = <span class="hljs-string">'blue'</span>;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt; canvas.width; x += size) {
  ctx.fillRect(x, <span class="hljs-number">50</span>, size, size);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621369192655/D4cTMqANv.png" alt="animate blue square" /></p>
<p>OK, we were able to draw the square as we wanted. But we have two issues:</p>
<ol>
<li>We are not cleaning up after ourselves.</li>
<li>It's too fast to see the animation.</li>
</ol>
<p>We need to clear away the old block. What we can do is erase the pixels in a rectangular area with <code>clearRect()</code>. By using the width and height of the canvas, we can clean it between paints.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt; canvas.width; x += size) {
  ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height); <span class="hljs-comment">// Clean up</span>
  ctx.fillRect(x, <span class="hljs-number">50</span>, size, size);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621369427867/HnD87zfY3.png" alt="clear rect" /></p>
<p>Great! We fixed the first problem. Now let's try to slow down the painting so we can see the animation.</p>
<p>You might be familiar with <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval"><code>setInterval(function, delay)</code></a>. It starts repeatedly executing the specified <code>function</code> every <code>delay</code> milliseconds. I set the interval to 200 ms, which means the code runs five times a second.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>;
<span class="hljs-keyword">const</span> id = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
  ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);      
  ctx.fillRect(x, <span class="hljs-number">50</span>, size, size);
  x += size;

  <span class="hljs-keyword">if</span> (x &gt;= canvas.width) {
    <span class="hljs-built_in">clearInterval</span>(id);
  }
}, <span class="hljs-number">200</span>);
</code></pre>
<p>To stop a timer created by <code>setInterval()</code>, we need to call <code>clearInterval()</code> and give it the identifier for the interval to cancel. The id to use is the one that is returned by <code>setInterval()</code>, and this is why we need to store it.</p>
<p>We can now see that if we press the button, we get a square that moves from left to right. But, if we press the play button several times, we can see that there is a problem animating multiple squares at the same time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621371364387/VMLssOIRg.gif" alt="animate many blocks" /></p>
<p>Every square gets its interval that clears the board and paints the square.
It's all over the place! Let's see how we can fix this.</p>
<h2 id="multiple-objects">Multiple objects</h2>
<p>To be able to run the animations for several blocks, we need to rethink the logic. As of now, each block gets its animation method with <code>setInterval()</code>. Instead, we should manage the moving objects before sending them to be drawn, all at once.</p>
<p>We can add a variable <code>started</code> to only start <code>setInterval()</code> on the first button click. Every time we press the play button, we add a new value 0 to a <code>squares</code> array. This is enough for this simple animation but for something more complex we could create a <code>Square</code> object with the coordinates and eventual other properties like color.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> squares = [];
<span class="hljs-keyword">let</span> started = <span class="hljs-literal">false</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Add 0 as x value for object to start from the left.</span>
  squares.push(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">if</span> (!started) {
      started = <span class="hljs-literal">true</span>;
      <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
        tick();
      }, <span class="hljs-number">200</span>)
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">tick</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Clear canvas</span>
  ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);

  <span class="hljs-comment">// Paint objects</span>
  squares.forEach(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> ctx.fillRect(x, <span class="hljs-number">50</span>, size, size));

  squares = squares.map(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x += size) <span class="hljs-comment">// move x to right</span>
      .filter(<span class="hljs-function"><span class="hljs-params">x</span> =&gt;</span> x &lt; canvas.width);  <span class="hljs-comment">// remove when at end</span>
}
</code></pre>
<p>The <code>tick()</code> function clears the screen and paints all the objects in the array every 200ms. And by having only one interval, we avoid the flicker we had before. And now we get better animations:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1621808272719/IHOF8JnDW.gif" alt="multiple inteval working.gif" /></p>
<p>What we did here is the first step of making a game loop. This loop is the heart of every game. It's a controlled infinite loop that keeps your game running ;  it's the place where all your little pieces get updated and drawn on the screen.</p>
<h2 id="optimize-animations">🚶Optimize animations 🏃</h2>
<p>Another option for animating is to use <code>requestAnimationFrame()</code>. It tells the browser that you wish to perform an animation and requests the browser to call a function to update an animation before the next repaint. In other words, we tell the browser: "Next time you paint on the screen, also run this function because I want to paint something too."</p>
<p>The way to animate with <code>requestAnimationFrame()</code> is to create a function that paints a frame and then schedules itself to invoke again. With this, we get an asynchronous loop that executes when we draw on the canvas. We invoke the animate method over and over again until we decide to stop. So, now we instead call the <code>animate()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Add 0 as x value for object to start from the left.</span>
  squares.push(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">if</span> (!started) {
      animate();
  }
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params"></span>) </span>{
  tick();
  requestAnimationFrame(animate);  
}
</code></pre>
<p>If we try this out we notice that we can see the animation, which was not the case with <code>setInterval()</code>, even though it's super fast. The number of callbacks is usually 60 times per second.</p>
<p>The <code>requestAnimationFrame()</code> method returns an <code>id</code> that we use for canceling the scheduled animation frame. To cancel a scheduled animation frame, you can use the <code>cancelAnimationFrame(id)</code> method.</p>
<p>To slow down the animation we need a timer to check the <code>elapsed</code> time since the last time we called the <code>tick()</code> function. To help us, the callback function is passed an argument, a <code>DOMHighResTimeStamp</code>, indicating the point in time when <code>requestAnimationFrame()</code> starts to execute callback functions.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> start = <span class="hljs-number">0</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params">timestamp</span>) </span>{    
  <span class="hljs-keyword">const</span> elapsed  = timestamp - start;
  <span class="hljs-keyword">if</span> (elapsed &gt; <span class="hljs-number">200</span>) {
    start = timestamp;
    tick();
  }
  requestAnimationFrame(animate);  
}
</code></pre>
<p>With this, we have the same functionality as we had earlier with <code>setInterval()</code>.</p>
<p>So, in conclusion, why should we use <code>requestAnimationFrame()</code> instead of <code>setInterval()</code>?</p>
<ul>
<li>It enables browser optimizations.</li>
<li>It handles the frame rate.</li>
<li>Animations only run when visible.</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>In this article, we created an <em>HTML5 Canvas</em> and used its <em>2D rendering context</em> and JavaScript to draw on the canvas. We got introduced to some of the methods available in the canvas context and used them to render different shapes.</p>
<p>Finally, we were able to animate multiple objects on the canvas. We learned how to use <code>setInterval()</code> to create an animation loop that manages and draws the objects on the screen.
We also learned how to optimize animations with <code>requestAnimationFrame()</code>.</p>
<p>With this intro to canvas animations, we have taken our first steps into game development. We are ready to start on a real game next:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.michaelkaren.dev/learning-modern-javascript-with-tetris-92d532bcd057">https://blog.michaelkaren.dev/learning-modern-javascript-with-tetris-92d532bcd057</a></div>
]]></content:encoded></item><item><title><![CDATA[7 Useful JavaScript Tricks and Tips]]></title><description><![CDATA[In this article, I gathered some JavaScript tips and tricks that I believe can make you a better JavaScript developer. In no particular order, here are seven (?) JavaScript tricks!
1. Converting to numbers
JavaScript is a loosely typed language, mean...]]></description><link>https://blog.michaelkaren.dev/7-useful-javascript-tricks-and-tips</link><guid isPermaLink="true">https://blog.michaelkaren.dev/7-useful-javascript-tricks-and-tips</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 10 May 2021 05:09:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620576999723/cYN5aRG5_.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, I gathered some JavaScript tips and tricks that I believe can make you a better JavaScript developer. In no particular order, here are seven (?) JavaScript tricks!</p>
<h2 id="1-converting-to-numbers">1. Converting to numbers</h2>
<p>JavaScript is a <strong>loosely typed language</strong>, meaning we don't have to explicitly specify types of variables. JavaScript also freely type-converts values into a type depending on the context of their use.</p>
<p>Converting values to numbers, especially strings to numbers, is a common requirement and many methods can be used. </p>
<h3 id="unary-operator">Unary + operator</h3>
<p>The most concise method for type-converting strings into numbers is the <strong>unary <code>+</code> operator</strong>:</p>
<pre><code class="lang-js">+<span class="hljs-string">"42"</span>  <span class="hljs-comment">// 42</span>
</code></pre>
<blockquote>
<p>A unary operation is an operation with only one operand. This operand comes either before or after the operator.</p>
</blockquote>
<p><em>The unary plus operator</em> precedes its operand and evaluates to its operand but attempts to convert it into a number if it isn't already. Here are a few more examples of how it behaves:</p>
<pre><code class="lang-js">+<span class="hljs-literal">true</span>  <span class="hljs-comment">// 1</span>
+<span class="hljs-literal">false</span> <span class="hljs-comment">// 0</span>
+<span class="hljs-literal">null</span>  <span class="hljs-comment">// 0</span>
</code></pre>
<p>But, what if we want to be more explicit in our code?</p>
<h3 id="number">Number</h3>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">Number</a> is a primitive wrapper object used to represent and manipulate numbers. When used as a function, <code>Number(value)</code> converts a string or other value to the Number type. If the value can't be converted, it returns <code>NaN</code> (Not a Number).</p>
<pre><code class="lang-js"><span class="hljs-built_in">Number</span>(<span class="hljs-string">'42'</span>)   <span class="hljs-comment">// 42</span>
<span class="hljs-built_in">Number</span>(<span class="hljs-string">'1.3'</span>)  <span class="hljs-comment">// 1.3</span>
<span class="hljs-built_in">Number</span>(<span class="hljs-string">'tax'</span>)  <span class="hljs-comment">// NaN</span>
</code></pre>
<h3 id="parseint">parseInt</h3>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt">parseInt()</a> takes a String as a first argument and a base to which that String will be converted to. This method always returns an integer.</p>
<pre><code class="lang-js"><span class="hljs-built_in">parseInt</span>(<span class="hljs-string">'1234'</span>, <span class="hljs-number">10</span>)       <span class="hljs-comment">// 1234</span>
<span class="hljs-built_in">parseInt</span>(<span class="hljs-string">'11 players'</span>, <span class="hljs-number">10</span>) <span class="hljs-comment">// 11</span>
<span class="hljs-built_in">parseInt</span>(<span class="hljs-string">'player 2'</span>, <span class="hljs-number">10</span>)   <span class="hljs-comment">// NaN</span>
<span class="hljs-built_in">parseInt</span>(<span class="hljs-string">'10.81'</span>, <span class="hljs-number">10</span>)      <span class="hljs-comment">// 10</span>
</code></pre>
<p><code>parseInt()</code> tries to get a number from a string that does not only contain a number, but if the string does not start with a number, you’ll get <code>NaN</code>.</p>
<h3 id="parsefloat">parseFloat</h3>
<p>If we want to retain the decimal part and not just the integer part, we can use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat">parseFloat()</a> that takes a String as an argument and returns the Float point number equivalent.</p>
<pre><code class="lang-js"><span class="hljs-built_in">parseFloat</span>(<span class="hljs-string">'10.42'</span>) <span class="hljs-comment">// 10.42</span>
<span class="hljs-built_in">parseFloat</span>(<span class="hljs-string">'10.00'</span>) <span class="hljs-comment">// 10</span>
</code></pre>
<p>There are a few more ways to convert to numbers but these are the more common ones.</p>
<h2 id="2-managing-objects">2. Managing objects</h2>
<p><strong>Destructuring</strong> is a huge part of ES6 and something you're probably going to be using often. It allows us to extract data from objects, and assigning the extracted data into variables:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> rectangle = { <span class="hljs-attr">h</span>: <span class="hljs-number">100</span>, <span class="hljs-attr">w</span>: <span class="hljs-number">200</span> };
<span class="hljs-keyword">const</span> { h, w } = rectangle;
</code></pre>
<p>We can rename the variables if we want to:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">h</span>: height, <span class="hljs-attr">w</span>: width} = rectangle;
<span class="hljs-built_in">console</span>.log(height); <span class="hljs-comment">// 100</span>
</code></pre>
<p>Another handy thing we could do is to destructure the returned object by a function and pick and choose what values we want to use:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getPerson</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">firstName</span>: <span class="hljs-string">'Max'</span>,
    <span class="hljs-attr">lastName</span>: <span class="hljs-string">'Best'</span>,
    <span class="hljs-attr">age</span>: <span class="hljs-number">42</span>
  }
}

<span class="hljs-keyword">const</span> { age } = getPerson();
<span class="hljs-built_in">console</span>.log(age); <span class="hljs-comment">// 42</span>
</code></pre>
<p>So, with destructuring, we can return multiple values from a function by returning an object and choosing the pieces we want to be returned.</p>
<p>Removing a property in an immutable way requires a little trick provided by spread’s counterpart, the <strong>rest</strong> operator, which is written with three dots (...) like spread. However, in this case, we spread the remaining properties into a new object.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">age</span>:_ , ...person } = getPerson();

<span class="hljs-built_in">console</span>.log(person); <span class="hljs-comment">// {firstName: "Max", lastName: "Best"}</span>
</code></pre>
<p>Now the <code>person</code> object holds all properties from the original person object except <code>age</code>.</p>
<h2 id="3-swapping-two-variables">3. Swapping two variables</h2>
<p>Using what we learned in the last trick makes swapping variables as easy as:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> me = <span class="hljs-string">'happy'</span>, you = <span class="hljs-string">'sad'</span>;
[me, you] = [you, me];
<span class="hljs-comment">// me = 'sad', you = 'happy'</span>
</code></pre>
<p>The above code creates an array of [you, me] and immediately destructures them into the opposite variables.</p>
<p>No need for temp variables anymore!</p>
<h2 id="4-setting-defaults">4. Setting defaults</h2>
<p>We have all seen them. The endless if statements checking if the values have been set. What if I said there was a better way? Well, that's exactly what I'm saying, default values.</p>
<h3 id="variables">Variables</h3>
<p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator">nullish coalescing operator (<code>??</code>)</a> is a logical operator that returns its right-hand side operand when its left-hand side operand is <code>null</code> or <code>undefined</code> and otherwise returns its left-hand side operand.
We can use this to set default values, for example when we receive a list that has not been set to an array yet:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bookList = receivedBooks ?? [];
</code></pre>
<h3 id="parameters">Parameters</h3>
<p>We could use the <em>null coalescing operator</em> to set defaults for variables in functions but there is a better way, <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">default parameters</a>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateArea</span>(<span class="hljs-params">width, height = <span class="hljs-number">100</span></span>) </span>{
    <span class="hljs-keyword">return</span> width * height;
}

<span class="hljs-keyword">const</span> area = calculateArea(<span class="hljs-number">50</span>);
<span class="hljs-built_in">console</span>.log(area); <span class="hljs-comment">// 5000</span>
</code></pre>
<p>Here we set the default value for <code>height</code> to 100 and calculate the area by only sending in the <code>width</code>.</p>
<h3 id="objects">Objects</h3>
<p>Another trick when destructruring objects is setting default values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> rectangle = { <span class="hljs-attr">height</span>: <span class="hljs-number">400</span> };
<span class="hljs-keyword">const</span> { height = <span class="hljs-number">750</span>, width = <span class="hljs-number">500</span> } = rectangle;
<span class="hljs-built_in">console</span>.log(height); <span class="hljs-comment">// 400 - comes from rectangle object</span>
<span class="hljs-built_in">console</span>.log(width);  <span class="hljs-comment">// 500 - fallback to default</span>
</code></pre>
<p> ES6 destructuring default values only kick in if the value is <code>undefined</code>.</p>
<h2 id="5-random-number-from-interval">5. Random number from interval</h2>
<p>There are times when we need a random number to be generated within a range. The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random"><code>Math.random()</code></a> function helps us generate a random number, and then we can transform it to the range we want:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> randomIntFromInterval = <span class="hljs-function">(<span class="hljs-params">min, max</span>) =&gt;</span> <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * (max - min + <span class="hljs-number">1</span>) + min);
</code></pre>
<p>There's another trick baked into this one if you look at how the function is constructed.</p>
<h2 id="6-remove-array-duplicates">6. Remove array duplicates</h2>
<p>The Set object type introduced in ES6 lets you store unique values. Together with the spread operator (<code>...</code>), we can use it to create a new array with only the unique values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> uniqueArray = [...new <span class="hljs-built_in">Set</span>(array)]
</code></pre>
<p>We create a Set from an array and because each value in the Set has to be unique we remove all duplicates. We then convert the Set back to a new array using the spread operator.</p>
<h2 id="7-dynamic-property-names">7. Dynamic property names</h2>
<p>ES6 brought us computed property names that allow property keys of object literals to use expressions. By surrounding the key with brackets [], we can use variables as property keys:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> type = <span class="hljs-string">"fruit"</span>;
<span class="hljs-keyword">const</span> item = {
  [type]: <span class="hljs-string">"kiwi"</span>
};

<span class="hljs-built_in">console</span>.log(item); <span class="hljs-comment">// {fruit: "kiwi"}</span>
</code></pre>
<p>This is useful in a situation where you want the key to be created on the fly.</p>
<p>We can access the value with bracket notation:</p>
<pre><code class="lang-js">item[type];   <span class="hljs-comment">// "kiwi"</span>
item[<span class="hljs-string">"fruit"</span>] <span class="hljs-comment">// "kiwi"</span>
</code></pre>
<p>Or with dot notation:</p>
<pre><code class="lang-js">item.fruit; <span class="hljs-comment">// "kiwi"</span>
</code></pre>
<h2 id="8-bonus-trick">8. Bonus trick</h2>
<p>If we want to add a new item to an array <strong>without mutation</strong> (which we usually want to avoid), we can create a new array using the ES6 <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice">slice</a>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> insert = <span class="hljs-function">(<span class="hljs-params">arr, index, newItem</span>) =&gt;</span> [
  ...arr.slice(<span class="hljs-number">0</span>, index), <span class="hljs-comment">// first half of array</span>
  newItem,                <span class="hljs-comment">// new item</span>
  ...arr.slice(index)     <span class="hljs-comment">// rest of array</span>
];

<span class="hljs-keyword">const</span> items = [<span class="hljs-string">'S'</span>, <span class="hljs-string">'L'</span>, <span class="hljs-string">'C'</span>, <span class="hljs-string">'E'</span>]

<span class="hljs-keyword">const</span> result = insert(items, <span class="hljs-number">2</span>, <span class="hljs-string">'I'</span>);

<span class="hljs-built_in">console</span>.log(result); <span class="hljs-comment">// ["S", "L", "I", "C", "E"]</span>
</code></pre>
<h2 id="9">9.</h2>
<p>Why was 6 afraid of 7?</p>
<p>Because 7 ate 9.</p>
<h1 id="conclusion">Conclusion</h1>
<p>I hope you find some of these JavaScript tricks useful and worth adding to your everyday arsenal.
And remember, being responsible is far more important than being efficient.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[A Promise of Asynchronous JavaScript]]></title><description><![CDATA[In this article, we discover the problems with synchronous JavaScript and how we can solve them with the asynchronous techniques of callbacks, promises, and async/await.
We go through the three ways one by one with examples to discover how JavaScript...]]></description><link>https://blog.michaelkaren.dev/a-promise-of-asynchronous-javascript-2d09b9be7019</link><guid isPermaLink="true">https://blog.michaelkaren.dev/a-promise-of-asynchronous-javascript-2d09b9be7019</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Tue, 20 Apr 2021 12:56:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1619630750625/qEmQ3j156.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we discover the <strong>problems with synchronous JavaScript</strong> and how we can <strong>solve them with the asynchronous</strong> techniques of <strong>callbacks, promises, and async/await</strong>.</p>
<p>We go through the three ways one by one with examples to discover how JavaScript has evolved in this area in recent years. However, before looking into these techniques, let’s look into the difference between synchronous and asynchronous code.</p>
<h2 id="synchronous-code">Synchronous code</h2>
<p>JavaScript is a single-threaded programming language, which means only one thing can happen at a time. While a single thread simplifies writing and reasoning about code, this also has some drawbacks.</p>
<p>Imagine we do a long-running task like fetching a resource over the network. Now we block the browser until the resource is downloaded. This can make for a bad user experience and might result in the user leaving our page.</p>
<p>When we execute code <strong>synchronously</strong>, we wait for it to finish before moving to the next task. Nothing else can happen while each operation is being processed — rendering is paused.</p>
<p>Let’s write some code to clarify:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">logFunction</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'in logFunction'</span>);
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Start'</span>);
logFunction();
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'End'</span>);

<span class="hljs-comment">// -&gt; Start</span>
<span class="hljs-comment">// -&gt; in logFunction</span>
<span class="hljs-comment">// -&gt; End</span>
</code></pre>
<p>This code executes as expected.</p>
<ol>
<li>We log “Start”. </li>
<li>We execute the function which logs “in logFunction”</li>
<li>We log “End”.</li>
</ol>
<p>So, synchronous tasks must be aware of one another and be executed in sequence.</p>
<h2 id="asynchronous-code">Asynchronous code</h2>
<p>That’s where asynchronous JavaScript comes into play. Using asynchronous JavaScript, we can perform long-lasting tasks without blocking the main thread. When we execute something <strong>asynchronously</strong>, we can move to another task before it finishes.</p>
<p>The <strong>event loop</strong> is the secret behind JavaScript’s asynchronous programming. JavaScript executes all operations on a single thread, but using a few clever data structures gives us the illusion of multi-threading. If you want to understand what happens under the hood in the following examples, you should read more about the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop">concurrency model and the event loop</a>.</p>
<p>Let’s do another example, this time using <code>setTimeout()</code>, that allows us to wait a defined number of milliseconds before running its code:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Start'</span>);

<span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'In timeout'</span>);
}, <span class="hljs-number">1000</span>); <span class="hljs-comment">// Wait 1s to run</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'End'</span>);

<span class="hljs-comment">// -&gt; Start</span>
<span class="hljs-comment">// -&gt; End</span>
<span class="hljs-comment">// -&gt; In timeout</span>
</code></pre>
<p>Did you expect “In timeout” to be logged before “End”? 
We are not blocking the code execution but instead, we continue and come back to run the code inside <code>setTimeout</code> one second later.</p>
<p>Let’s look at another example. When we fetch an image from a server, we can’t return the result immediately. That means that the following wouldn’t work:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">let</span> response = fetch(<span class="hljs-string">'myImage.png'</span>); <span class="hljs-comment">// fetch is asynchronous</span>
<span class="hljs-keyword">let</span> blob = response.blob();
</code></pre>
<p>That’s because we don’t know how long the image takes to download, so when we run the second line, it throws an error because the response is not yet available. Instead, we need to wait until the response returns before using it.</p>
<p>Let’s look at how we would solve this with asynchronous code.</p>
<h2 id="callbacks">Callbacks</h2>
<p>This approach to asynchronous programming is to make slow-performing actions take an extra argument, a <strong>callback function</strong>. When the slow action finishes, the callback function is called with the result.</p>
<p>As an example, the <code>setTimeout</code> function waits a given number of milliseconds before calling a function. We can simulate slow asynchronous tasks without calling the backend this way:</p>
<pre><code class="lang-js"><span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'One second later.'</span>), <span class="hljs-number">1000</span>);
</code></pre>
<p>While the concept of callbacks is great in theory, it can lead to confusing and difficult-to-read code. Just imagine making callback after callback:</p>
<pre><code class="lang-javascript">getData(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a</span>) </span>{
  getMoreData(a, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">b</span>) </span>{
    getMoreData(b, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">c</span>) </span>{ 
      getMoreData(c, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">d</span>) </span>{ 
       <span class="hljs-comment">// ...</span>
      });
    });
  });
});
</code></pre>
<p>Nested callbacks going several levels deep are sometimes called <strong>callback hell</strong>. Each new callback level makes the code more difficult to understand and maintain. Using callbacks is not common these days, but if we get unlucky we might find them in legacy code bases.</p>
<p>Next, we look into how modern JavaScript has tried to solve this problem.</p>
<h2 id="promises">Promises</h2>
<p>Promises, introduced with ES6, are a new way of dealing with asynchronous operations in JavaScript. A <strong>promise</strong> is an object that might produce a value in the future. Just like in real life, we don’t know if the promise will be kept and we use the promise object as a placeholder while we wait for the outcome.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>();
</code></pre>
<p>Having an object as a proxy for future values lets us write the code in a synchronous manner. We get the promise object and continue executing the code. But, there is a bit more to it, as we will see.</p>
<p>The promise constructor takes one argument, a callback with two parameters, one for success (resolve) and one for fail (reject). We need to either resolve a promise if it’s fulfilled or reject it if it failed:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> { 

  <span class="hljs-comment">// Do stuff</span>

  <span class="hljs-keyword">if</span> (<span class="hljs-comment">/* fulfilled */</span>) {
    resolve(<span class="hljs-string">'It worked!'</span>);
  } <span class="hljs-keyword">else</span> {
    reject(<span class="hljs-built_in">Error</span>(<span class="hljs-string">'It failed!'</span>));
  } 
});
</code></pre>
<h2 id="states">States</h2>
<p>A promise in JavaScript is similar to a promise in real life. It will either be kept, (fulfilled), or it won’t (rejected).</p>
<p>A promise can be:</p>
<ul>
<li><p><strong>pending </strong>— Initial state, not fulfilled or rejected yet.</p>
</li>
<li><p><strong>fulfilled </strong>— The operation succeeded. <code>resolve()</code> was called.</p>
</li>
<li><p><strong>rejected </strong>— The operation failed. <code>reject()</code> was called.</p>
</li>
<li><p><strong>settled</strong>— Has fulfilled or rejected.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619630744916/tzF-5n28M.png" alt /></p>
<p>After a promise is <em>settled</em> it can not change its state anymore.</p>
<h3 id="resolve">Resolve</h3>
<p>Let’s create a promise and resolve it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  resolve(<span class="hljs-string">'We are done.'</span>);
});

<span class="hljs-built_in">console</span>.log(promise);
<span class="hljs-comment">// -&gt; Promise {&lt;fulfilled&gt;: "We are done."}</span>
</code></pre>
<p>We can see that resolving the promise resulted in a <em>fulfilled</em> state.</p>
<p>Now that we have created a promise, let’s see how to use it.</p>
<h3 id="then">Then</h3>
<p>To access the value passed by the <code>resolve</code> or <code>reject</code> functions, we can use <code>then()</code>. It takes two optional arguments, a callback for a resolved case and another for a rejected one.</p>
<p>In this case, we get its resolved value by using the <code>then()</code> method:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  resolve(<span class="hljs-string">'We are done.'</span>);
});

promise.then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(result));
<span class="hljs-comment">// -&gt; We are done.</span>
</code></pre>
<p>A promise can only resolve or reject once.</p>
<h3 id="chaining">Chaining</h3>
<p>Since <code>then()</code> returns a new promise, it can be chained. Like synchronous code, chaining results in a sequence that runs in serial.</p>
<p>Consider this simplified example where we fetch some data:</p>
<pre><code><span class="hljs-selector-tag">fetch</span>(url)
 <span class="hljs-selector-class">.then</span>(processData)
 <span class="hljs-selector-class">.then</span>(saveData)
 <span class="hljs-selector-class">.catch</span>(handleErrors);
</code></pre><p>Assuming each function returns a promise, <code>saveData()</code> waits for <code>processData()</code> to complete before starting, which in turn waits for <code>fetch()</code> to complete. <code>handleErrors()</code> only runs if any of the previous promises reject.</p>
<p>The possibility of chaining is one of the advantages of using Promises compared to callbacks.</p>
<h3 id="error-handling">Error handling</h3>
<p>When a promise rejects, the control jumps to the closest rejection handler. The <code>catch()</code> doesn’t have to be immediately after, it may instead appear after one or multiple <code>then()</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> promise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  reject(<span class="hljs-string">'We failed.'</span>);
});

promise
  .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.json())
  .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(error));
<span class="hljs-comment">// -&gt; We failed.</span>
</code></pre>
<p>We should end all promise chains with a <code>catch()</code>.</p>
<p>Promises are commonly used when fetching data over a network or doing other kinds of asynchronous programming in JavaScript and have become an integral part of modern JavaScript.</p>
<p>Next, let’s take a look at <code>async/await</code>.</p>
<h2 id="async-and-await">Async and Await</h2>
<p><strong>Async functions and the await keyword</strong>, new additions with ECMAScript 2017, act as syntactic sugar on top of promises allowing us to write synchronous-looking code while performing asynchronous tasks behind the scenes.</p>
<h2 id="async">Async</h2>
<p>First, we have the <code>async</code> keyword. We put it in front of a function declaration to turn it into an <em>async function</em>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params">url</span>) </span>{}
</code></pre>
<p>Invoking the function now returns a <strong>promise</strong>. This is one of the traits of async functions — their return values are converted to promises.</p>
<p><em>Async functions</em> enable us to write promise-based code as if it were synchronous, but without blocking the execution thread and instead operating asynchronously.</p>
<p>However, <code>async</code> alone does not make the magic happen. The next step is to use the <code>await</code> keyword inside the function.</p>
<h2 id="await">Await</h2>
<p>The real advantage of <em>async functions</em> becomes apparent when you combine them with the <code>await</code> keyword. Await can only be used inside an async block, where it makes JavaScript wait until a promise returns a result.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> value = <span class="hljs-keyword">await</span> promise
</code></pre>
<p>The keyword <code>await</code> makes JavaScript pause at that line until the promise settles and returns its result, and then resumes code execution.</p>
<p>It’s a more elegant syntax of getting the result from a promise than <code>promise.then()</code>.</p>
<h2 id="fetch">Fetch</h2>
<p><code>fetch()</code> allows us to make network requests similar to <code>XMLHttpRequest</code> (XHR). The main difference is that the <strong>Fetch API</strong> uses promises, which enables a simpler and cleaner API, avoiding callbacks.</p>
<p>The simplest use of <code>fetch()</code> takes one argument — the path to the resource — and returns a promise containing the response.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> getData(url) {
 <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(url);
 <span class="hljs-keyword">return</span> data;
}
</code></pre>
<p>In our code, we now wait for <code>fetch()</code> to return with the data before we return it from the function.</p>
<p>Now, we have our function ready. Remember, since it returns a promise, we need to use <code>then()</code> to get hold of the value.</p>
<pre><code class="lang-js">getData(url).then(<span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(data));
</code></pre>
<p>Or we could even write this shorthand:</p>
<pre><code class="lang-js">getData(url).then(<span class="hljs-built_in">console</span>.log);
</code></pre>
<p>We have all the basics of expected behavior figured out now, but what if something unexpected happens?</p>
<h2 id="error-handling">Error handling</h2>
<p>If <code>await promise</code> is rejected, it throws the error, just as if there were a <code>throw</code> statement at that line. We can catch that error using <code>try/catch</code>, the same way as in regular code where an error is thrown.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> getData(url) {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(url);
    <span class="hljs-keyword">return</span> data;
  } <span class="hljs-keyword">catch</span>(error) {
    <span class="hljs-comment">// Handle error</span>
  }
}
</code></pre>
<p>If we don’t have the <code>try/catch</code>, the promise generated by calling the async function becomes rejected. We can append <code>catch()</code> to handle it:</p>
<pre><code class="lang-js">getData(url).catch(alert);
</code></pre>
<p>If we don’t add a <code>catch()</code>, we get an unhandled promise error. We could catch such errors using a global error handler.</p>
<h2 id="example-with-fetch">Example with fetch</h2>
<p>For testing purposes, it’s often a good idea to start by making the data available locally. We can do this by creating a <strong>json file</strong> with the data. Since we can use <code>fetch()</code> to get the data from it just like we would do with a remote call it’s easy to replace the URL from local to remote.</p>
<p>We can’t use fetch directly on the file system so we need to run a webserver to serve our file.</p>
<h3 id="http-server">Http-server</h3>
<p>If we don’t have a web server on our machine, we can use the simple, zero-configuration command-line <a target="_blank" href="https://github.com/http-party/http-server#readme">http-server</a>. You need <a target="_blank" href="https://nodejs.org/en/download/">Node.js</a> installed on your machine. <a target="_blank" href="https://www.npmjs.com/package/npx">Npx</a> is a tool for executing Node packages, and we can use it to run our server:</p>
<pre><code class="lang-bash">npx http-server
</code></pre>
<p>It serves files from the folder we run the command from. When the server starts, it tells you which address to go to in your browser to run the application:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1619630747749/SYMDOs-kO.png" alt /></p>
<p>Now that we are serving the file, we can start the actual coding.</p>
<h3 id="fetch">Fetch</h3>
<p>First, we create a file <code>data.json</code> where we can save the data in JSON format. Next, we write an <em>async function `</em>getData()` to get the data from the local json file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'data.json'</span>)
    .then(<span class="hljs-function">(<span class="hljs-params">response</span>) =&gt;</span> response.json())
    .catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(error))
  || [] <span class="hljs-comment">// Default if file is empty;</span>

  <span class="hljs-keyword">return</span> data;
}
</code></pre>
<p>The response from fetch is an HTTP response, not the actual JSON. To extract the JSON body content from the response, we use the <code>json()</code> method. Running the code retrieves the data from the local file.</p>
<h2 id="conclusion">Conclusion</h2>
<p>When we have code that doesn’t complete immediately, we need to wait for it to finish before continuing. This is where asynchronous JavaScript comes in. We looked into the differences between synchronous and asynchronous JavaScript and how we first tried solving it with callbacks.</p>
<p>Next, we learned about promises, and how they solve some of the problems we had with callbacks. Promises are commonly used when fetching data over a network or doing other kinds of asynchronous programming in JavaScript. They have become an integral part of modern JavaScript and as such, are important for JavaScript developers to master.</p>
<p>Async/await provides a nice, simplified way to write async code that is simpler to read and maintain. The <code>async</code> keyword tells that functions return a promise rather than directly returning the value. The <code>await</code> keyword can only be used inside an async block, where it makes JavaScript wait until a promise returns a result.</p>
<p>I hope that after reading this, you have a better understanding of asynchronous JavaScript and the different techniques we can use to implement it.</p>
]]></content:encoded></item><item><title><![CDATA[Maintaining Multi-language Angular Applications with i18n]]></title><description><![CDATA[Angular i18n and the localizing of applications had an overhaul with version 9, enabled by the new rendering engine Ivy. In this article, we take a closer look at how this built-in package of Angular now works, while pointing out the benefits and dra...]]></description><link>https://blog.michaelkaren.dev/maintaining-multi-language-angular-applications-i18n</link><guid isPermaLink="true">https://blog.michaelkaren.dev/maintaining-multi-language-angular-applications-i18n</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Angular]]></category><category><![CDATA[i18n]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 05 Apr 2021 11:08:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075774926/9dy7bVSwN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Angular i18n and the localizing of applications had an overhaul with version 9</strong>, enabled by the new rendering engine Ivy. In this article, we <strong>take a closer look at how this built-in package of Angular now works</strong>, while pointing out the benefits and drawbacks we find.</p>
<p>We then set up an application with Angular internationalization and go through the complete process from marking texts for translation, extracting them to translation files, and how we manage these files to get the application deployed and maintained while keeping users all over the world happy with our translations.</p>
<p>And speaking of international, if you prefer reading in Spanish:</p>
<ul>
<li><a target="_blank" href="https://www.ibidem-translations.com/edu/traduccion-app-angular-i18n-i10n/">Cómo mantener las traducciones de una app Angular con i18n</a></li>
</ul>
<p><em>Illustration by</em> <a target="_blank" href="https://twitter.com/VeroIsabellaK"><em>Vero Karén</em></a></p>
<h2 id="heading-internationalization-and-localization">Internationalization and localization</h2>
<p>It’s easy to get confused with the terms <strong>internationalization (i18n)</strong> and <strong>localization (i10n),</strong> and where to draw the line between them. <em>Internationalization</em> is the process of designing your application so that it can be adapted to different locales around the world while <em>localization</em> is the process of building the versions of the applications to different locales.</p>
<p>Together they help us in adapting software to different languages and local variations in the look and feel expected by the target audience.</p>
<h2 id="heading-how-localization-works-with-ivy">How localization works with Ivy</h2>
<p>The new localization process of <a target="_blank" href="https://angular.io/guide/ivy">Angular Ivy</a> is based on the concept of <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates">tagged templates</a>. Tags allow you to parse template literals with a function. The tag used here is the global identifier <code>$localize</code>. Instead of translating the strings, the Ivy template compiler converts all template text marked with <code>i18n</code> attributes to <code>$localize</code> tagged strings.</p>
<p>So when we add:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">i18n</span>&gt;</span>Hello World!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<p>It will be compiled to <code>$localize</code> calls and somewhere in the compiled code we will be able to find:</p>
<pre><code class="lang-js">$localize<span class="hljs-string">`Hello World!`</span>
</code></pre>
<p>The way the <em>tagged template</em> works is that you put the function that you want to run against the string before the template. Instead of <code>function()</code>, you have <code>function`` </code> or as in this case <code>$localize`` </code> .</p>
<p>When this step is done we have two choices:</p>
<ul>
<li><p><strong>compile-time inlining</strong>: the <a target="_blank" href="https://angular.io/api/localize/init/$localize"><code>$localize</code></a> tag is transformed at compile time by a transpiler, removing the tag and replacing the template literal string with the translation.</p>
</li>
<li><p><strong>run-time evaluation</strong>: the <a target="_blank" href="https://angular.io/api/localize/init/$localize"><code>$localize</code></a> tag is a run-time function that replaces the template literal string with translations loaded at run-time.</p>
</li>
</ul>
<p>In this article, we use <em>compile-time inlining</em> to achieve our goals. At the very end of the build process, we run a step for the translation files by providing an option flag to get a localized application for the languages. Since we are doing the translations compile-time we get one application per locale.</p>
<p>At the end of the article, we take a further look into <em>run-time evaluation</em>.</p>
<blockquote>
<p>Because the application does not need to be built again for each locale, the build process is much faster than before v9 of Angular.</p>
</blockquote>
<p><img src="https://cdn-images-1.medium.com/max/2696/0*GMtohFA2nbkDKzpB.png" alt="You can read more about this in Angular localization with Ivy from where this picture is." /></p>
<p><em>You can read more about this in</em> <a target="_blank" href="https://blog.angular.io/angular-localization-with-ivy-4d8becefb6aa"><em>Angular localization with Ivy</em></a> <em>from where this picture is.</em></p>
<p>Now that we understand the process of building the application we start to get an understanding of what it entails.</p>
<h2 id="heading-the-good-and-the-bad">The good and the bad</h2>
<p>The standard Angular internationalization and localization are designed to produce one compiled application per language. By doing this we get optimal performance since there is no overhead of loading translation files and compiling them at run-time. But, this also means that each language has to be deployed to a separate URL:</p>
<pre><code class="lang-plaintext">www.mydomain.com/en
www.mydomain.com/nb
www.mydomain.com/fi
</code></pre>
<p>This means we need to do a bit more set up on our webserver. A limitation with <code>ng serve</code> is that it only works with one language at a time and to run different languages also needs some configuration. To run all languages locally we need to use a local webserver. We look into how we do all this in this article.</p>
<p>Angular i18n uses <strong>XLIFF</strong> and <strong>XMB</strong> formats that are XML-based, more verbose formats than JSON. But since these files are used at compile-time it doesn’t matter. It makes sense to use JSON when we load the translation files at run-time to keep the file sizes smaller. The formats chosen for the built-in i18n are used by translation software which helps us with our translations as we will see.</p>
<p>The number one drawback that people find with this solution is that you need to reload the application when you switch languages. But, is this really going to be a problem for you? People usually switch languages once if ever. And that couple of seconds it takes to reload applications will not be a problem.</p>
<p>Having one bundle per language is not a problem for a web SPA other than that you have to configure your web server for this. But for standalone apps, this means you got to make the user download every translated bundle, or distribute a different app for every version.</p>
<p>It’s important to understand your requirements before deciding which route to take.</p>
<h2 id="heading-transloco">Transloco</h2>
<p>If the standard Angular i18n doesn’t give you what you want then the best alternative today in my opinion is <a target="_blank" href="https://ngneat.github.io/transloco/">Transloco</a>. It’s being actively maintained and has an active community. It will get you up and running faster and is more flexible than the built-in solution. Since Transloco is runtime translation you have just <code>www.mydoman.com</code> and can change localization on the fly.</p>
<p>So, before choosing which way to go in such a fundamental choice you should check Transloco out to see if it would be a better fit for you.</p>
<p>OK, enough technicalities let’s see some code!</p>
<h2 id="heading-add-localize-to-angular-project">Add localize to Angular project</h2>
<p><code>@angular/localize</code> package was <a target="_blank" href="https://blog.angular.io/version-9-of-angular-now-available-project-ivy-has-arrived-23c97b63cfa3#b939">released with Angular 9</a> and supports i18n in Ivy applications. This package requires a global <a target="_blank" href="https://angular.io/api/localize/init/$localize"><code>$localize</code></a> symbol to exist. The symbol is loaded by importing the <a target="_blank" href="https://angular.io/api/localize/init"><code>@angular/localize/init</code></a> module.</p>
<p>To add the localization features provided by Angular, we need to add the <code>@angular/localize</code> package to our project:</p>
<pre><code class="lang-bash">ng add @angular/localize
</code></pre>
<p>This command:</p>
<ul>
<li><p>Updates <code>package.json</code> and installs the package.</p>
</li>
<li><p>Updates <code>polyfills.ts</code>to import the <code>@angular/localize</code> package.</p>
</li>
</ul>
<p>If you try using i18n without adding this package you get a self-explanatory error message reminding us to run <code>ng add @angular/localize</code>.</p>
<h2 id="heading-translating-templates">Translating templates</h2>
<p>To translate templates in our application, we need first to prepare the texts by marking them with the <code>i18n</code> attribute.</p>
<blockquote>
<p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization">i18n</a> is a custom attribute from the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions">WebExtensions</a> API. It’s recognized by Angular tools and compilers. During the compilation, it is removed, and the tag content is replaced with the translations.</p>
</blockquote>
<p>We mark the text like this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">i18n</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
</code></pre>
<p>This <code>&lt;span&gt;</code> tag is now marked and ready for the next step in the translation process.</p>
<h2 id="heading-translating-typescript-files">Translating TypeScript files</h2>
<blockquote>
<p>NB! You need Angular 10.1 or later to extract strings from source code (.ts) files.</p>
</blockquote>
<p>It’s not only our templates that need to be translated. Sometimes we have code in our TypeScript files that also need a translation. To localize a string in the source code, we use the <code>$localize</code> template literal:</p>
<pre><code class="lang-js">title = $localize<span class="hljs-string">`My page`</span>;
</code></pre>
<p>Note that <a target="_blank" href="https://michael-karen.medium.com/getting-started-with-modern-javascript-template-literals-d72f25511ab5">template literals</a> use the backtick (`) character instead of double or single quotes.</p>
<h2 id="heading-extracting-texts">Extracting texts</h2>
<p>When our application is prepared to be translated, we can use the <a target="_blank" href="https://angular.io/cli/extract-i18n">extract-i18n</a> command to extract the marked texts into a <strong>source language file</strong> named <code>messages.xlf</code>.</p>
<p>The command options we can use are:</p>
<ul>
<li><p><code>--output-path</code>: Change the location of the source language file.</p>
</li>
<li><p><code>--outFile</code>: Change the file name.</p>
</li>
<li><p><code>--format</code>: Change file format. Possible formats are <a target="_blank" href="https://en.wikipedia.org/wiki/XLIFF">XLIFF 1.2</a> (default), XLIFF 2, and <a target="_blank" href="http://cldr.unicode.org/development/development-process/design-proposals/xmb">XML Message Bundle (XMB)</a>.</p>
</li>
</ul>
<p>Running this command from the root directory of the project:</p>
<pre><code class="lang-bash">ng extract-i18n
</code></pre>
<p>We get the <code>messages.xlf</code> file looking like this:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">xliff</span> <span class="hljs-attr">version</span>=<span class="hljs-string">"1.2"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"urn:oasis:names:tc:xliff:document:1.2"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">file</span> <span class="hljs-attr">source-language</span>=<span class="hljs-string">"en-US"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"plaintext"</span> <span class="hljs-attr">original</span>=<span class="hljs-string">"ng2.template"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"3492007542396725315"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.html<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"5513198529962479337"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>My page<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.ts<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">file</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">xliff</span>&gt;</span>
</code></pre>
<p>We can see that we have the texts “Welcome” and “My page” in the file but what does it all mean?</p>
<ul>
<li><p><code>trans-unit</code> is the tag containing a single translation. <code>id</code> is a translation identifier that <code>extract-i18n</code> generates so don’t modify it!</p>
</li>
<li><p><code>source</code> contains translation source text.</p>
</li>
<li><p><code>context-group</code> specifies where the given translation can be found.</p>
</li>
<li><p><code>context-type="sourcefile"</code> shows the file where translation is from.</p>
</li>
<li><p><code>context-type="linenumber"</code> tells the line of code of the translation.</p>
</li>
</ul>
<p>Now that we have extracted the source file, how do we get files with the languages we want to translate?</p>
<h2 id="heading-create-translation-files">Create translation files</h2>
<p>After we have generated the <code>messages.xlf</code> file, we can add new languages by copying it and naming the new file accordingly with the associated locale.</p>
<p>To store Norwegian translations we rename the copied file to <code>messages.nb.xlf</code>. Then we send this file to the translator so that he can do the translations with an XLIFF editor. But, let’s not get ahead of us and first do a manual translation to get a better understanding of the translation files.</p>
<h3 id="heading-translating-files-manually">Translating files manually</h3>
<p>Open the file and find the <code>&lt;trans-unit&gt;</code> element, representing the translation of the <code>&lt;h1&gt;</code> greeting tag that was previously marked with the <code>i18n</code> attribute. Duplicate the <code>&lt;source&gt;...&lt;/source&gt;</code> element in the text node, rename it to <code>target</code>, and then replace its content with the Norwegian text:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">xliff</span> <span class="hljs-attr">version</span>=<span class="hljs-string">"1.2"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"urn:oasis:names:tc:xliff:document:1.2"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">file</span> <span class="hljs-attr">source-language</span>=<span class="hljs-string">"en-US"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"plaintext"</span> <span class="hljs-attr">original</span>=<span class="hljs-string">"ng2.template"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"3492007542396725315"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">target</span>&gt;</span>Velkommen<span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.html<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"5513198529962479337"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>my page<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.ts<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>9<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">file</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">xliff</span>&gt;</span>
</code></pre>
<p>This is all that there is to it to add the translations to the files. Let’s see how we do it with an editor.</p>
<h3 id="heading-translating-files-with-an-editor">Translating files with an editor</h3>
<p>Before we can use an editor, we need to provide the translation language. We can do this by adding the <code>target-language</code> attribute for the file tag so that translation software can detect the locale:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">file</span> <span class="hljs-attr">source-language</span>=<span class="hljs-string">"en-US"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"plaintext"</span> <span class="hljs-attr">original</span>=<span class="hljs-string">"ng2.template"</span> <span class="hljs-attr">target-language</span>=<span class="hljs-string">"nb"</span>&gt;</span>
</code></pre>
<p>Let’s open this file in a translation tool to see what we are working with. I’m using the free version of <a target="_blank" href="https://poedit.net/">PoEdit</a> in this article:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075769143/GoAaKAWlq.png" alt /></p>
<p>This looks much easier to work with than the manual way. We even get some suggestions for translations. Let’s translate “my page” and save the file. If we then open <code>messages.nb.xlf</code> we can see that it has added the translation in a target block like when we did it manually:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>My page<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">target</span> <span class="hljs-attr">state</span>=<span class="hljs-string">"translated"</span>&gt;</span>Min side<span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span>
</code></pre>
<p>We see that it added <code>state="translated"</code> to the target tag. This is an optional attribute that can have the values <code>translated</code>, <code>needs-translation</code>, or <code>final</code>. This helps us when using the editor to find the texts that are not yet translated.</p>
<p>This is a great start but before we try out the translations in our application, let’s see what more we can do by adding more information into the box in the screenshot named “Notes for translators”.</p>
<h2 id="heading-notes-for-translators">Notes for translators</h2>
<p>Sometimes the translator needs more information about what they are translating. We can add a <strong>description</strong> of the translation as the value of the i18n attribute:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">i18n</span>=<span class="hljs-string">"Welcome message"</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
</code></pre>
<p>We can add even more context to the translator by adding the <strong>meaning</strong> of the text message. We can add the <em>meaning</em> together with the <em>description</em> and separate them with the <code>|</code> character: <code>&lt;meaning&gt;|&lt;description&gt;</code>. In this example we might want to let the translator know that this welcome message is located in the toolbar:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">i18n</span>=<span class="hljs-string">"toolbar header|Welcome message"</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
</code></pre>
<p>The last part that we can add to the value of the <code>i18n</code> attribute is an ID by using <code>@@</code>. Be sure to define unique custom ids. If you use the same id for two different text messages, only the first one is extracted, and its translation is used in place of both original text messages.</p>
<p>Here we add the ID <code>toolbarHeader</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">i18n</span>=<span class="hljs-string">"toolbar header|Welcome message@@toolbarHeader"</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
</code></pre>
<p>If we don’t add an ID for the translation, Angular will generate a random ID as we saw earlier. Running <code>ng extract-i18n</code> again we can see that the helpful information has been added to our translation unit:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"toolbarHeader"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>Welcome<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.html<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>7<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">note</span> <span class="hljs-attr">priority</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">from</span>=<span class="hljs-string">"description"</span>&gt;</span>Welcome message<span class="hljs-tag">&lt;/<span class="hljs-name">note</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">note</span> <span class="hljs-attr">priority</span>=<span class="hljs-string">"1"</span> <span class="hljs-attr">from</span>=<span class="hljs-string">"meaning"</span>&gt;</span>toolbar header<span class="hljs-tag">&lt;/<span class="hljs-name">note</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
</code></pre>
<ul>
<li>There are now a couple of <code>note</code> tags that provide the translation <code>description</code> and <code>meaning</code> and the <code>id</code> is no longer a random number.</li>
</ul>
<p>If we copy these to the <code>messages.ng.xlf</code> file and open it in PoEdit we see that all these are now visible in “Notes for translators”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075770919/WrcgDKyAx.png" alt /></p>
<h2 id="heading-providing-context-in-typescript-files">Providing context in TypeScript files</h2>
<p>Like with Angular templates you can provide more context to translators by providing <code>meaning</code>, <code>description</code>, and <code>id</code> in TypeScript files. The format is the same as used for <code>i18n</code> markers in the templates. Here are the different options as found in the <a target="_blank" href="https://angular.io/api/localize/init/$localize#description">Angular Docs</a>:</p>
<pre><code class="lang-js">$localize<span class="hljs-string">`:meaning|description@@id:source message text`</span>;
$localize<span class="hljs-string">`:meaning|:source message text`</span>;
$localize<span class="hljs-string">`:description:source message text`</span>;
$localize<span class="hljs-string">`:@@id:source message text`</span>;
</code></pre>
<p>Adding an <code>id</code> and <code>description</code> to our title could look like this:</p>
<pre><code class="lang-js">title = $localize<span class="hljs-string">`:Header on first page@@firstPageTitle:My page`</span>;
</code></pre>
<p>If the template literal string contains expressions, you can provide the placeholder name wrapped in <code>:</code> characters directly after the expression:</p>
<pre><code class="lang-js">$localize<span class="hljs-string">`Hello <span class="hljs-subst">${person.name}</span>:name:`</span>;
</code></pre>
<h2 id="heading-specialized-use-cases">Specialized use cases</h2>
<p>There are some specialized use cases for translations that we need to look at. <strong>Attributes</strong> can easily be overlooked but are also important to translate, not least for accessibility.</p>
<p>Different languages have different pluralization rules and grammatical constructions that can make translation difficult. To simplify translation, we can use <code>plural</code> to mark the uses of plural numbers and <code>select</code> to mark alternate text choices.</p>
<h3 id="heading-attributes">Attributes</h3>
<p>Apart from the usual suspects of HTML tags, we need to also be aware that we need to translate HTML attributes. This is especially important when we are making our applications accessible to all people.</p>
<p>Let’s take the example of an <code>img</code> tag. People using a screen reader would not see the picture but instead, the <code>alt</code> attribute would be read to them. For this reason and others, provide a useful value for <code>alt</code> whenever possible.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> [<span class="hljs-attr">src</span>]=<span class="hljs-string">"logo"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Welcome logo"</span> /&gt;</span>
</code></pre>
<p>To mark an attribute for translation, add <code>i18n-</code> followed by the attribute that is being translated. To mark the <code>alt</code> attribute on the <code>img</code> tag we add <code>i18n-alt</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> [<span class="hljs-attr">src</span>]=<span class="hljs-string">"logo"</span> <span class="hljs-attr">i18n-alt</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Welcome logo"</span> /&gt;</span>
</code></pre>
<p>In this case, the text “Welcome logo” will be extracted for translation.</p>
<blockquote>
<p>You can also assign a meaning, description, and custom ID with the <code>i18n-attribute="&lt;meaning&gt;|&lt;description&gt;@@&lt;id&gt;"</code> syntax.</p>
</blockquote>
<h3 id="heading-plurals">Plurals</h3>
<p>Pluralization rules between languages differ. We need to account for all potential cases. We use the <code>plural</code> clause to mark expressions we want to translate depending on the number of subjects.</p>
<p>For example, imagine we do a search and want to show how many results were found. We want to show “nothing found” or the number of results appended with “items found”. And of course, let’s not forget about the case with only one result.</p>
<p>The following expression allows us to translate the different plurals:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">i18n</span>&gt;</span>
{itemCount, plural, =0 {nothing found} =1 {one item found} other {{{itemCount}} items found}}
<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<ul>
<li><p><code>itemCount</code> is a property with the number of items found.</p>
</li>
<li><p><code>plural</code> identifies the translation type.</p>
</li>
<li><p>The third parameter lists all the possible cases (0, 1, other) and the corresponding text to display. Unmatched cases are caught by <code>other</code>. Angular supports more categories <a target="_blank" href="https://angular.io/guide/i18n#mark-plurals">listed here</a>.</p>
</li>
</ul>
<p>When we translate plural expression we have two trans units: One for the regular text placed before the plural and one for the plural versions.</p>
<h3 id="heading-alternates">Alternates</h3>
<p>If your text depends on the value of a variable, you need to translate all alternatives. Much like <code>plural</code>, we can use the <code>select</code> clause to mark choices of alternate texts. It allows you to choose one of the translations based on a value:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">i18n</span>&gt;</span>Color: {color, select, red {red} blue {blue} green {green}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
</code></pre>
<p>Based on the value of <code>color</code> we display either “red”, “blue”, or “green”. Like when translating plural expressions we get two trans units:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"7195591759695550088"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>Color: <span class="hljs-tag">&lt;<span class="hljs-name">x</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"ICU"</span> <span class="hljs-attr">equiv-text</span>=<span class="hljs-string">"{color, select, red {red} blue {blue} green {green}}"</span>/&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.html<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>12<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">trans-unit</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"3928679011634560837"</span> <span class="hljs-attr">datatype</span>=<span class="hljs-string">"html"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>{VAR_SELECT, select, red {red} blue {blue} green {green}}<span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">context-group</span> <span class="hljs-attr">purpose</span>=<span class="hljs-string">"location"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"sourcefile"</span>&gt;</span>src/app/app.component.html<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">context</span> <span class="hljs-attr">context-type</span>=<span class="hljs-string">"linenumber"</span>&gt;</span>12<span class="hljs-tag">&lt;/<span class="hljs-name">context</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">context-group</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">trans-unit</span>&gt;</span>
</code></pre>
<p>The editors understand these units and help us with the translations:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075772614/avS2wCzQV.png" alt /></p>
<h3 id="heading-interpolation">Interpolation</h3>
<p>Let’s combine a welcome message the <code>title</code> property:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">i18n</span>&gt;</span>Welcome to {{ title }}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
</code></pre>
<p>This places the value of the <code>title</code> variable that we earlier translated in the text. When we extract this text we see how the interpolation is handled:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">source</span>&gt;</span>Welcome to <span class="hljs-tag">&lt;<span class="hljs-name">x</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"INTERPOLATION"</span> <span class="hljs-attr">equiv-text</span>=<span class="hljs-string">"{{ title }}"</span>/&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">source</span>&gt;</span>
</code></pre>
<p>For the translation the <code>&lt;x.../&gt;</code> stays the same for the target language:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">target</span>&gt;</span>Velkommen til <span class="hljs-tag">&lt;<span class="hljs-name">x</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"INTERPOLATION"</span> <span class="hljs-attr">equiv-text</span>=<span class="hljs-string">"{{ title }}"</span>/&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">target</span>&gt;</span>
</code></pre>
<p>And that’s the last example of translations that we are looking at. Now, let’s see how we can get this applications up and running with our new language!</p>
<h2 id="heading-configuring-locales">Configuring locales</h2>
<p>To be able to run our application in many languages we need to define the locales in the build configuration. In the <code>angular.json</code> file, we can define locales for a project under the <code>i18n</code> option and <code>locales</code>, that maps locale identifiers to translation files:</p>
<pre><code class="lang-json"><span class="hljs-string">"projects"</span>: {
  <span class="hljs-attr">"i18n-app"</span>: {
    <span class="hljs-attr">"i18n"</span>: {
      <span class="hljs-attr">"sourceLocale"</span>: <span class="hljs-string">"en-US"</span>,
      <span class="hljs-attr">"locales"</span>: {
        <span class="hljs-attr">"nb"</span>: <span class="hljs-string">"messages.nb.xlf"</span>
      }
   }
}
</code></pre>
<p>Here we added the configuration for the Norwegian language. We provide the path for the translation file for the locale <code>"nb"</code>. In our case, the file is still in the root directory.</p>
<p>The <code>sourceLocale</code> is the locale you use within the app source code. The default is <code>en-US</code> so we could leave this line out or we could change it to another language. Whatever value we use here is also used to build an application together with the <code>locales</code> we define.</p>
<p>To use your locale definition in the build configuration, use the <code>"localize"</code> option in <code>angular.json</code> to tell the CLI which locales to generate for the build configuration:</p>
<ul>
<li><p>Set <code>"localize"</code> to <code>true</code> for <em>all</em> the locales previously defined in the build configuration.</p>
</li>
<li><p>Set <code>"localize"</code> to an array of a subset of the previously-defined locale identifiers to build only those locale versions.</p>
</li>
</ul>
<p>The development server only supports localizing a single locale at a time. Setting the <code>"localize"</code> option to <code>true</code> will cause an error when using <code>ng serve</code> if more than one locale is defined. Setting the option to a specific locale, such as <code>"localize": ["nb"]</code>, can work if you want to develop against a specific locale.</p>
<p>Since we want to be able to <code>ng serve</code> our application with a single language, we create a custom locale-specific configuration by specifying a single locale in <code>angular.json</code> as follows:</p>
<pre><code class="lang-json"><span class="hljs-string">"build"</span>: {
  <span class="hljs-attr">"configurations"</span>: {
    <span class="hljs-attr">"nb"</span>: {
      <span class="hljs-attr">"localize"</span>: [<span class="hljs-string">"nb"</span>]
    }
  }
},
<span class="hljs-string">"serve"</span>: {
  <span class="hljs-attr">"configurations"</span>: {
    <span class="hljs-attr">"nb"</span>: {
      <span class="hljs-attr">"browserTarget"</span>: <span class="hljs-string">"ng-i18n:build:nb"</span>
    }
  }
}
</code></pre>
<p>With this change we can serve the Norwegian version of the app and make sure the translations are working by sending in <code>nb</code> to the <code>configuration</code> option:</p>
<pre><code class="lang-bash">ng serve --configuration=nb
</code></pre>
<p>We can also build the app with a specific locale:</p>
<pre><code class="lang-bash">ng build --configuration=production,nb
</code></pre>
<p>Or with all the locales at once:</p>
<pre><code class="lang-bash">ng build --prod --localize
</code></pre>
<p>In other words, it’s more flexible to configure it the way we did but we could also have just set <code>localize</code> and <code>aot</code> to true and be done with it.</p>
<h2 id="heading-run-multiple-languages-locally">Run multiple languages locally</h2>
<p>For performance reasons, running <code>ng serve</code> only supports one locale at a time. As we saw earlier we can serve the specific languages by sending in the locale to the <code>configuration</code> option. But, how can we run the application with all the configured languages?</p>
<h3 id="heading-multiple-languages">Multiple languages</h3>
<p>To run all languages simultaneously we need first to build the project. We can build applications with the locales defined in the build configuration with the <code>localize</code> option:</p>
<pre><code class="lang-bash">ng build --prod --localize
</code></pre>
<p>When the build is localized and ready we need to set up a local webserver to serve the applications. Remember we have one application per language, which is what makes this a bit more complex.</p>
<p>In <a target="_blank" href="https://angular.io/guide/i18n#configuring-servers">Angular Docs</a>, there are a couple of examples of server-side code that we can use.</p>
<h3 id="heading-nginx">Nginx</h3>
<p>To get our application up and running we need to:</p>
<ol>
<li><p>Install <a target="_blank" href="https://www.nginx.com/resources/wiki/start/">Nginx</a></p>
</li>
<li><p>Add config from <a target="_blank" href="https://angular.io/guide/i18n#nginx">Angular Docs</a> to <code>conf/nginx.conf</code></p>
</li>
<li><p>Build our applications</p>
</li>
<li><p>Copy applications to the folder defined in <code>root</code> in <code>nginx.conf</code>.</p>
</li>
<li><p>Open browser in <code>localhost</code></p>
</li>
</ol>
<p>The port is set in <code>listen</code> and is normally set to 80. You change languages by changing the URL. We should now see our Norwegian application at <code>localhost/nb</code>.</p>
<p>Here is an example of the <code>nginx.conf</code> file:</p>
<pre><code class="lang-nginx">events{}
<span class="hljs-section">http</span> {
  <span class="hljs-section">types</span> {
    module;
  }
  <span class="hljs-attribute">include</span> /etc/nginx/mime.types;

  <span class="hljs-comment"># Expires map for caching resources</span>
  <span class="hljs-attribute">map</span> <span class="hljs-variable">$sent_http_content_type</span> <span class="hljs-variable">$expires</span> {
    <span class="hljs-attribute">default</span>                    <span class="hljs-literal">off</span>;
    text/<span class="hljs-attribute">html</span>                  epoch;
    text/<span class="hljs-attribute">css</span>                   max;
    application/<span class="hljs-attribute">javascript</span>     max;
    ~image/                    max;
  }

  <span class="hljs-comment"># Browser preferred language detection</span>
  <span class="hljs-attribute">map</span> <span class="hljs-variable">$http_accept_language</span> <span class="hljs-variable">$accept_language</span> {
    ~*^<span class="hljs-attribute">en</span> en;
    ~*^<span class="hljs-attribute">nb</span> nb;
  }

  <span class="hljs-section">server</span> {
      <span class="hljs-attribute">listen</span>       <span class="hljs-number">80</span>;
    <span class="hljs-attribute">root</span>         /usr/share/nginx/html;

    <span class="hljs-comment"># Set cache expires from the map we defined.</span>
    <span class="hljs-attribute">expires</span> <span class="hljs-variable">$expires</span>;

    <span class="hljs-comment"># Security. Don't send nginx version in Server header.</span>
    <span class="hljs-attribute">server_tokens</span> <span class="hljs-literal">off</span>;

    <span class="hljs-comment"># Fallback to default language if no preference defined by browser</span>
    <span class="hljs-attribute">if</span> (<span class="hljs-variable">$accept_language</span> <span class="hljs-regexp">~ "^$")</span> {
      <span class="hljs-attribute">set</span> <span class="hljs-variable">$accept_language</span> <span class="hljs-string">"nb"</span>;
    }

    <span class="hljs-comment"># Redirect "/" to Angular app in browser's preferred language</span>
    <span class="hljs-attribute">rewrite</span><span class="hljs-regexp"> ^/$</span> /<span class="hljs-variable">$accept_language</span> <span class="hljs-literal">permanent</span>;

    <span class="hljs-comment"># Everything under the Angular app is always redirected to Angular in the correct language</span>
    <span class="hljs-attribute">location</span> <span class="hljs-regexp">~ ^/(en|nb)</span> {
      <span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> /<span class="hljs-variable">$1</span>/index.html?<span class="hljs-variable">$args</span>;

      <span class="hljs-comment"># Add security headers from separate file</span>
      <span class="hljs-attribute">include</span> /etc/nginx/security-headers.conf;
    }

    <span class="hljs-comment"># Proxy for APIs.</span>
    <span class="hljs-attribute">location</span> /api {
      <span class="hljs-attribute">proxy_pass</span> https://api.address.here;
    }
  }
}
</code></pre>
<p>If we use Nginx in production, it makes sense to also test our application locally with it.</p>
<h2 id="heading-deploy-to-production">Deploy to production</h2>
<p>If you are using Nginx in production, then you already have the language configuration setup. If not, you need to find out what changes you need for your particular server configuration.</p>
<p>We have to take into consideration if we are running the application locally or in production. We can do this by using <a target="_blank" href="https://angular.io/api/core/isDevMode"><code>isDevMode</code></a>, which returns whether Angular is in development mode:</p>
<pre><code class="lang-js">isDevMode() ? <span class="hljs-string">'/'</span> : <span class="hljs-string">`/<span class="hljs-subst">${locale}</span>/`</span>;
</code></pre>
<p>So, when we are running the application locally with <code>ng serve</code> we don’t add the locale to the URL as we do when we have localized the application in the production build.</p>
<h2 id="heading-maintaining-the-application">Maintaining the application</h2>
<p>Usually, when the application has been deployed it’s time to end the article. This time I wanted to address a few more things before ending. Let’s start by looking into what challenges we run into when going into maintenance mode.</p>
<p>The biggest challenge is the handling of the translation files. We need to make sure that the marked texts find their way to the translators and back to the application before it’s deployed. To help with this we need to find a way to <strong>automate</strong> the generation of translation files and get <strong>notified</strong> when we have missing translations.</p>
<h3 id="heading-generating-the-translation-files">Generating the translation files</h3>
<p>It’s not sustainable to keep merging the translation files manually. We need some automation! To implement this, I’m using a free tool called <a target="_blank" href="https://github.com/martinroob/ngx-i18nsupport/tree/master/projects/xliffmerge">Xliffmerge</a>.</p>
<blockquote>
<p>Since this tool has old Angular versions as <code>peerDependencies</code> we need to use <code>--legacy-peer-deps</code> if we are using a new version of NPM (v7) that would otherwise fail on installation.</p>
</blockquote>
<p>The documentation for Xliffmerge is targeting older versions of Angular, but after some experimentation, I found it enough to install the <code>@ngx-i18nsupport/tooling</code> package:</p>
<pre><code class="lang-bash">npm install -D @ngx-i18nsupport/tooling --legacy-peer-deps
</code></pre>
<p>Note that <code>-D</code> installs to <code>devDependencies</code>, and for use in a CI pipeline, you should omit it to use in <code>dependencies</code>.</p>
<p>Then we can add new languages to the configurations in <code>angular.json</code> under <code>projects -&amp;gt; projectName -&amp;gt; architect -&amp;gt; xliffmerge</code>.</p>
<pre><code class="lang-json"><span class="hljs-string">"xliffmerge"</span>: {
  <span class="hljs-attr">"builder"</span>: <span class="hljs-string">"@ngx-i18nsupport/tooling:xliffmerge"</span>,
  <span class="hljs-attr">"options"</span>: {
    <span class="hljs-attr">"xliffmergeOptions"</span>: {
      <span class="hljs-attr">"defaultLanguage"</span>: <span class="hljs-string">"en-US"</span>,
      <span class="hljs-attr">"languages"</span>: [<span class="hljs-string">"nb"</span>]
    }
  }
}
</code></pre>
<p>After adding new translations, we can extract them and migrate them to our translation files by running this script:</p>
<pre><code class="lang-bash">ng extract-i18n &amp;&amp; ng run projectName:xliffmerge
</code></pre>
<p>We get a couple of warnings running the script which tells us its working!</p>
<pre><code class="lang-plaintext">WARNING: merged 1 trans-units from master to "nb"
WARNING: please translate file "messages.nb.xlf" to target-language="nb"
</code></pre>
<p>After this, you can distribute the language files to the translators. And when the translations finish, the files need to be merged back into the project repository.</p>
<blockquote>
<p>Just a word of caution that this library was not being actively maintained at the time of this writing, so you might want to look into other options. There is an Angular <a target="_blank" href="https://github.com/angular/angular/issues/37655">issue on merging translated files</a>. Go and upvote it if you think this is something that we need!</p>
</blockquote>
<h3 id="heading-missing-translations">Missing Translations</h3>
<p>Another way to make sure the translations are valid is to get noticed if translations are missing. By default, the build succeeds but generates a warning of missing translations. We can configure the level of the warning generated by the Angular compiler:</p>
<ul>
<li><p><code>error</code>: An error message is displayed, and the build process is aborted.</p>
</li>
<li><p><code>warning</code> (default): Show a Missing translation warning in the console or shell.</p>
</li>
<li><p><code>ignore</code>: Do nothing.</p>
</li>
</ul>
<p>Specify the warning level in the options section for the build target of your Angular CLI configuration file, <code>angular.json</code>. The following example shows how to set the warning level to error:</p>
<pre><code class="lang-json"><span class="hljs-string">"options"</span>: {
  <span class="hljs-attr">"i18nMissingTranslation"</span>: <span class="hljs-string">"error"</span>
}
</code></pre>
<p>If you run the application and no translation is found, the application displays the source-language text. We have to make a decision here on how important the translations are. If they are crucial then we should break the build to make sure we get all translations delivered.</p>
<h2 id="heading-format-data-based-on-locale">Format data based on locale</h2>
<p>Languages are not the only thing to take into consideration when localizing applications. A couple of the more obvious things we need to think about is how we present dates and numbers to our local customers.</p>
<p>In Angular, we provide the <a target="_blank" href="https://angular.io/api/core/LOCALE_ID"><code>LOCALE_ID</code></a> token to set the locale of the application and register locale data with <a target="_blank" href="https://angular.io/api/common/registerLocaleData"><code>registerLocaleData()</code></a>. When we use the <code>--localize</code> option with <code>ng build</code> or run the <code>--configuration</code> flag with <code>ng serve</code>, the Angular CLI automatically includes the locale data and sets the <code>LOCALE_ID</code> value.</p>
<p>With the <code>LOCALE_ID</code> set to the correct locale, we can use the built-in <a target="_blank" href="https://angular.io/guide/glossary#pipe">pipes</a> of Angular to format our data. Angular provides the following pipes:</p>
<ul>
<li><p><a target="_blank" href="https://angular.io/api/common/DatePipe"><code>DatePipe</code></a>: Formats a date value.</p>
</li>
<li><p><a target="_blank" href="https://angular.io/api/common/CurrencyPipe"><code>CurrencyPipe</code></a>: Transforms a number to a currency string.</p>
</li>
<li><p><a target="_blank" href="https://angular.io/api/common/DecimalPipe"><code>DecimalPipe</code></a>: Transforms a number into a decimal number string.</p>
</li>
<li><p><a target="_blank" href="https://angular.io/api/common/PercentPipe"><code>PercentPipe</code></a>: Transforms a number to a percentage string.</p>
</li>
</ul>
<p>For example, <code>{{myDate | date}}</code> uses <code>DatePipe</code> to display the date in the correct format. We can also use the pipes in TypeScript files as long as we provide them to the module.</p>
<h2 id="heading-runtime-translations">Runtime translations</h2>
<p>When we run <code>ng serve --configuration=xx</code> or <code>ng build --localize</code> then the application is compiled and translated before we run it. However, if we don’t tell Angular to localize our application, then the <code>$localize</code> tags are left in the code, and it’s possible to instead do the translation at runtime.</p>
<p>This means that we can ship a single application and load the translations that we want to use before the application starts. There is a function <a target="_blank" href="https://angular.io/api/localize/loadTranslations"><code>loadTranslations</code></a> in <code>@angular/localize</code> that can be used to load translations, in the form of key/value pairs, before the application starts.</p>
<p>Since the translations have to be called before any module file is imported, we can put it in <code>polyfills.ts</code>. You could also use it in <code>main.ts</code> by using a dynamic <code>import(...)</code> for the module.</p>
<p>Here is an example of using <code>loadTranslations</code> in <code>polyfills.ts</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> <span class="hljs-string">'@angular/localize/init'</span>;
<span class="hljs-keyword">import</span> { loadTranslations } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/localize'</span>;

loadTranslations({
  <span class="hljs-string">'welcome'</span>: <span class="hljs-string">'Velkommen'</span>
});
</code></pre>
<p>Note that the outcome of this is effectively the same as translation at compile-time. The translation happens only once If you want to change the language at runtime then you must restart the whole application. Since <code>$localize</code> messages are only processed on the first encounter, they do not provide dynamic language changing without refreshing the browser.</p>
<p>The main benefit is allowing the project to deploy a single application with many translation files. The documentation on this part is still lacking, but hopefully, we get <a target="_blank" href="https://github.com/angular/angular/issues/37563">official documentation</a> on how to best work with <code>loadTranslations</code> and <code>$localize</code>. There are 3rd party libraries like <a target="_blank" href="https://github.com/soluling/I18N/tree/master/Library/Angular">Soluling</a> out there trying to bridge the gaps.</p>
<p>If a dynamic and runtime-friendly solution is what you are looking for, then you should use <a target="_blank" href="https://ngneat.github.io/transloco/">Transloco</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We started this article by looking into how the new Ivy engine changed the i18n and localizing of applications with Angular. We looked into what benefits and drawbacks this entails and if and when we should use alternative solutions.</p>
<p>We then looked into adding the built-in package to a solution and how we mark texts for translation. We learned how to configure the application for localization and added tooling to manage our translation files. When we used an editor for translating, we saw how adding context to translations helps.</p>
<p>Finally, after configuring and translating the application, we set up a web server to serve our application both locally and in production.</p>
<p>There are many parts to localizing an application and I hope that after reading this article, you have a better understanding of how you can create and manage multi-language applications with Angular.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><p><a target="_blank" href="https://angular.io/guide/i18n">Angular Docs</a></p>
</li>
<li><p><a target="_blank" href="https://blog.angular.io/angular-localization-with-ivy-4d8becefb6aa">Angular localization with Ivy</a> by <a target="_blank" href="https://medium.com/@petebd">Pete Bacon Darwin</a></p>
</li>
<li><p><a target="_blank" href="https://blog.ninja-squad.com/2019/12/10/angular-localize/">Internationalization with @angular/localize</a> by <a target="_blank" href="https://twitter.com/cedric_exbrayat">Cédric Exbrayat</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Save High Scores in Local Storage]]></title><description><![CDATA[After creating a game, it would be nice to save our best scores. If we only save the score in memory it will be gone the next time we play. Instead, we can save the scores in the browser’s local storage.
This article steps through how to save high sc...]]></description><link>https://blog.michaelkaren.dev/how-to-save-high-scores-in-local-storage-7860baca9d68</link><guid isPermaLink="true">https://blog.michaelkaren.dev/how-to-save-high-scores-in-local-storage-7860baca9d68</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[localstorage]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 11 Jan 2021 09:45:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075280966/Hc3wuf1J_.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After creating a game, it would be nice to save our best scores. If we only save the score in memory it will be gone the next time we play. Instead, we can save the scores in the browser’s local storage.</p>
<p>This article steps through how to save high scores in local storage and then how to present them on the screen for the player. If you want to read about the game that inspired this article you can read about it here:</p>
<ul>
<li><a target="_blank" href="https://medium.com/@michael.karen/learning-modern-javascript-with-tetris-92d532bcd057">Learning Modern JavaScript with Tetris</a></li>
</ul>
<h2 id="local-storage">Local storage</h2>
<p>With local storage, we can store data in the browser in the form of key-value pairs, where both the key and the value are strings. The data is persisted across browser sessions and its scope is limited to the origin where the script that accesses local storage resides.</p>
<p>Different browsers use different storages, so data is not shared between different browsers on the same computer — each browser has its unique storage.</p>
<p>The following snippets show how we can use localStorage:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Add data</span>
<span class="hljs-built_in">localStorage</span>.setItem(<span class="hljs-string">'myCar'</span>, <span class="hljs-string">'Tesla'</span>);

<span class="hljs-comment">// Read data</span>
<span class="hljs-keyword">const</span> car = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">'myCar'</span>);

<span class="hljs-comment">// Remove specific data</span>
<span class="hljs-built_in">localStorage</span>.removeItem(<span class="hljs-string">'myCar'</span>);

<span class="hljs-comment">// Remove all data</span>
<span class="hljs-built_in">localStorage</span>.clear();
</code></pre>
<p>With this knowledge, we can start implementing our solution.</p>
<h2 id="load-high-scores">Load high scores</h2>
<p>Let’s start by defining a couple of constants:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> NO_OF_HIGH_SCORES = <span class="hljs-number">10</span>;
<span class="hljs-keyword">const</span> HIGH_SCORES = <span class="hljs-string">'highScores'</span>;
</code></pre>
<p>Since we want to store an array we need to translate the array into a string before we save it and back to an array when getting it. For this, we can use the <em>JSON object</em> that contains methods for parsing JSON and converting values to JSON.</p>
<p>We can parse the string that we get from localStorage. If we don’t have any scores saved yet we can use the OR operator <code>||</code> to give a default value of empty array:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> highScoreString = <span class="hljs-built_in">localStorage</span>.getItem(HIGH_SCORES);
<span class="hljs-keyword">const</span> highScores = <span class="hljs-built_in">JSON</span>.parse(highScoreString) || [];
</code></pre>
<p>We now have the high scores parsed into an array. Next, we need to check if a score is good enough to make the high score list.</p>
<h2 id="check-for-a-high-score">Check for a high score</h2>
<p>To get the lowest score on the list we can take the score from the last position in the array with the help of our constant <code>NO_OF_HIGH_SCORES</code>. If we don’t have a full list yet we can use optional chaining with the Elvis operator (?) and return a zero:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lowestScore = highScores[NO_OF_HIGH_SCORES — <span class="hljs-number">1</span>]?.score ?? <span class="hljs-number">0</span>;
</code></pre>
<p>We have enough now to create a function <code>checkHighScore()</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkHighScore</span>(<span class="hljs-params">score</span>) </span>{
  <span class="hljs-keyword">const</span> highScores = <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">localStorage</span>.getItem(HIGH_SCORES)) || [];
  <span class="hljs-keyword">const</span> lowestScore = highScores[NO_OF_HIGH_SCORES - <span class="hljs-number">1</span>]?.score ?? <span class="hljs-number">0</span>;

  <span class="hljs-keyword">if</span> (score &gt; lowestScore) {
    saveHighScore(score, highScores); <span class="hljs-comment">// TODO</span>
    showHighScores(); <span class="hljs-comment">// TODO</span>
  }
}
</code></pre>
<p>And add it to the <code>gameOver()</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gameOver</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Other game over logic.</span>

  checkHighScore(account.score);
}
</code></pre>
<p>As you can see we have a couple of remaining functions marked with <em>TODO </em>that we need to take care of. If we have a score good enough to make the high score list we need to save it and refresh the list.</p>
<h2 id="save-high-score">Save high score</h2>
<p>Now, we need to save the scores when the game ends and the player gets a score that qualifies on the top list. In addition to the score we need a name so let’s ask for it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> name = prompt(‘You got a high score! Enter name:’);
</code></pre>
<p>When we have the name and the score we can create an object to save in the list:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> newScore = { score, name };
</code></pre>
<p>And when we have the new score that qualifies into the list we can:</p>
<ol>
<li>Add it to the list</li>
<li>Sort the list</li>
<li>Select the new high score list</li>
<li>Save it back to local storage</li>
</ol>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveHighScore</span>(<span class="hljs-params">score, highScores</span>) </span>{
  <span class="hljs-keyword">const</span> name = prompt(<span class="hljs-string">'You got a highscore! Enter name:'</span>);
  <span class="hljs-keyword">const</span> newScore = { score, name };

  <span class="hljs-comment">// 1. Add to list</span>
  highScores.push(newScore);

  <span class="hljs-comment">// 2. Sort the list</span>
  highScores.sort(<span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> b.score - a.score);

  <span class="hljs-comment">// 3. Select new list</span>
  highScores.splice(NO_OF_HIGH_SCORES);

  <span class="hljs-comment">// 4. Save to local storage</span>
  <span class="hljs-built_in">localStorage</span>.setItem(HIGH_SCORES, <span class="hljs-built_in">JSON</span>.stringify(highScores));
};
</code></pre>
<p>So, now that we have all this logic figured out we need to show the scores on the screen.</p>
<h2 id="show-high-scores">Show high scores</h2>
<p>To show the best scores we need an element in the HTML that we can hook into. Let’s add an ordered list element with the id set to <code>highScores</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>HIGH SCORES<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">ol</span> <span class="hljs-attr">id</span>=<span class="hljs-string">”highScores”</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
</code></pre>
<p>Now, we need to retrieve the high scores from localStorage and show them on the screen. We can do this by using the array method <em>map</em>. It lets us go through the array and add an HTML ordered list item to each score in the array.</p>
<pre><code class="lang-js">highScores.map(<span class="hljs-function">(<span class="hljs-params">score</span>) =&gt;</span> <span class="hljs-string">`&lt;li&gt;<span class="hljs-subst">${score.score}</span> — <span class="hljs-subst">${score.name}</span>`</span>);
</code></pre>
<p>We can then get the ordered list element and add the list items to its innerHTML:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> highScoreList = <span class="hljs-built_in">document</span>.getElementById(HIGH_SCORES);

highScoreList.innerHTML = highScores.map(<span class="hljs-function">(<span class="hljs-params">score</span>) =&gt;</span> 
  <span class="hljs-string">`&lt;li&gt;<span class="hljs-subst">${score.score}</span> - <span class="hljs-subst">${score.name}</span>`</span>
);
</code></pre>
<p>We can run this when we initialize the game and every time there is a new high score:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">showHighScores</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> highScores = <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">localStorage</span>.getItem(HIGH_SCORES)) || [];
  <span class="hljs-keyword">const</span> highScoreList = <span class="hljs-built_in">document</span>.getElementById(HIGH_SCORES);

  highScoreList.innerHTML = highScores
    .map(<span class="hljs-function">(<span class="hljs-params">score</span>) =&gt;</span> <span class="hljs-string">`&lt;li&gt;<span class="hljs-subst">${score.score}</span> - <span class="hljs-subst">${score.name}</span>`</span>)
    .join(<span class="hljs-string">''</span>);
}
</code></pre>
<p>Now, we have a functioning high score list!</p>
<h2 id="conclusion">Conclusion</h2>
<p>In this article, we added the functionality to persist our high scores in local storage. To help us format the data that we load and save from local storage, we used the JSON object. And to show it on the screen we added an HTML element as a hook to the DOM.</p>
<p>The next step to truly persist our high scores would be to add the high scores to a database. Maybe I will write about that next.</p>
<p>While I do, go play the game that inspired this article and make a high score:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/melcor76/js-tetris">https://github.com/melcor76/js-tetris</a></div>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Spread vs Rest]]></title><description><![CDATA[JavaScript version ES6 (ES2015) brought us a couple of useful features for arrays represented by three dots (…), the rest parameter, and the spread operator. And ES2018 introduced the same syntax for objects.
It can be confusing to have one syntax re...]]></description><link>https://blog.michaelkaren.dev/javascript-spread-vs-rest</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-spread-vs-rest</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Tue, 22 Sep 2020 12:42:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601035084563/JC0BP0JSf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript version ES6 (ES2015) brought us a couple of useful features for arrays represented by three dots (…), the <strong>rest parameter</strong>, and the <strong>spread operator</strong>. And ES2018 introduced the same syntax for objects.</p>
<p>It can be confusing to have one syntax represent two different uses. In this article, we will try to clear up the confusion and look into the two ways of using Javascript’s three dots.</p>
<p>In short we could say that:</p>
<ul>
<li><strong>spread operator</strong> unpacks elements.</li>
<li><strong>rest parameter</strong> packs elements.</li>
</ul>
<h2 id="definitions">Definitions</h2>
<ul>
<li><code>argument</code>— An argument is a value passed to a function.</li>
<li><code>parameter</code> — A Parameter is a variable used in the declaration of a function.</li>
<li><code>iterable</code>— A collection of something that we can <em>iterate</em> (loop) over. For example array, list, set, and string.</li>
</ul>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">print</span>(<span class="hljs-params">params</span>) </span>{
  params.forEach(<span class="hljs-function"><span class="hljs-params">param</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(param));
}

print([<span class="hljs-string">'arg1'</span>, <span class="hljs-string">'arg2'</span>]);
<span class="hljs-comment">// -&gt; arg1</span>
<span class="hljs-comment">// -&gt; arg2</span>
</code></pre>
<h1 id="spread-operator">Spread Operator</h1>
<p>The <em>spread operator</em> unpacks <em>iterables</em> into individual elements. Let’s look into different scenarios when this is useful.</p>
<h2 id="arrays">Arrays</h2>
<p>The spread operator unpacks an array into separate arguments:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> array = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];

<span class="hljs-built_in">console</span>.log(…array);
<span class="hljs-comment">// -&gt; 1 2 3</span>
</code></pre>
<p>This comes in handy when a function expects a list of arguments and all you have is an array:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> array = [<span class="hljs-number">4</span>, <span class="hljs-number">2</span>, <span class="hljs-number">9</span>, <span class="hljs-number">5</span>];

<span class="hljs-built_in">Math</span>.max(…array); <span class="hljs-comment">// -&gt; 9</span>
</code></pre>
<p>To <strong>copy</strong> an array we put the spread values into another array:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> arrayA = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> arrayB = [...arrayA];

<span class="hljs-built_in">console</span>.log(arrayB);
<span class="hljs-comment">// -&gt; [1, 2, 3]</span>
</code></pre>
<p>This is a great way of cloning arrays. If we do changes to either of the arrays they will not affect the other.</p>
<p>The spread syntax can also be used to compose several values into one:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> arrayA = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>];
<span class="hljs-keyword">const</span> arrayB = [<span class="hljs-number">0</span>, ...arrayA, <span class="hljs-number">4</span>];

<span class="hljs-built_in">console</span>.log(arrayB);
<span class="hljs-comment">// -&gt; [0, 1, 2, 3, 4]</span>
</code></pre>
<p>This is useful when we want to add elements into an existing array. We can even <strong>merge</strong> two arrays:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> first = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>];
<span class="hljs-keyword">const</span> other = [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>];

<span class="hljs-keyword">const</span> combo = [...first, ...other]; 
<span class="hljs-comment">// [1, 2, 3, 4]</span>
</code></pre>
<p>These operations are not only available for arrays but also other iterables like strings:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> word = <span class="hljs-string">'test'</span>;

<span class="hljs-built_in">console</span>.log([...word]);
<span class="hljs-comment">// -&gt; ["t", "e", "s", "t"]</span>
</code></pre>
<hr />
<h1 id="objects">Objects</h1>
<p>The spread operator (…) with objects is used to create copies of existing objects with new or updated values or to make a copy of an object with more properties. Let’s take an example of how to use the spread operator on an object.</p>
<p>Here we are spreading the <code>user</code> object. All key-value pairs are <strong>copied</strong> into the <code>clonedUser</code> object.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> user = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Max'</span>,
  <span class="hljs-attr">age</span>: <span class="hljs-number">42</span>
};

<span class="hljs-keyword">const</span> clonedUser = { ...user };
</code></pre>
<p>The spread syntax is useful for <strong>merging</strong> the properties and methods on objects into a new object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> x = { <span class="hljs-attr">x</span>: <span class="hljs-number">1</span> };
<span class="hljs-keyword">const</span> y = { <span class="hljs-attr">y</span>: <span class="hljs-number">2</span> };

<span class="hljs-keyword">const</span> coord = {...x, ...y};
<span class="hljs-built_in">console</span>.log(coord);
<span class="hljs-comment">// {x: 1, y: 2}</span>
</code></pre>
<p><strong>Note:</strong> Spread syntax only does a <strong>shallow copy</strong> meaning nested arrays or objects will not copy properly. The deeper data is still linked to the original.</p>
<h1 id="rest-parameter">Rest Parameter</h1>
<p>Where the <em>spread operator</em> unpacks the contents of an iterable into single elements, the <em>rest parameter</em> instead collects all the <strong>remaining</strong> elements into an <strong>array</strong>.</p>
<p>In JavaScript, it’s possible to call a function with any number of arguments.
We can use the <em>rest parameter</em> when we don’t know how many arguments will be used or just want to collect some of them into an array.</p>
<p>Let’s try an example where we add together all the values sent into our function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sum</span>(<span class="hljs-params">...args</span>) </span>{
  <span class="hljs-keyword">let</span> result = <span class="hljs-number">0</span>;

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> arg <span class="hljs-keyword">of</span> args) {
    result += arg;
  }

  <span class="hljs-keyword">return</span> result
}

sum(<span class="hljs-number">4</span>, <span class="hljs-number">2</span>) <span class="hljs-comment">// -&gt; 6</span>
sum(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>) <span class="hljs-comment">// -&gt; 18</span>
</code></pre>
<p>So, no matter how many numbers we send into the <code>sum</code> function they will be added together.</p>
<p>Let’s do another example:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">family</span>(<span class="hljs-params">spouse, …children</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Spouse: <span class="hljs-subst">${spouse}</span>`</span>);

  <span class="hljs-keyword">for</span>(<span class="hljs-keyword">const</span> child <span class="hljs-keyword">of</span> children) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Child: <span class="hljs-subst">${child}</span>`</span>);
  }
}

family(<span class="hljs-string">'Veronica'</span>, <span class="hljs-string">'Max'</span>, <span class="hljs-string">'Jack'</span>);
<span class="hljs-comment">// -&gt; Spouse: Veronica</span>
<span class="hljs-comment">// -&gt; Child: Max</span>
<span class="hljs-comment">// -&gt; Child: Jack</span>
</code></pre>
<p>As shown in the above example, the three dots collected all the elements after the <code>spouse</code> into the <code>children</code> array.</p>
<p>We can also use the rest syntax with objects together with <strong>destructuring</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> player = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Max Best'</span>,
  <span class="hljs-attr">age</span>: <span class="hljs-number">42</span>,
  <span class="hljs-attr">game</span>: <span class="hljs-string">'Football'</span>
}

<span class="hljs-keyword">const</span> { name, ...rest } = player;
<span class="hljs-built_in">console</span>.log(name); <span class="hljs-comment">// -&gt; Max Best</span>
<span class="hljs-built_in">console</span>.log(rest);
<span class="hljs-comment">// -&gt; {age: 42, game: 'Football'}</span>
</code></pre>
<p><strong>Note:</strong> Rest parameters have to be the last argument. This is because it collects all remaining arguments into an array.</p>
<h1 id="conclusion">Conclusion</h1>
<ul>
<li><strong>Rest Parameter</strong> collects all remaining elements into an array.</li>
<li><strong>Spread Operator</strong> expands collected elements such as arrays into single elements.</li>
<li>The spread syntax only does a <strong>shallow copy</strong> one level deep.</li>
<li>Only the <strong>last parameter</strong> can be a <em>rest parameter</em>.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Template Literals]]></title><description><![CDATA[Introduced in 2015 with ECMAScript6, template literals let us dynamically construct strings of text and embedded expressions, even multi-line strings of text, in a more elegant way than concatenation.
The syntax is not much different from the old one...]]></description><link>https://blog.michaelkaren.dev/javascript-template-literals</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-template-literals</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 14 Sep 2020 08:52:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601034046204/OIO4yUAvv.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Introduced in 2015 with ECMAScript6, <strong>template literals</strong> let us dynamically construct strings of text and <strong>embedded expressions</strong>, even <strong>multi-line</strong> strings of text, in a more elegant way than concatenation.</p>
<p>The syntax is not much different from the old one at first glance:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> newWay = <span class="hljs-string">`is cool`</span>;
</code></pre>
<p>Can you spot the difference? Instead of single <code>''</code> or double <code>""</code> quotes we use backticks <code>``.</code></p>
<h1 id="string-interpolation">String Interpolation</h1>
<p>In ES5 you had <strong>string concatenation</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> name = <span class="hljs-string">'Jack'</span>;
<span class="hljs-keyword">const</span> old = <span class="hljs-string">'My name is '</span>+ name + <span class="hljs-string">'.'</span>;
</code></pre>
<p>Using <code>+</code> for both addition and concatenation can be confusing and even lead to unexpected bugs:</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> a = <span class="hljs-number">4</span>;
<span class="hljs-keyword">var</span> b = <span class="hljs-number">2</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'a + b = '</span> + a + b);
<span class="hljs-comment">// -&gt; a + b = 42</span>
</code></pre>
<p>Template literals provide an easy way to interpolate variables and expressions into strings. The curly braces accept any valid JavaScript expression inside the <code>${}</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> name = <span class="hljs-string">'Jack'</span>;
<span class="hljs-keyword">const</span> str = <span class="hljs-string">`My name is <span class="hljs-subst">${name}</span>.`</span>;
<span class="hljs-built_in">console</span>.log(str);
<span class="hljs-comment">// -&gt; My name is Jack.</span>

<span class="hljs-keyword">const</span> a = <span class="hljs-number">4</span>;
<span class="hljs-keyword">const</span> b = <span class="hljs-number">2</span>;
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`a + b = <span class="hljs-subst">${a + b}</span>`</span>);
<span class="hljs-comment">// -&gt; a + b = 6</span>
</code></pre>
<hr />
<h1 id="multiline">Multiline</h1>
<p>In ES5 you had to use the newline character <code>\n</code> explicitly for line breaks and the <code>\</code> character at the end of a line to be able to write multi-line strings. This allows to create a string on two lines:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> concatenation = <span class="hljs-string">'First line\n \
second line'</span>;
</code></pre>
<p>Template literals make multi-line strings simpler. Once a template literal is opened with the <em>backtick</em>, you press enter to create a new line, with no special characters, and it’s rendered as-is:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> interpolation = <span class="hljs-string">`This
is more fun!

We can add expressions!
a + b = <span class="hljs-subst">${a + b}</span>`</span>
</code></pre>
<hr />
<h1 id="tagged-templates">Tagged Templates</h1>
<p>A not as known feature that comes along with template literals, is the ability to <strong>tag</strong> them. A <strong>tagged template</strong> is a function that allows you to parse <em>template literals</em>, which allows us to control the string creation.</p>
<p>The way the <em>tag template</em> works is that you put the name of the function that you want to run against the string before the template. So instead of <code>function()</code> you have <code>function`` </code>.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hi</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">'TODO'</span>;
}

<span class="hljs-keyword">const</span> name = <span class="hljs-string">'Jack'</span>;
<span class="hljs-keyword">const</span> tag = hi<span class="hljs-string">`My name is <span class="hljs-subst">${name}</span>.`</span>;
<span class="hljs-built_in">console</span>.log(tag);
<span class="hljs-comment">// -&gt; 'TODO'</span>
</code></pre>
<p>The tag template is equivalent to the following function call:</p>
<pre><code class="lang-js">hi([<span class="hljs-string">'My name is '</span>, <span class="hljs-string">'.'</span>], name);
</code></pre>
<p>First, we get an array of all the string pieces from our literal. After that, we get all the interpolated values. Here we only have one, the <code>name</code>.</p>
<p>So then we would need to change our function to accept these arguments and return the string as we like it:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hi</span>(<span class="hljs-params">strings, name</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-string">`Hello <span class="hljs-subst">${name}</span>!`</span>;
}

<span class="hljs-keyword">const</span> name = <span class="hljs-string">'Jack'</span>;
<span class="hljs-keyword">const</span> tag = hi<span class="hljs-string">`My name is <span class="hljs-subst">${name}</span>.`</span>
<span class="hljs-built_in">console</span>.log(tag);
<span class="hljs-comment">// -&gt; 'Hello Jack!'</span>
</code></pre>
<p>You can also alter the strings depending on the arguments, which is where the true power of tagged templates comes through.
There are popular libraries like <code>styled-components</code> and <code>lit-html</code> using tagged components.</p>
<h1 id="conclusion">Conclusion</h1>
<p>We have learned how template literals make strings easier to handle. They can take care of our variables and embedded expressions with ease. This is much more powerful than the old concatenation of strings and variables. And we also took a look into tagged templates and how they can let us manipulate the template literals before the browser exposes them to the world.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Proxy]]></title><description><![CDATA[JavaScript proxies were introduced in 2015 with ECMAScript 6. They allow us to intercept and override operations such as object property lookup and assignment. A Proxy object wraps another object and acts as a middleman.

Syntax
A proxy is created us...]]></description><link>https://blog.michaelkaren.dev/javascript-proxy</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-proxy</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Tue, 08 Sep 2020 08:51:42 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601032025732/E8f3A6sG6.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>JavaScript proxies were introduced in 2015 with ECMAScript 6. They allow us to <strong>intercept</strong> and <strong>override</strong> operations such as object property lookup and assignment. A <code>Proxy</code> object wraps another object and acts as a middleman.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1601032063441/DtWE_RD6Q.png" alt="proxy.png" /></p>
<h1 id="syntax">Syntax</h1>
<p>A proxy is created using the <code>new Proxy</code> constructor with two required arguments: the <strong>target</strong> and the <strong>handler</strong>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> proxy = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(target, handler)&lt;/span&gt;
</code></pre>
<ul>
<li><code>target</code> — The object we wrap.</li>
<li><code>handler</code> — An object that defines the methods (also called <strong>traps</strong>) to control the behaviors of the <em>target</em>.</li>
</ul>
<p>A <code>Proxy</code> creates an undetectable barrier around the target object that redirects all operations to the handler object. If we send in an empty <code>handler</code>, the proxy is just an empty wrapper around the original object.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> user = { 
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Max'</span>, 
  <span class="hljs-attr">age</span>: <span class="hljs-number">42</span>
};

<span class="hljs-keyword">let</span> proxyUser = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(user, {});

<span class="hljs-built_in">console</span>.log(user.name); <span class="hljs-comment">// -&gt; Max</span>
<span class="hljs-built_in">console</span>.log(proxyUser.name); <span class="hljs-comment">// -&gt; Max</span>
</code></pre>
<p>To give the proxy meaning, we need to add some functionality to the handler.</p>
<h1 id="traps">Traps</h1>
<p>Whenever you interact with an object, you are calling an internal method. Proxies allow you to intercept the execution of a given internal method with traps.</p>
<p>So when we run <code>user.name</code> we are telling the JavaScript engine to call the internal <code>[[GET]]</code> method to retrieve the <code>name</code> property.</p>
<p>When we run <code>proxyUser.name</code> the <strong>get trap</strong> calls the <code>get()</code> function defined in the <code>handler</code> to execute before sending the call through to the original object.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1601032501769/aPsFfmRBc.png" alt="proxyuser.png" /></p>
<h2 id="get">Get</h2>
<p>The <code>get()</code> method has two required parameters:</p>
<ul>
<li><code>target</code> — Object passed to the proxy.</li>
<li><code>property</code> — Name of the accessed property.</li>
</ul>
<p>To customize the proxy, we define functions on the <code>handler</code> object. Here we define the <code>get</code> method to log the access:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handler = {
  get(target, property) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`GET <span class="hljs-subst">${property}</span>`</span>);
    <span class="hljs-keyword">return</span> target[property];
  }
};
</code></pre>
<p>To let the call through, we return <code>target[property]</code>.</p>
<p>Now, if we create a proxy with this handler and try to access the original object, we log the call:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> proxyUser = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(user, handler);

<span class="hljs-built_in">console</span>.log(proxyUser.age);
<span class="hljs-comment">// -&gt; GET age</span>
<span class="hljs-comment">// -&gt; 42</span>
</code></pre>
<p>We can see that when we access a property of the <code>user</code> object via the <code>proxyUser</code> object, the <code>get()</code> method fires in the <code>handler</code> object.</p>
<h2 id="set">Set</h2>
<p>The <strong>set trap</strong> controls behavior when a property of the <code>target</code> object is assigned.</p>
<p>Let’s validate the input of the <code>age</code> value:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handler = {
  set(target, property, value) {
    <span class="hljs-keyword">if</span>(property === <span class="hljs-string">'age'</span> &amp;&amp; <span class="hljs-keyword">typeof</span>(value) !== <span class="hljs-string">'number'</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">'Age is just a number.'</span>);
    }

    target[property] = value;
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>If we try to assign a wrong type to <code>age</code> an error is thrown:</p>
<pre><code class="lang-js">proxyUser.age = <span class="hljs-string">'old'</span>;
<span class="hljs-comment">// -&gt; TypeError: Age is just a number.</span>
</code></pre>
<p>In the line <code>target[property] = value</code> we set the <code>age</code> property of the <code>user</code> object.</p>
<p>The <code>set()</code> method should return a boolean value <code>true</code> to indicate that the assignment succeeded. If the JavaScript is run in <em>strict mode</em>, and a <em>falsy</em> value or nothing is returned, an error will be thrown.</p>
<pre><code class="lang-js">Uncaught <span class="hljs-built_in">TypeError</span>: ‘set’ on proxy: trap returned falsish <span class="hljs-keyword">for</span> property <span class="hljs-string">'age'</span>
</code></pre>
<blockquote>
<p>In addition to intercepting reads and modifications to properties, Proxy can intercept a total of 13 operations.</p>
</blockquote>
<h1 id="conclusion">Conclusion</h1>
<p>We have learned how we can use a proxy to spy on objects. You should now be able to add behaviors to them by using trap methods in the handler object. We have only dipped our toes into proxies with a couple of basic examples but it’s enough to get started and inspired to explore the possibilities!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Destructuring]]></title><description><![CDATA[The two most used data structures in JavaScript are Object and Array. The destructuring assignment introduced in ECMAScript 2015 is a shorthand syntax that allows us to extract array values or object properties into variables. In this article, we go ...]]></description><link>https://blog.michaelkaren.dev/javascript-destructuring</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-destructuring</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Thu, 03 Sep 2020 17:58:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601026085329/_yzo74_xY.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The two most used data structures in JavaScript are <code>Object</code> and <code>Array</code>. The <strong>destructuring assignment</strong> introduced in ECMAScript 2015 is a shorthand syntax that allows us to extract array values or object properties into variables. In this article, we go through the syntax of both data structures and give examples when you can use them.</p>
<h1 id="destructuring-arrays">Destructuring Arrays</h1>
<p>In ES5 you could access items in an array by index:</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> fruit = [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'banana'</span>, <span class="hljs-string">'kiwi'</span>];

<span class="hljs-keyword">var</span> apple = fruit[<span class="hljs-number">0</span>];
<span class="hljs-keyword">var</span> banana = fruit[<span class="hljs-number">1</span>];
<span class="hljs-keyword">var</span> kiwi = fruit[<span class="hljs-number">2</span>];
</code></pre>
<p>With ES6 destructuring, the code becomes simpler:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [apple, banana, kiwi] = fruit;
</code></pre>
<p>Sometimes you might want to skip over items in the array being destructured:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [,,kiwi] = [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'banana'</span>, <span class="hljs-string">'kiwi'</span>];
</code></pre>
<p>Or you can save the other items in an array with the <strong>rest</strong> pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [apple, …rest] = [<span class="hljs-string">'apple'</span>, <span class="hljs-string">'banana'</span>, <span class="hljs-string">'kiwi'</span>];

<span class="hljs-built_in">console</span>.log(rest); <span class="hljs-comment">// -&gt; ['banana', 'kiwi']</span>
</code></pre>
<blockquote>
<p>Note that the destructuring assignment pattern works for any iterable.</p>
</blockquote>
<h1 id="destructuring-objects">Destructuring Objects</h1>
<p><strong>Object destructuring</strong> lets you extract properties from objects and bind them to variables. Instead of accessing <code>width</code> through <code>rectangle.width</code> we can access the property and assign it to a variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> rectangle = { <span class="hljs-attr">width</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">8</span> };

<span class="hljs-keyword">const</span> { width } = rectangle;
</code></pre>
<p>What’s even better, <em>object destructuring</em> can extract multiple properties in one statement. This makes the code clearer. The order of the properties does not matter.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { width, height } = rectangle;
</code></pre>
<p>If we want to change the name of the property we can do it using a colon:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { <span class="hljs-attr">width</span>: w, <span class="hljs-attr">height</span>: h } = rectangle;

<span class="hljs-built_in">console</span>.log(w); <span class="hljs-comment">// -&gt; 5</span>
</code></pre>
<p>Here we assign the property <code>width</code> from <code>rectangle</code> to a variable named <code>w</code>.</p>
<h1 id="default-values">Default Values</h1>
<p>When you destructure on properties that are not defined, you get <code>undefined</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { password } = {};

<span class="hljs-built_in">console</span>.log(password); <span class="hljs-comment">// -&gt; undefined</span>
</code></pre>
<p>You can provide default values for when the property you are destructuring is not defined:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [favorite = <span class="hljs-string">'apple'</span>] = [];
<span class="hljs-built_in">console</span>.log(favorite); <span class="hljs-comment">// -&gt; apple</span>

<span class="hljs-keyword">const</span> { width = <span class="hljs-number">100</span> } = {};
<span class="hljs-built_in">console</span>.log(width); <span class="hljs-comment">// -&gt; 100</span>
</code></pre>
<h1 id="examples">Examples</h1>
<p>There are many places where we can use destructuring to make the code terser. Let’s see some examples!</p>
<h2 id="string-manipulation">String Manipulation</h2>
<p>We could for example do some string manipulation on a name and directly assign to variables <code>firstName</code> and <code>lastName</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [firstName, lastName] = <span class="hljs-string">'Max Best'</span>.split(<span class="hljs-string">' '</span>);

<span class="hljs-comment">// firstName = 'Max', lastName = 'Best'</span>
</code></pre>
<h2 id="swapping-variable-values">Swapping Variable Values</h2>
<p>Let’s first do the ES5 swap:</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> me = <span class="hljs-string">'happy'</span>, you = <span class="hljs-string">'sad'</span>;

<span class="hljs-keyword">var</span> temp = me;
me = you;
you = temp;

<span class="hljs-comment">// me = 'sad', you = 'happy'</span>
</code></pre>
<p>And now let’s swap back with ES6 destructuring:</p>
<pre><code class="lang-js">[me, you] = [you, me];

<span class="hljs-comment">// me = 'happy', you = 'sad'</span>
</code></pre>
<p>No more need for temporary variables!</p>
<h2 id="function-parameter-objects">Function Parameter Objects</h2>
<p>When you are passing multiple parameters it often makes sense to do it as an object. We can use <em>destructuring</em> whenever we want to unpack its properties:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateArea</span>(<span class="hljs-params">{ width, height }</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Area is '</span> + width * height);
}

calculateArea({ <span class="hljs-attr">width</span>: <span class="hljs-number">5</span>, <span class="hljs-attr">height</span>: <span class="hljs-number">6</span> }); 
<span class="hljs-comment">// -&gt; Area is 30</span>
</code></pre>
<p>We can also set default values and change variable names:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">calculateArea</span>(<span class="hljs-params">{ width: w = <span class="hljs-number">10</span>, height: h = <span class="hljs-number">5</span> }</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Area is '</span> + w * h);
}

calculateArea({ <span class="hljs-attr">height</span>: <span class="hljs-number">6</span> });
<span class="hljs-comment">// -&gt; Area is 60</span>
</code></pre>
<h2 id="multiple-return-values">Multiple Return Values</h2>
<p>If you need to return multiple values from a function you can return an array or object and destructure the result:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">returnWidthAndHeight</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> [<span class="hljs-number">5</span>, <span class="hljs-number">10</span>];
}

<span class="hljs-keyword">const</span> [width, height] = returnWidthAndHeight();
<span class="hljs-comment">// width = 5, height = 10</span>
</code></pre>
<hr />
<h1 id="conclusion">Conclusion</h1>
<p>Destructuring is a JavaScript expression that allows us to extract data from arrays and objects. In this article, we have explored the syntax and various ways we can use it in our code. Destructuring of arrays and objects is something that will make your code a bit shorter and cleaner all over the place.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Arrow Functions]]></title><description><![CDATA[One of the most popular new features in ECMAScript 2015 is arrow functions. Is it because of the new cleaner syntax or the sharing of this with the parent scope? Maybe both. Let’s look into them in more detail.
Syntax
The first factor that influenced...]]></description><link>https://blog.michaelkaren.dev/javascript-arrow-functions</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-arrow-functions</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Wed, 02 Sep 2020 12:30:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601024860698/JXtBiTT9V.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One of the most popular new features in ECMAScript 2015 is <strong>arrow functions</strong>. Is it because of the new <strong>cleaner syntax</strong> or the sharing of <strong>this</strong> with the parent scope? Maybe both. Let’s look into them in more detail.</p>
<h1 id="syntax">Syntax</h1>
<p>The first factor that influenced the introduction of arrow functions was a shorter function syntax. The syntax can look a bit different depending on the function. Let’s see some options!</p>
<p>Here is a function written in ES5 syntax:</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> sum = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>) </span>{
  <span class="hljs-keyword">return</span> a + b;
}

sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>) <span class="hljs-comment">// -&gt; 3</span>
</code></pre>
<p>And here is the same function as an arrow function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> sum = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> a + b;

sum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>) <span class="hljs-comment">// -&gt; 3</span>
</code></pre>
<p>As we can see the arrow function makes the code much more concise when we have one-line expressions. Due to implicit return we can omit the <strong>curly braces</strong> and <code>return</code> keyword.</p>
<p>If we have multiple lines in the function we always have to use the <em>curly braces</em> and <code>return</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> printSum = <span class="hljs-function">(<span class="hljs-params">a, b</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> result = a + b;
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Answer: '</span> + result);

  <span class="hljs-keyword">return</span> result;
}

<span class="hljs-keyword">const</span> sum = printSum(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>); 
<span class="hljs-comment">// -&gt; Answer: 3</span>
</code></pre>
<p>Parentheses are optional when only one parameter is present:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> square = <span class="hljs-function"><span class="hljs-params">n</span> =&gt;</span> n * n;

square(<span class="hljs-number">3</span>); <span class="hljs-comment">// -&gt; 9</span>
</code></pre>
<blockquote>
<p>Arrow functions are sometimes called <strong>fat arrow functions</strong>, because of the token <code>=&gt;</code> that resembles a fat arrow.</p>
</blockquote>
<p>A common use case for arrow functions is when using array methods. Here we create a new array with the ages of the players by mapping through the player array:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> players = [
  { <span class="hljs-attr">name</span>:<span class="hljs-string">'Michael'</span>, <span class="hljs-attr">age</span>:<span class="hljs-number">44</span>},
  { <span class="hljs-attr">name</span>:<span class="hljs-string">'Karl'</span>, <span class="hljs-attr">age</span>:<span class="hljs-number">33</span>},
  { <span class="hljs-attr">name</span>:<span class="hljs-string">'Lisa'</span>, <span class="hljs-attr">age</span>:<span class="hljs-number">37</span>}
];

<span class="hljs-keyword">const</span> ages = players.map(<span class="hljs-function"><span class="hljs-params">player</span> =&gt;</span> player.age); 
<span class="hljs-comment">// [44, 33, 37]</span>
</code></pre>
<p>Array functions really shine here!</p>
<hr />
<h1 id="this">This</h1>
<p>We have seen how nice the new syntax can be but there is a another better reason to use arrow functions. And that is the sometimes confusing behavior of the <code>this</code> keyword in JavaScript. It doesn’t depend on where it’s declared but on how and where the function is called, the <strong>execution context</strong>.</p>
<blockquote>
<p>In the global scope, value of <code>this</code> is always the <code>window</code> object.</p>
</blockquote>
<h2 id="regular-functions">Regular Functions</h2>
<p>Functions have their own <em>execution context</em> and with it comes their own <code>this</code>. Understanding these concepts is not easy but they are important.</p>
<p>Some example code can hopefully make it clearer. To show the difference we use <code>setTimeout</code>, a native JavaScript function which calls a function after a set delay in milliseconds.</p>
<pre><code class="lang-js"><span class="hljs-comment">// ES5</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Age</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">this</span>.age = <span class="hljs-number">42</span>;
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.age); <span class="hljs-comment">// -&gt; undefined</span>
  }, <span class="hljs-number">1000</span>);
}

<span class="hljs-keyword">var</span> a = <span class="hljs-keyword">new</span> Age();
</code></pre>
<p>If we run this code we get <code>undefined</code> logged to the console because the function inside <code>setTimeout</code> has its own <em>execution context</em>. So we are not accessing <code>this.age</code> of the <code>Age</code> function but of the one inside the function where we make the call. And that hasn’t assigned a value to <code>age</code>.</p>
<p>To access the context of the parent function developers often reassign <code>this</code> of the outer function to a variable commonly named <code>that</code> or <code>self</code>.</p>
<pre><code class="lang-js"><span class="hljs-comment">// ES5</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Age</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> that = <span class="hljs-built_in">this</span>;
  that.age = <span class="hljs-number">42</span>;
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(that.age); <span class="hljs-comment">// -&gt; 42</span>
  }, <span class="hljs-number">1000</span>);
}

<span class="hljs-keyword">var</span> a = <span class="hljs-keyword">new</span> Age();
</code></pre>
<p>In this way we can access the <code>this</code> of the parent function but you can see how it can be confusing.</p>
<blockquote>
<p>Another option is to use <code>function{}.bind(this)</code>.</p>
</blockquote>
<h2 id="arrow-functions">Arrow Functions</h2>
<p>Arrow functions however share the <strong>lexical scope</strong> with their parent. This means that it uses <code>this</code> from the code that contains the arrow function.</p>
<pre><code class="lang-js"><span class="hljs-comment">// ES6</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Age</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">this</span>.age = <span class="hljs-number">42</span>;
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">this</span>.age); <span class="hljs-comment">// -&gt; 42</span>
  }, <span class="hljs-number">1000</span>);
}

<span class="hljs-keyword">const</span> a = <span class="hljs-keyword">new</span> Age();
</code></pre>
<p>So, we can see how arrow functions help to make the code cleaner and easier to read.</p>
<hr />
<h1 id="should-we-always-use-arrow-functions">Should we always use Arrow Functions?</h1>
<p>Arrow functions are great but there is still use for regular functions. Let’s see some examples when we should not use arrow functions.</p>
<h2 id="methods">Methods</h2>
<p>Arrow functions are best suited for non-method functions. Let’s see what happens when we try to use them as methods. In this example, we create an object <code>blog</code> with a method <code>like</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blog = {
  <span class="hljs-attr">likes</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">like</span>: <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.likes++;
  }
}
</code></pre>
<p>One would think that every time we call <code>blog.like()</code> the attribute <code>blog.likes</code> increases by one. However, sadly the value of likes will remain at zero.</p>
<p>This time the parent scope is the window object and not the blog object. So invoking the method <code>like()</code> would attempt to increment the property <code>likes</code> on the window object.</p>
<p>If instead, we use the traditional syntax it will work as expected:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blog = {
  <span class="hljs-attr">likes</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">like</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">this</span>.likes++;
  }
}
</code></pre>
<p>Even better, another new feature in ES6 is <strong>shorthand method syntax</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blog = {
  <span class="hljs-attr">likes</span>: <span class="hljs-number">0</span>,
  like() {
    <span class="hljs-built_in">this</span>.likes++;
  }
}
</code></pre>
<p>Notice here that we can omit the <code>function</code> keyword and colon.</p>
<h2 id="constructor">Constructor</h2>
<p>An arrow function cannot be used as a constructor. It will throw an error when used with <code>new</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> PrintDouble = <span class="hljs-function">(<span class="hljs-params">x</span>) =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-number">2</span> * x);

<span class="hljs-keyword">new</span> PrintDouble(<span class="hljs-number">2</span>);
<span class="hljs-comment">// -&gt; TypeError: PrintDouble is not a constructor</span>
</code></pre>
<p>We can instead use a function expression:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> PrintDouble = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">x</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-number">2</span> * x);
};

<span class="hljs-keyword">new</span> PrintDouble (<span class="hljs-number">2</span>); <span class="hljs-comment">// -&gt; 4</span>
</code></pre>
<h1 id="conclusion">Conclusion</h1>
<p>Arrow functions are a great new addition ES6 that brings us a syntactically compact alternative to a regular function. An arrow function does not have its own this. The this value of the enclosing lexical scope is used. Arrow functions are ill suited as methods, and they cannot be used as constructors.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Classes]]></title><description><![CDATA[We often need to create many objects of the same kind, like users or cars. In object-oriented languages, a class is often used for this purpose.
JavaScript, being a prototype-based language, has something called constructor functions.
// ES5 construc...]]></description><link>https://blog.michaelkaren.dev/javascript-classes</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-classes</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Thu, 27 Aug 2020 08:42:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1601023360235/0ynZ6Rt2I.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We often need to create many objects of the same kind, like users or cars. In object-oriented languages, a class is often used for this purpose.
JavaScript, being a prototype-based language, has something called <strong>constructor functions</strong>.</p>
<pre><code class="lang-js"><span class="hljs-comment">// ES5 constructor function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Car</span>(<span class="hljs-params">brand</span>) </span>{
  <span class="hljs-built_in">this</span>.brand = brand;
}

<span class="hljs-comment">// Adding a method to the prototype</span>
Car.prototype.getBrand = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.brand;
}
</code></pre>
<p>Classes, introduced with ES6 provide “syntactical sugar”, that is comparable to inheritance in object-oriented languages. Classes are special functions meant to mimic the <code>class</code> keyword from these other languages. In this article we go through how to use JavaScript classes.</p>
<h1 id="defining-a-class">Defining a Class</h1>
<p>To define a class we use the <code>class</code> keyword followed by the name of the class. The body of a class is the part that is in curly braces <code>{}</code>:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-comment">// Body of the class</span>
}
</code></pre>
<p>The code above defines a class Car. This syntax is named <strong>class declaration</strong>.</p>
<p>The <code>new</code> operator instantiates the class:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myCar = <span class="hljs-keyword">new</span> Car();
</code></pre>
<p>This is how we create a new object, an <strong>instance</strong>, of the Car class.</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">typeof</span> Car); <span class="hljs-comment">// -&gt; function</span>
</code></pre>
<p>And as you can see, in JavaScript, a class is a kind of function.</p>
<p>We don’t need to give the class a name. By using a <strong>class expression</strong> you can assign the class to a variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Car = <span class="hljs-class"><span class="hljs-keyword">class</span> </span>{} <span class="hljs-comment">// unnamed</span>
<span class="hljs-keyword">const</span> Car = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{} <span class="hljs-comment">// named</span>
</code></pre>
<p><em>Class expressions</em> can be named or unnamed. The name given to a named class expression is local to the class’s body.</p>
<h2 id="hoisting">Hoisting</h2>
<p>An important difference between function declarations and class declarations is that function declarations are <strong>hoisted</strong> and class declarations are not. Therefore you need to first declare the class before you can initialize objects with the <code>new</code> keyword.</p>
<blockquote>
<p>Conceptually, for example, a strict definition of hoisting suggests that variable and function declarations are physically moved to the top of your code, but this is not in fact what happens. Instead, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code. — MDN</p>
</blockquote>
<p>As you might remember variables declared with <code>var</code> are also <em>hoisted</em>. So, keeping with the “modern” way it makes then sense that <em>classes</em> just like <em>variables</em> declared with <code>let</code> or <code>const</code> are not <em>hoisted</em>.</p>
<h1 id="initialization">Initialization</h1>
<p>Classes in JavaScript have a special method called <strong>constructor</strong> that lets us set initial values for fields when the object is initialized. There can be only one <em>constructor method</em>.</p>
<p>Let’s create a Car class with a constructor that sets the initial value of the field <code>brand</code>:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-keyword">constructor</span>(brand) {
    <span class="hljs-built_in">this</span>.brand = brand; 
  } 
}
</code></pre>
<p>The expression <code>this.brand = brand</code> creates a <strong>public field</strong> <code>brand</code> and assigns it an initial value. We can now create a new car object and access it’s <em>brand property</em>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> car = <span class="hljs-keyword">new</span> Car(<span class="hljs-string">'Volvo'</span>);
<span class="hljs-built_in">console</span>.log(car.brand); <span class="hljs-comment">// -&gt; Volvo</span>
</code></pre>
<p>As you can see we can now access the <code>brand</code> field using a <strong>property accessor</strong>. There’s no restriction on the access of the public fields. You can read and modify the values of public fields inside the constructor, methods, and outside of the class.</p>
<blockquote>
<p>The bodies of class declarations and class expressions are executed in <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>.</p>
</blockquote>
<hr />
<h1 id="methods">Methods</h1>
<p>Classes provide a cleaner and more elegant syntax for adding methods.</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{ 
  <span class="hljs-keyword">constructor</span>(brand) {
    <span class="hljs-built_in">this</span>.brand = brand;
  } 

  getBrand() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.brand;
  }
}
</code></pre>
<p>The keyword <code>this</code> allows us to access instance data inside the constructor and methods.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> car = <span class="hljs-keyword">new</span> Car(<span class="hljs-string">'Tesla'</span>);
<span class="hljs-built_in">console</span>.log(car.getBrand()); <span class="hljs-comment">// -&gt; Tesla</span>
</code></pre>
<p>The method invocation <code>car.getBrand()</code> executes the methods inside the Car class and returns the brand property.</p>
<h2 id="static-methods">Static Methods</h2>
<p>We can also assign a method to the class function itself, not to its <em>prototype</em>. Such methods are called <strong>static</strong> and are prepended with the <code>static</code> keyword:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Double</span> </span>{
  <span class="hljs-keyword">static</span> double(n) {
    <span class="hljs-keyword">return</span> n * <span class="hljs-number">2</span>;
  }
}

Double.double(<span class="hljs-number">2</span>); <span class="hljs-comment">// -&gt; 4</span>
</code></pre>
<p>We don’t have to create an instance of the class but can call the method directly on the class itself. Static methods are often used in utility classes for making computations.</p>
<h2 id="getters-and-setters">Getters and Setters</h2>
<p>JavaScript classes can have getter and setter functions.</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{ 
  <span class="hljs-keyword">constructor</span>(brand) {
    <span class="hljs-built_in">this</span>._brand = brand;
  }

  <span class="hljs-keyword">get</span> <span class="hljs-title">brand</span>() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>._brand;
  }

  <span class="hljs-keyword">set</span> <span class="hljs-title">brand</span>(<span class="hljs-params">value</span>) {
    <span class="hljs-built_in">this</span>._brand = value;
  }
}
</code></pre>
<p>Notice that if you would do <code>this.brand = value</code> in the setter we would be calling the setter again and go into an infinite loop. Using an underscore <code>_</code> is a common convention.</p>
<p>With this we can create an instance of the class and access the brand property through the setter and getter:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> car = <span class="hljs-keyword">new</span> Car(<span class="hljs-string">''</span>);
car.brand = <span class="hljs-string">'Tesla;
console.log(car.brand); // -&gt; Tesla</span>
</code></pre>
<h1 id="inheritance">Inheritance</h1>
<p>Class inheritance is a way to inherit the functionality of another class and extend it. We create a child class with the <code>extends</code> keyword.</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SportsCar</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Car</span> </span>{
  isFast() {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>Now we can use the functionality of the class we extended:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> car = <span class="hljs-keyword">new</span> SportsCar(<span class="hljs-string">'Mazda'</span>);
<span class="hljs-built_in">console</span>.log(car.brand); <span class="hljs-comment">// -&gt; Mazda</span>
<span class="hljs-built_in">console</span>.log(car.isFast()); <span class="hljs-comment">// -&gt; true</span>
</code></pre>
<p>You can see here that we didn’t have to create a constructor. If a class extends another class and has no constructor, then the following constructor is generated:</p>
<pre><code class="lang-js"><span class="hljs-keyword">constructor</span>(...args) {
  <span class="hljs-built_in">super</span>(...args); <span class="hljs-comment">// Copying args with spread operator (...)</span>
}
</code></pre>
<p>The <code>super</code> keyword is used to call corresponding methods of the parent class. So the constructor calls the parent constructor passing it all the arguments. If we want to add another in-parameter to our class we can create a constructor:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SportsCar</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-keyword">constructor</span>(brand, model) {
    <span class="hljs-built_in">super</span>(brand);
    <span class="hljs-built_in">this</span>.model = model;
  }
}

<span class="hljs-keyword">const</span> myCar = <span class="hljs-keyword">new</span> SportsCar(<span class="hljs-string">'Mazda'</span>, <span class="hljs-string">'MX-5'</span>);
</code></pre>
<p>Note that constructors in inheriting classes must call <code>super()</code>, and do it before using <code>this</code>.</p>
<h1 id="conclusion">Conclusion</h1>
<ul>
<li>Use classes when you need to create <strong>multiple objects</strong> of the same kind.</li>
<li>Classes are a special kind of functions that run in <strong>strict mode</strong> and are <strong>not hoisted</strong>.</li>
<li>Classes can have fields and methods that we can access from a class instance.</li>
<li>We can inherit functionality from other classes by <strong>extending</strong> them.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Getting Started with Modern JavaScript — Variables and Scope]]></title><description><![CDATA[In this article, we introduce variables and scope in JavaScript.
Variables
A variable is a named container with a unique name for storing data values. The statement below declares a variable with the name “car”:
let car;

console.log(car); // undefin...]]></description><link>https://blog.michaelkaren.dev/javascript-variables-and-scope</link><guid isPermaLink="true">https://blog.michaelkaren.dev/javascript-variables-and-scope</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Tue, 25 Aug 2020 12:39:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1600864727175/JX-FhmCW8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, we introduce variables and scope in JavaScript.</p>
<h1 id="variables">Variables</h1>
<p>A variable is a named container with a unique name for storing data values. The statement below <strong>declares</strong> a variable with the name “car”:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> car;

<span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// undefined</span>
</code></pre>
<p>In JavaScript, variables are <strong>initialized</strong> with the value of <code>undefined</code> when they are created. You can assign a value to a variable using the assignment operator (=) when you declare it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> car = <span class="hljs-string">'Volvo'</span>;

<span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// Volvo</span>
</code></pre>
<p>Always initialize your variables before using them or you will get an error:</p>
<pre><code class="lang-js"><span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// ReferenceError: car is not defined</span>

<span class="hljs-keyword">const</span> car = <span class="hljs-string">"Toyota"</span>;
</code></pre>
<p>ECMAScript 2015 (or ES6) introduced two new ways of declaring variables, <strong>let</strong> and <strong>const</strong>. The reason for the new keywords was because the <strong>function scoping</strong> of <code>var</code> is confusing. It was one of the main sources of bugs in JavaScript.</p>
<h1 id="scope">Scope</h1>
<p>By scope, we are talking about the visibility of variables in the different parts of the code during runtime. Or in other words which parts of the code can access and modify a variable.</p>
<p>In JavaScript there are two types of scope:</p>
<ul>
<li>Global scope</li>
<li>Local scope</li>
</ul>
<p>What changed with Modern JavaScript (ES6+) is the way we use variables in the local scope.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1600864549731/CPpg9u2gi.png" alt="js-scopes.png" /></p>
<h1 id="global-scope">Global Scope</h1>
<p>A variable declared outside a function becomes global. This means it can be accessed and modified everywhere in the code.</p>
<p>We can declare constants in the global scope:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> COLS = <span class="hljs-number">10</span>;
<span class="hljs-keyword">const</span> ROWS = <span class="hljs-number">20</span>;&lt;/span&gt;
</code></pre>
<p>We can then access them from all parts of our code.</p>
<h1 id="local-scope">Local Scope</h1>
<p>Variables declared in a local scope can not be accessed from outside that scope. The same variable name can be used in different scopes because they are bound to their respective scopes.</p>
<p>Local scope differs depending on the variable declaration used.</p>
<h2 id="function-scope">Function Scope</h2>
<p>Variables declared with the <code>var</code> keyword become local to the function. They can be accessed from within the function.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printCar</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span>(<span class="hljs-literal">true</span>) {
    <span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// undefined</span>
    <span class="hljs-keyword">var</span> car = <span class="hljs-string">"Porsche"</span>;
    <span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// "Porsche" </span>
  }
  <span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// "Porsche"</span>
}

printCar();
<span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// ReferenceError</span>
</code></pre>
<p>We can see that we don’t get an error even though we access <code>car</code> before the declaration. Variables declared with the <code>var</code> keyword are <strong>hoisted</strong> — moved to the top of the function and initialized with <code>undefined</code> before the code is run. With the <em>hoisting,</em> they are accessible in their enclosing scope even before they are declared.</p>
<p>Can you see how this can get confusing?</p>
<h2 id="block-scope">Block Scope</h2>
<p>The concept of <strong>block scope</strong> was introduced in ES6 together with the new ways to declare variables — <code>const</code> and <code>let</code>. This means that the variable is accessible between two curly braces <code>{}</code>. For example inside an <code>if</code> or <code>for</code>.</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">printCar</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">if</span>(<span class="hljs-literal">true</span>) {
    <span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// ReferenceError</span>
    <span class="hljs-keyword">const</span> car = <span class="hljs-string">"Fiat"</span>;
    <span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// "Fiat" </span>
  }
  <span class="hljs-built_in">console</span>.log(car) <span class="hljs-comment">// ReferenceError</span>
}

printCar();
<span class="hljs-built_in">console</span>.log(car); <span class="hljs-comment">// ReferenceError</span>
</code></pre>
<p>The <code>let</code> and <code>const</code> variables are not initialized until their definition is evaluated. They are not hoisted as in the function scoping. Accessing them before the initialization results in a <code>ReferenceError</code>.</p>
<p>I hope you can see how this is easier to reason about.</p>
<h1 id="const-vs-let">Const vs Let</h1>
<p>So now that we know that we should use <code>let</code> and <code>const</code>, when should we use which?</p>
<p>The difference between the two is that the value of a <code>const</code> can’t be changed through reassignment, and it can’t be re-declared. So if we don’t need to reassign we should use <code>const</code>. This also makes the code clearer since we have one variable to represent one thing.</p>
<p>You could even always declare the variables as const until you see that you need to reassign the variables and then change to <code>let</code>. One example of when you need <code>let</code> is in loops:</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10</span>; i++) {
  <span class="hljs-built_in">console</span>.log(i); <span class="hljs-comment">// 1, 2, 3, 4 …</span>
}
</code></pre>
<h1 id="conclusion">Conclusion</h1>
<ul>
<li>Variables declared on the <strong>global scope</strong> are accessible everywhere in your code.</li>
<li>Variables declared in a <strong>local scope</strong> can not be accessed from outside that scope.</li>
<li><code>const</code> and <code>let</code> use block scope which exists between two curly braces.</li>
<li>Mostly use <code>const</code> for variables whose values will never change.</li>
<li>For everything else use <code>let</code>.</li>
<li>Don’t use <code>var</code> to avoid confusion.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[Learning Modern JavaScript with Tetris]]></title><description><![CDATA[Today, I’m taking you along for a journey in game development with the classic game of Tetris. We are going to touch upon concepts like graphics, game loops, and collision detection. In the end, we have a fully functioning game with points and levels...]]></description><link>https://blog.michaelkaren.dev/learning-modern-javascript-with-tetris-92d532bcd057</link><guid isPermaLink="true">https://blog.michaelkaren.dev/learning-modern-javascript-with-tetris-92d532bcd057</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Game Development]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 02 Dec 2019 08:49:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075641894/8rPIMliTx.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, I’m taking you along for a journey in game development with the classic game of Tetris. We are going to touch upon concepts like graphics, game loops, and collision detection. In the end, we have a fully functioning game with points and levels. Part of the journey is using concepts of modern JavaScript, meaning features introduced in ECMAScript 2015 (ES6) like:</p>
<ul>
<li><p><a target="_blank" href="https://medium.com/@michael.karen/modern-javascript-classes-cec93045d85d">Classes</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@michael.karen/getting-started-with-modern-javascript-arrow-functions-d38053b27e31">Arrow Functions</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@michael.karen/getting-started-with-modern-javascript-destructuring-assignment-140d0adc37da">Destructuring</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@michael.karen/modern-javascript-variables-and-scope-572099943edf">Let and const</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@michael.karen/getting-started-with-modern-javascript-proxy-789a7fb71c8e">Proxy</a></p>
</li>
</ul>
<p>I hope you pick up something new that you can bring into your arsenal of JavaScript tricks!</p>
<p>If you are creating the project and get an error from the code snippets, then check the <a target="_blank" href="https://github.com/melcor76/js-tetris/tree/blog">code in the repository on GitHub</a>. Please send me a message if you find something that does not work. Future developments of the game will go into the <a target="_blank" href="https://github.com/melcor76/js-tetris">master branch</a> while the <strong>blog branch</strong> will stay as is.</p>
<p>The finished game looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075605777/ASw4lP5HM.gif" alt /></p>
<p><strong>Translations:</strong></p>
<ul>
<li><a target="_blank" href="https://ui.toast.com/weekly-pick/ko_20191216/">Korean</a></li>
</ul>
<h2 id="tetris">Tetris</h2>
<p>Tetris was created in 1984 by Alexey Pajitnov. The game requires players to rotate and move falling Tetris pieces. Players clear lines by completing horizontal rows of blocks without empty cells. But, if the pieces reach the top, the game is over!</p>
<p>Tetris is a great game to begin our journey in game development. It contains essential elements of games and is relatively easy to program. The tetrominos are a collection of four blocks, which makes graphics a bit easier than most games.</p>
<h2 id="project-structure">Project structure</h2>
<p>It’s good to split the code up some in the project even if it’s not that big. The JavaScript is in four different files:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075607578/ibxnWwsTt.png" alt /></p>
<ul>
<li><p><code>constants.js</code> is where we put the configurations and rules of the game.</p>
</li>
<li><p><code>board.js</code> is for board logic.</p>
</li>
<li><p><code>piece.js</code> is for piece logic.</p>
</li>
<li><p><code>main.js</code> has code to initialize the game and the overall game logic.</p>
</li>
<li><p><code>index.html</code> the order of the scripts that we add at the end is essential.</p>
</li>
<li><p><code>styles.css</code> all the beautifying styles are in here.</p>
</li>
<li><p><code>README.md</code> markdown info file that is the first page in the repository.</p>
</li>
</ul>
<h2 id="size-and-style">Size and Style</h2>
<p>The playing board consists of 10 columns and 20 rows. We are using these values often to loop through the board so we can add them to <code>constants.js</code> together with the size of the blocks:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> COLS = <span class="hljs-number">10</span>;
<span class="hljs-keyword">const</span> ROWS = <span class="hljs-number">20</span>;
<span class="hljs-keyword">const</span> BLOCK_SIZE = <span class="hljs-number">30</span>;
</code></pre>
<p>I prefer using the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial">canvas</a> element for the graphics:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"board"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"game-board"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"right-column"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>TETRIS<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Score: <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"score"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lines: <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"lines"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Level: <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"level"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"next"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"next"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"play()"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"play-button"</span>&gt;</span>Play<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>We can get the canvas element and its 2d context in <code>main.js</code> and use the constants to set the size:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'board'</span>);
<span class="hljs-keyword">const</span> ctx = canvas.getContext(<span class="hljs-string">'2d'</span>);

<span class="hljs-comment">// Calculate size of canvas from constants.</span>
ctx.canvas.width = COLS * BLOCK_SIZE;
ctx.canvas.height = ROWS * BLOCK_SIZE;

<span class="hljs-comment">// Scale blocks</span>
ctx.scale(BLOCK_SIZE, BLOCK_SIZE);
</code></pre>
<p>By using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale">scale</a>, we can always give the size of the blocks as one (1) instead of having to calculate with <code>BLOCK_SIZE</code> everywhere, which simplifies our code.</p>
<h3 id="styling">Styling</h3>
<p>It’s nice to have a bit of an 80’s feel to our game. <a target="_blank" href="https://fonts.google.com/specimen/Press+Start+2P">Press Start 2P</a> is a bitmap font based on the font design from the 1980s Namco arcade games. We can link to it in the <code>&amp;lt;head&amp;gt;</code> and add it to our styles:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">link</span> 
  <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css?family=Press+Start+2P"</span> 
  <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
/&gt;</span>
</code></pre>
<p>The first section in <code>styles.css</code> is for the arcade-style font. Notice the use of CSS Grid and Flexbox for the layout:</p>
<pre><code class="lang-css">* {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Press Start 2P'</span>, cursive;
}

<span class="hljs-selector-class">.grid</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">320px</span> <span class="hljs-number">200px</span>;
}

<span class="hljs-selector-class">.right-column</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
  <span class="hljs-attribute">justify-content</span>: space-between;
}

<span class="hljs-selector-class">.game-board</span> {
  <span class="hljs-attribute">border</span>: solid <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-class">.play-button</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#4caf50</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">15px</span> <span class="hljs-number">30px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}
</code></pre>
<p>With this, we have our game container styled and ready, awaiting code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075609353/JTlV_tBv-.png" alt /></p>
<h2 id="the-board">The Board</h2>
<p>The board in Tetris consists of cells, which are either occupied or not. My first thought was to represent a cell with boolean values. But, we can do better by using numbers. We can represent an empty cell with 0, and the colors with numbers 1–7.</p>
<p>The next concept is representing the rows and columns of the game board. We can use an array of numbers to represent a row. And the board is an array of rows. In other words, a two dimensional (2D) array or what we call a matrix.</p>
<p>The board is a good candidate for a <code>class</code>. We probably wan’t to create a <code>new Board</code> when starting a new game. If you wan’t to learn more about classes I have written a short article about them:</p>
<ul>
<li><a target="_blank" href="https://medium.com/@michael.karen/modern-javascript-classes-cec93045d85d">Getting Started with Modern JavaScript — Classes</a></li>
</ul>
<p>Let’s create a function in <code>board.js</code> that returns an empty board with all cells set to zero. The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill">fill()</a> method comes in handy here:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Board</span> </span>{

  <span class="hljs-comment">// Reset the board when we start a new game.</span>
  reset() {
    <span class="hljs-built_in">this</span>.grid = <span class="hljs-built_in">this</span>.getEmptyBoard();
  }

  <span class="hljs-comment">// Get matrix filled with zeros.</span>
  getEmptyBoard() {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.from(
      {<span class="hljs-attr">length</span>: ROWS}, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">Array</span>(COLS).fill(<span class="hljs-number">0</span>)
    );
  }
}
</code></pre>
<p>We can call this function in <code>main.js</code> when we press play:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> board = <span class="hljs-keyword">new</span> Board();

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{  
  board.reset();  
  <span class="hljs-built_in">console</span>.table(board.grid);  
}
</code></pre>
<p>By using <code>console.table</code> we see the representation of the board in numbers:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075611107/1PseqBuqc.png" alt /></p>
<p>The X and Y coordinates represent the cells of the board. Now that we have the board, let’s take a look at the moving parts.</p>
<h2 id="tetrominos">Tetrominos</h2>
<p>A piece in Tetris is a shape consisting of four blocks that move as a unit. They are often called tetrominos and come in seven different patterns and colors. The names I, J, L, O, S, T, and Z are from the resemblance in their shape.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075612886/6mP-e8u5X.png" alt /></p>
<p>We represent the J tetromino as a matrix where the number two represents the colored cells. We add the row of zeros to get a center to rotate around:</p>
<pre><code>[<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]<span class="hljs-string">,</span>
[<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>]<span class="hljs-string">,</span>
[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]<span class="hljs-string">;</span>
</code></pre><blockquote>
<p>The tetrominos spawn horizontally with J, L, and T spawning flat-side first.</p>
</blockquote>
<p>We want the Piece class to know its <strong>position</strong> on the board, what <strong>color</strong> it has, and its <strong>shape</strong>. So to be able to draw itself on the board, it needs a reference to the <strong>canvas context</strong>.</p>
<p>For starters, we can hard-code the values of our piece in the <code>constructor</code> of the <code>Piece</code> class:</p>
<pre><code class="lang-js"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Piece</span> </span>{  
  <span class="hljs-keyword">constructor</span>(ctx) {
    <span class="hljs-built_in">this</span>.ctx = ctx;
    <span class="hljs-built_in">this</span>.color = <span class="hljs-string">'blue'</span>;
    <span class="hljs-built_in">this</span>.shape = [
      [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], 
      [<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>], 
      [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
    ];

    <span class="hljs-comment">// Starting position.</span>
    <span class="hljs-built_in">this</span>.x = <span class="hljs-number">3</span>;
    <span class="hljs-built_in">this</span>.y = <span class="hljs-number">0</span>;
  }
}
</code></pre>
<p>To draw the tetromino on the board, we loop through all the cells of the shape. If the value in the cell is greater than zero, then we color that block:</p>
<pre><code>draw() {
  <span class="hljs-keyword">this</span>.ctx.fillStyle = <span class="hljs-keyword">this</span>.color;
  <span class="hljs-keyword">this</span>.shape.forEach((row, y) =&gt; {
    row.forEach((value, x) =&gt; {
      <span class="hljs-comment">// this.x, this.y gives the left upper position of the shape</span>
      <span class="hljs-comment">// x, y gives the position of the block in the shape</span>
      <span class="hljs-comment">// this.x + x is then the position of the block on the board</span>
      <span class="hljs-keyword">if</span> (value &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">this</span>.ctx.fillRect(<span class="hljs-keyword">this</span>.x + x, <span class="hljs-keyword">this</span>.y + y, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
      }
    });
  });
}
</code></pre><p>The board keeps track of the tetromino on the board so we can create and paint it when we press the play button:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">play</span>(<span class="hljs-params"></span>) </span>{
  board.reset();
  <span class="hljs-keyword">let</span> piece = <span class="hljs-keyword">new</span> Piece(ctx);
  piece.draw();

  board.piece = piece;
}
</code></pre>
<p>The blue J tetromino appears!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075614625/pjMlLqBz8.png" alt /></p>
<p>Next, let’s make magic happen through the keyboard.</p>
<h2 id="keyboard-input">Keyboard input</h2>
<p>We need to connect the keyboard events to move the piece on the board. The <code>move</code> function changes the x or y variable of the current piece to change its position on the board.</p>
<pre><code>move(p) {
  <span class="hljs-keyword">this</span>.x = p.x;
  <span class="hljs-keyword">this</span>.y = p.y;
}
</code></pre><h3 id="enums">Enums</h3>
<p>Next, we map the keys to the key codes in <code>constants.js</code>. For this, it would be nice to have an enum.</p>
<blockquote>
<p>Enum (enumeration) is a special type used to define collections of constants.</p>
</blockquote>
<p>There are no built-in enums in JavaScript so let’s make one by creating an object with the values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> KEY = {
  <span class="hljs-attr">LEFT</span>: <span class="hljs-number">37</span>,
  <span class="hljs-attr">RIGHT</span>: <span class="hljs-number">39</span>,
  <span class="hljs-attr">DOWN</span>: <span class="hljs-number">40</span>
}
<span class="hljs-built_in">Object</span>.freeze(KEY);
</code></pre>
<p>The const can be a bit misleading when working with objects and arrays and does not actually make them immutable. To achieve this, we can use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze">Object.freeze()</a>. A couple of gotchas here are:</p>
<ul>
<li><p>For this to work properly, we need to use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a>.</p>
</li>
<li><p>This only works one level down. In other words, if we have an array or object inside our object, then this does not freeze them.</p>
</li>
</ul>
<h3 id="object-literals">Object literals</h3>
<p>To match the key events to actions, we can use object literal lookups.</p>
<blockquote>
<p>ES6 allows property keys of object literals to use expressions, making them computed property keys.</p>
</blockquote>
<p>We need the brackets to get computed property names so that we can use our constants. This is a simplified example of how it works:</p>
<pre><code><span class="hljs-keyword">const</span> X = <span class="hljs-string">'x'</span>;
<span class="hljs-keyword">const</span> a = { [X]: <span class="hljs-number">5</span> };
console.<span class="hljs-built_in">log</span>(a.x); *<span class="hljs-comment">// 5*</span>
</code></pre><p>We want to send in the current tetromino and return a copy of it together with the change in coordinates. For this, we can use the spread operator to get a shallow copy and then change the coordinates to our desired position.</p>
<blockquote>
<p>In JavaScript, we can use <strong>shallow copying</strong> to copy primitive data types like numbers and strings. In our case, the coordinates are numbers. ES6 offers two shallow copy mechanisms: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign()</a> and the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator</a>.</p>
</blockquote>
<p>In other words, a lot is going on in this code snippet:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> moves = {
  [KEY.LEFT]:  <span class="hljs-function"><span class="hljs-params">p</span> =&gt;</span> ({ ...p, <span class="hljs-attr">x</span>: p.x - <span class="hljs-number">1</span> }),
  [KEY.RIGHT]: <span class="hljs-function"><span class="hljs-params">p</span> =&gt;</span> ({ ...p, <span class="hljs-attr">x</span>: p.x + <span class="hljs-number">1</span> }),
  [KEY.DOWN]:    <span class="hljs-function"><span class="hljs-params">p</span> =&gt;</span> ({ ...p, <span class="hljs-attr">y</span>: p.y + <span class="hljs-number">1</span> })
};
</code></pre>
<p>Which we can use with the code beneath to get the new state without mutating the original piece. It’s important because we don’t always want to move to a new position.</p>
<pre><code>const p = this.moves[<span class="hljs-string">event.key</span>](<span class="hljs-link">this.piece</span>);
</code></pre><p>Next, we add an event listener that listens to <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event">keydown events</a>:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'keydown'</span>, <span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
  <span class="hljs-keyword">if</span> (moves[event.keyCode]) {  
    <span class="hljs-comment">// Stop the event from bubbling.</span>
    event.preventDefault();

    <span class="hljs-comment">// Get new state of piece</span>
    <span class="hljs-keyword">let</span> p = moves[event.keyCode](board.piece);

    <span class="hljs-keyword">if</span> (board.valid(p)) {    
      <span class="hljs-comment">// If the move is valid, move the piece.</span>
      board.piece.move(p);

      <span class="hljs-comment">// Clear old position before drawing.</span>
      ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, ctx.canvas.width, ctx.canvas.height); 

      board.piece.draw();
    }
  }
});
</code></pre>
<p>Now we are listening to the keyboard events, and if we press left, right, or down arrows, then we can see the piece moving.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075615987/mghfix25d.gif" alt /></p>
<p>We have a movement! However, ghost pieces going through walls are not what we want.</p>
<h2 id="collision-detection">Collision detection</h2>
<p>Tetris would not be a particularly exciting game if all blocks could pass through each other, or if the walls and floor did not stop them. So instead of moving the tetromino, we’ll check for potential collisions first, and then only move the tetromino if it’s safe. We have a few different collisions to consider.</p>
<p>We have a collision when the tetromino:</p>
<ul>
<li><p>hits the floor</p>
</li>
<li><p>moves left or right into a wall</p>
</li>
<li><p>hits a block on the board</p>
</li>
<li><p>rotates, and the new rotation hits a wall or block</p>
</li>
</ul>
<p>We already defined the potential new position for the shape. Now we can add a check if this position is valid before we move to it. To check for collisions, we loop through all the spaces in the grid that the tetromino would take up in its potential new position.</p>
<p>The array method best suited for this is <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every">every()</a>. With it, we can check whether all elements in the array pass the tests we provide. We calculate the coordinates of every block of the piece and check that it’s a valid position:</p>
<pre><code class="lang-js">valid(p) {
  <span class="hljs-keyword">return</span> p.shape.every(<span class="hljs-function">(<span class="hljs-params">row, dy</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> row.every(<span class="hljs-function">(<span class="hljs-params">value, dx</span>) =&gt;</span> {
      <span class="hljs-keyword">let</span> x = p.x + dx;
      <span class="hljs-keyword">let</span> y = p.y + dy;
      <span class="hljs-keyword">return</span> (
        <span class="hljs-built_in">this</span>.isEmpty(value) ||
       (<span class="hljs-built_in">this</span>.insideWalls(x) &amp;&amp;
        <span class="hljs-built_in">this</span>.aboveFloor(y)
      );
    });
  });
}
</code></pre>
<p>By using this method before we move, we make sure that we don’t move anywhere we shouldn’t:</p>
<pre><code><span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.valid(p)) {
  <span class="hljs-keyword">this</span>.piece.move(p);
}
</code></pre><p>Let’s try going outside the grid again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075617714/dt0ca40Eq.gif" alt /></p>
<p>No more ghosting!</p>
<p>Now that the floor stops the tetromino, we can add another move called the hard drop. Pressing space drops the tetromino until it collides with something. This is called a <em>hard drop</em>. We also need to add the new key mapping and move:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> KEY = {  
  <span class="hljs-attr">SPACE</span>: <span class="hljs-number">32</span>,
  <span class="hljs-comment">// ...</span>
}

moves = {  
  [KEY.SPACE]: <span class="hljs-function"><span class="hljs-params">p</span> =&gt;</span> ({ ...p, <span class="hljs-attr">y</span>: p.y + <span class="hljs-number">1</span> })
  <span class="hljs-comment">// ...</span>
};

<span class="hljs-comment">// In EventListener</span>
<span class="hljs-keyword">if</span> (event.keyCode === KEY.SPACE) {
  <span class="hljs-comment">// Hard drop</span>
  <span class="hljs-keyword">while</span> (board.valid(p)) {
    board.piece.move(p);   
    p = moves[KEY.DOWN](board.piece);
  }
}
</code></pre>
<p>What’s next?</p>
<h2 id="rotation">Rotation</h2>
<p>Now we can move around, but it would not be any fun if we can’t rotate the piece. We need to rotate the tetrominos around their center.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075619322/I6SuyHUXw.png" alt /></p>
<p>It has been a while since I studied <a target="_blank" href="https://en.wikipedia.org/wiki/Rotation_matrix">linear algebra</a> in school. But, to rotate clockwise goes something like this:</p>
<blockquote>
<p><em>Two reflections can accomplish a rotation by 90 degrees at a 45-degree angle so you can take the transpose of the matrix and then multiply it by the permutation matrix that reverses the order of the columns.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075620685/f1Sg10P4x.png" alt /></p>
<p>And in JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Transpose matrix, p is the Piece.</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> y = <span class="hljs-number">0</span>; y &lt; p.shape.length; ++y) {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt; y; ++x) {
    [p.shape[x][y], p.shape[y][x]] = 
    [p.shape[y][x], p.shape[x][y]];
  }
}

<span class="hljs-comment">// Reverse the order of the columns.</span>
p.shape.forEach(<span class="hljs-function"><span class="hljs-params">row</span> =&gt;</span> row.reverse());
</code></pre>
<p>We can add a function that rotates the shape. Earlier, we used the spread operator to clone the coordinates. In this case, we are working with a multiple level array, but the spread operator only copies one level deep. The rest is copied by reference.</p>
<p>I’m instead using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">JSON.parse</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">JSON.stringify</a>. The <code>**stringify()</code><strong> method converts the matrix to a JSON string. The `</strong>parse()`** method parses the JSON string, constructing our matrix back again to a clone:</p>
<pre><code class="lang-js">rotate(p){
  <span class="hljs-comment">// Clone with JSON for immutability</span>
  <span class="hljs-keyword">let</span> clone = <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">JSON</span>.stringify(p));

  <span class="hljs-comment">// Do algorithm</span>

  <span class="hljs-keyword">return</span> clone;
}
</code></pre>
<p>Then we add a new state for ArrowUp in <code>board.js</code>.</p>
<pre><code>[KEY.UP]: <span class="hljs-function"><span class="hljs-params">(p)</span> =&gt;</span> <span class="hljs-built_in">this</span>.rotate(p)
</code></pre><p>Now we rotate!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075622195/fJxiqmlax.gif" alt /></p>
<h2 id="randomize-tetromino">Randomize Tetromino</h2>
<p>To be able to get different kinds of pieces, we need to add a bit of randomization to our code.</p>
<p>Following the <a target="_blank" href="https://tetris.fandom.com/wiki/SRS">Super Rotation System</a>, we can take the first position of the pieces and add them to our constants together with the colors:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> COLORS = [  
  <span class="hljs-string">'cyan'</span>,
  <span class="hljs-string">'blue'</span>,
  <span class="hljs-string">'orange'</span>,
  <span class="hljs-string">'yellow'</span>,
  <span class="hljs-string">'green'</span>,
  <span class="hljs-string">'purple'</span>,
  <span class="hljs-string">'red'</span>
];

<span class="hljs-keyword">const</span> SHAPES = [  
  [
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], 
    [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], 
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
  ], 
  [
    [<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>],
    [<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>],
    [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]
  ],
  <span class="hljs-comment">// And so on</span>
];
</code></pre>
<p>We need to randomize the index of one of these to pick one piece. To get a random number, we create a function that uses the length of the array.</p>
<pre><code class="lang-js">randomizeTetrominoType(noOfTypes) {
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * noOfTypes);
}
</code></pre>
<p>With this method we can get a random tetromino type when we spawn and then set the color and shape from it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> typeId = <span class="hljs-built_in">this</span>.randomizeTetrominoType(COLORS.length);
<span class="hljs-built_in">this</span>.shape = SHAPES[typeId];
<span class="hljs-built_in">this</span>.color = COLORS[typeId];
</code></pre>
<p>If we press play the page shows pieces with different shapes and colors.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075624243/IW3kqc5XR.gif" alt /></p>
<h2 id="game-loop">Game Loop</h2>
<p>Almost all games have one main function that keeps the game running even when the user isn’t doing anything. This cycle of running the same core function over and over again is called the game loop. In our game, we need a game loop that moves the tetrominos down the screen.</p>
<h3 id="requestanimationframe">RequestAnimationFrame</h3>
<p>To create our game loop, we can use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame">requestAnimationFrame</a>. It tells the browser that we want to animate, and it should call a function to update an animation before the next repaint. In other words, we tell the browser: “Next time you paint on the screen, also run this function because I want to paint something too.”</p>
<blockquote>
<h1 id="animation-is-not-the-art-of-drawings-that-move-but-the-art-of-movements-that-are-drawn-norman-mclaren">“Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren</h1>
</blockquote>
<p>The way to animate with <code>window.requestAnimationFrame()</code> is to create a function that paints a frame and then re-schedules itself. If we use it inside a class (we don’t in our case), we need to bind the call to <code>this</code>, or it has the window object as its context. Since it doesn't contain the animate function, we get an error.</p>
<pre><code class="lang-js">animate() {
  <span class="hljs-built_in">this</span>.piece.draw();
  requestAnimationFrame(<span class="hljs-built_in">this</span>.animate.bind(<span class="hljs-built_in">this</span>));
}
</code></pre>
<p>We can remove all our previous calls to <code>draw()</code> and instead call <code>animate()</code> from the <code>play()</code> function to start the animation. If we try our game, it should still run like before.</p>
<h3 id="timer">Timer</h3>
<p>Next, we need a timer. Every time frame, we drop the tetromino. There is an <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame#Notes">example</a> on the MDN page that we can modify to our needs.</p>
<p>We start by creating an object with the info we need:</p>
<pre><code><span class="hljs-string">time</span> <span class="hljs-string">=</span> { <span class="hljs-attr">start:</span> <span class="hljs-number">0</span>, <span class="hljs-attr">elapsed:</span> <span class="hljs-number">0</span>, <span class="hljs-attr">level:</span> <span class="hljs-number">1000</span> }<span class="hljs-string">;</span>
</code></pre><p>In the game loop, we update our game state based on the time interval and then draw the result:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animate</span>(<span class="hljs-params">now = <span class="hljs-number">0</span></span>) </span>{
  <span class="hljs-comment">// Update elapsed time.  </span>
  time.elapsed = now - time.start;

  <span class="hljs-comment">// If elapsed time has passed time for current level  </span>
  <span class="hljs-keyword">if</span> (time.elapsed &gt; time.level) {

    <span class="hljs-comment">// Restart counting from now</span>
    time.start = now;   

    <span class="hljs-built_in">this</span>.drop();  
  }

  <span class="hljs-comment">// Clear board before drawing new state.</span>
  ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, ctx.canvas.width, ctx.canvas.height); 

  board.draw();  
  requestId = requestAnimationFrame(animate);
}
</code></pre>
<p>We have animation!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075626265/3kxChAF9G.gif" alt /></p>
<p>Next, let’s look at what happens when we reach the bottom.</p>
<h2 id="freeze">Freeze</h2>
<p>When we can’t move down anymore, we freeze the piece and spawn a new one. Let’s start by defining <code>freeze()</code>. This function merges the tetromino blocks to the board:</p>
<pre><code class="lang-js">freeze() {
  <span class="hljs-built_in">this</span>.piece.shape.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">value, x</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (value &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">this</span>.grid[y + <span class="hljs-built_in">this</span>.piece.y][x + <span class="hljs-built_in">this</span>.piece.x] = value;
      }
    });
  });
}
</code></pre>
<p>We can’t see anything yet, but by logging the representation of the board, we can see that the shape is on the board.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075628110/1WEyQL2YJ.png" alt /></p>
<p>Let’s add a function that draws the board:</p>
<pre><code class="lang-js">drawBoard() {
  <span class="hljs-built_in">this</span>.grid.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">value, x</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (value &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">this</span>.ctx.fillStyle = COLORS[value];
        <span class="hljs-built_in">this</span>.ctx.fillRect(x, y, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
      }
    });
  });
}
</code></pre>
<p>Now the draw function looks like this:</p>
<pre><code class="lang-js">draw() {
  <span class="hljs-built_in">this</span>.piece.draw();
  <span class="hljs-built_in">this</span>.drawBoard();
}
</code></pre>
<p>If we run the game, we can see that the pieces are showing up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075629662/9X6O6jKvG.png" alt /></p>
<p>Now that we are freezing the pieces, we need to add new collision detection. This time we have to make sure that we don’t collide with frozen tetrominos on the board. We can do this by checking that the cell is zero. Add this to the <code>valid</code> method and send in the board as an argument:</p>
<pre><code class="lang-js">board[p.y + y][p.x + x] === <span class="hljs-number">0</span>;
</code></pre>
<p>Now that we are adding pieces to the board, it quickly gets crowded. We should do something about that.</p>
<h2 id="line-clear">Line clear</h2>
<p>To last longer, we need to assemble the tetrominos in rows of blocks that span the entire row, resulting in a line clear. When you do so, the row disappears, causing the ones above it to settle.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075631185/VXQd7nDwT.png" alt /></p>
<p>Detecting formed lines is as easy as checking if it has any zeros:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.grid.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {

  <span class="hljs-comment">// If every value is greater than 0.</span>
  <span class="hljs-keyword">if</span> (row.every(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> value &gt; <span class="hljs-number">0</span>)) {

    <span class="hljs-comment">// Remove the row.</span>
    <span class="hljs-built_in">this</span>.grid.splice(y, <span class="hljs-number">1</span>);

    <span class="hljs-comment">// Add zero filled row at the top. </span>
    <span class="hljs-built_in">this</span>.grid.unshift(<span class="hljs-built_in">Array</span>(COLS).fill(<span class="hljs-number">0</span>));
  } 
});
</code></pre>
<p>We can add a call to this <code>clearLines()</code> function after the <code>freeze()</code> call. We can try playing and hopefully see the rows getting cleared.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075632783/C1UylKGGX.gif" alt /></p>
<h2 id="score">Score</h2>
<p>To get a bit more excitement, we need to keep score. From the Tetris guideline we get these values:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> POINTS = {
  <span class="hljs-attr">SINGLE</span>: <span class="hljs-number">100</span>,
  <span class="hljs-attr">DOUBLE</span>: <span class="hljs-number">300</span>,
  <span class="hljs-attr">TRIPLE</span>: <span class="hljs-number">500</span>,
  <span class="hljs-attr">TETRIS</span>: <span class="hljs-number">800</span>,
  <span class="hljs-attr">SOFT_DROP</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">HARD_DROP</span>: <span class="hljs-number">2</span>
}
<span class="hljs-built_in">Object</span>.freeze(POINTS);
</code></pre>
<p>To keep track of the game progress, we add an <code>accountValues</code> object with the score and lines. When any of these values changes, we want to change it on the screen. We add a generic function that gets the element from the HTML and changes its <code>textContext</code> to the value provided.</p>
<p>To act on changes on the account object, we can create a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy">Proxy</a> object and run the code to update the screen in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set">set method</a>. If you wan’t to learn the basics of <code>Proxy</code> I have a short article on it you can read:</p>
<ul>
<li><a target="_blank" href="https://medium.com/@michael.karen/getting-started-with-modern-javascript-proxy-789a7fb71c8e">Getting Started with Modern JavaScript — Proxy</a></li>
</ul>
<p>We send in the <code>accountValues</code> object to the proxy because this is the object we want to have custom behaviors on:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> accountValues = {
  <span class="hljs-attr">score</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">lines</span>: <span class="hljs-number">0</span>
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateAccount</span>(<span class="hljs-params">key, value</span>) </span>{
  <span class="hljs-keyword">let</span> element = <span class="hljs-built_in">document</span>.getElementById(key);
  <span class="hljs-keyword">if</span> (element) {
    element.textContent = value;
  }
}

<span class="hljs-keyword">let</span> account = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Proxy</span>(accountValues, {
  <span class="hljs-attr">set</span>: <span class="hljs-function">(<span class="hljs-params">target, key, value</span>) =&gt;</span> {
    target[key] = value;
    updateAccount(key, value);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
  }
}
</code></pre>
<p>Now every time we call properties on the proxy <code>account</code>, we call <code>updateAccount()</code> and update the DOM. Let’s add the points for soft and hard drops in our event handler:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (event.keyCode === KEY.SPACE) {
  <span class="hljs-keyword">while</span> (board.valid(p)) {
    account.score += POINTS.HARD_DROP;
    board.piece.move(p);
    p = moves[KEY.DOWN](board.piece);
  }
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (board.valid(p)) {
  board.piece.move(p);
  <span class="hljs-keyword">if</span> (event.keyCode === KEY.DOWN) {
    account.score += POINTS.SOFT_DROP;
  }
}****
</code></pre>
<p>Now for the line clear points. Depending on the number of lines, we get the defined points:</p>
<pre><code class="lang-js">getLineClearPoints(lines) {  
  <span class="hljs-keyword">return</span> lines === <span class="hljs-number">1</span> ? Points.SINGLE :
         lines === <span class="hljs-number">2</span> ? Points.DOUBLE :  
         lines === <span class="hljs-number">3</span> ? Points.TRIPLE :     
         lines === <span class="hljs-number">4</span> ? Points.TETRIS : 
         <span class="hljs-number">0</span>;
}
</code></pre>
<p>For this to work, we need to add a bit of logic to count how many lines we clear:</p>
<pre><code class="lang-js">clearLines() {
  <span class="hljs-keyword">let</span> lines = <span class="hljs-number">0</span>;
  <span class="hljs-built_in">this</span>.board.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {    
    <span class="hljs-keyword">if</span> (row.every(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> value !== <span class="hljs-number">0</span>)) {      
      lines++; <span class="hljs-comment">// Increase for cleared line</span>
      <span class="hljs-built_in">this</span>.board.splice(y, <span class="hljs-number">1</span>); 
      <span class="hljs-built_in">this</span>.board.unshift(<span class="hljs-built_in">Array</span>(COLS).fill(<span class="hljs-number">0</span>));
    }  
  });  
  <span class="hljs-keyword">if</span> (lines &gt; <span class="hljs-number">0</span>) {    
    <span class="hljs-comment">// Add points if we cleared some lines</span>
    account.score += <span class="hljs-built_in">this</span>.getLineClearPoints(lines);  
  }
}
</code></pre>
<p>If we try playing now, we can see that we are increasing our score. What we need to keep in mind is that whenever we want something to show up on the screen, we need to go through the proxy instead of directly to the account object.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075634654/qTimKLgGu.gif" alt /></p>
<h2 id="levels">Levels</h2>
<p>When we get better at Tetris, the speed we start on gets too easy. And too easy means boring. So we need to increase the level of difficulty. We do this by decreasing the interval speed in our game loop:</p>
<pre><code><span class="hljs-string">const</span> <span class="hljs-string">LINES_PER_LEVEL</span> <span class="hljs-string">=</span> <span class="hljs-number">10</span><span class="hljs-string">;</span>

<span class="hljs-string">const</span> <span class="hljs-string">LEVEL</span> <span class="hljs-string">=</span> {
  <span class="hljs-attr">0:</span> <span class="hljs-number">800</span>,
  <span class="hljs-attr">1:</span> <span class="hljs-number">720</span>,
  <span class="hljs-attr">2:</span> <span class="hljs-number">630</span>,
  <span class="hljs-attr">3:</span> <span class="hljs-number">550</span>,
  <span class="hljs-string">//</span> <span class="hljs-string">...</span>
}

<span class="hljs-string">Object.freeze(LEVEL);</span>
</code></pre><p>We can also show the player which level they are currently on. The logic of keeping track and showing levels and lines is the same as for points. We initialize a value for them, and when we start a new game, we have to reset them.</p>
<p>We can add it to the account object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> accountValues = {
  <span class="hljs-attr">score</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">lines</span>: <span class="hljs-number">0</span>,
  <span class="hljs-attr">level</span>: <span class="hljs-number">0</span>
}
</code></pre>
<p>The initialization of the game can go in a function that we call from <code>play()</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resetGame</span>(<span class="hljs-params"></span>) </span>{
  account.score = <span class="hljs-number">0</span>;
  account.lines = <span class="hljs-number">0</span>;
  account.level = <span class="hljs-number">0</span>;
  board = <span class="hljs-built_in">this</span>.getEmptyBoard();
}
</code></pre>
<p>With increasing levels comes more points for line clears. We multiply the points with the current level and add one since we start on level zero.</p>
<pre><code>(account.<span class="hljs-keyword">level</span> + <span class="hljs-number">1</span>) * lineClearPoints;
</code></pre><p>The next level is reached when the lines are cleared as configured. We also need to update the speed of the level:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (lines &gt; <span class="hljs-number">0</span>) {
  <span class="hljs-comment">// Calculate points from cleared lines and level.</span>

  account.score += <span class="hljs-built_in">this</span>.getLinesClearedPoints(lines, <span class="hljs-built_in">this</span>.level);
  account.lines += lines;

  <span class="hljs-comment">// If we have reached the lines for next level</span>
  <span class="hljs-keyword">if</span> (account.lines &gt;= LINES_PER_LEVEL) {

    <span class="hljs-comment">// Goto next level</span>
    account.level++;

    <span class="hljs-comment">// Remove lines so we start working for the next level</span>
    account.lines -= LINES_PER_LEVEL;

    <span class="hljs-comment">// Increase speed of game.</span>
    time.level = Level[account.level];
  }
}
</code></pre>
<p>Now if we play and clear ten lines we see the level increase and the points double. And of course the game starts moving a bit faster.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075636653/JjDExWwSx.gif" alt /></p>
<h2 id="game-over">Game Over</h2>
<p>If you play for a while, you notice that the tetrominos don’t stop falling. We need to know when to end the game.</p>
<p>After we drop we can check if we are still on row 0 and in that case, we stop the game by exiting the game loop function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.piece.y === <span class="hljs-number">0</span>) {
  <span class="hljs-built_in">this</span>.gameOver();
  <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>Before we exit, we cancel the previously scheduled animation frame request with <code>cancelAnimationFrame</code>. And, we show a message to the user:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">gameOver</span>(<span class="hljs-params"></span>) </span>{
  cancelAnimationFrame(requestId);
  <span class="hljs-built_in">this</span>.ctx.fillStyle = <span class="hljs-string">'black'</span>;
  <span class="hljs-built_in">this</span>.ctx.fillRect(<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">1.2</span>);
  <span class="hljs-built_in">this</span>.ctx.font = <span class="hljs-string">'1px Arial'</span>;
  <span class="hljs-built_in">this</span>.ctx.fillStyle = <span class="hljs-string">'red'</span>;
  <span class="hljs-built_in">this</span>.ctx.fillText(<span class="hljs-string">'GAME OVER'</span>, <span class="hljs-number">1.8</span>, <span class="hljs-number">4</span>);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075638600/9KCkzb2Lh.png" alt /></p>
<h2 id="next-tetromino">Next tetromino</h2>
<p>Let’s add one last thing, the next tetromino. We can add another canvas for this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"next"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"next"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
</code></pre>
<p>Next, we do as we did for our first canvas:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> canvasNext = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'next'</span>);
<span class="hljs-keyword">const</span> ctxNext = canvasNext.getContext(<span class="hljs-string">'2d'</span>);

<span class="hljs-comment">// Size canvas for four blocks.</span>
ctxNext.canvas.width = <span class="hljs-number">4</span> * BLOCK_SIZE;
ctxNext.canvas.height = <span class="hljs-number">4</span> * BLOCK_SIZE;
ctxNext.scale(BLOCK_SIZE, BLOCK_SIZE);
</code></pre>
<p>We have to change the logic a bit in the <code>drop</code> function. Instead of creating a new piece we set it to the next and instead create a <em>new next</em> piece:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.piece = <span class="hljs-built_in">this</span>.next;
<span class="hljs-built_in">this</span>.next = <span class="hljs-keyword">new</span> Piece(<span class="hljs-built_in">this</span>.ctx);
<span class="hljs-built_in">this</span>.next.drawNext(<span class="hljs-built_in">this</span>.ctxNext);
</code></pre>
<p>Now that we see which piece is coming next, we can be a bit more strategic.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075640169/g8QK0oNBx.png" alt /></p>
<h2 id="conclusion">Conclusion</h2>
<p>Today we learned about the basics in game development and how we can use Canvas for graphics. I also wanted this project to be a fun way of learning modern JavaScript. I hope you enjoyed the article and learned something new for your JavaScript toolbox.</p>
<p>And now that we have taken our first steps into game development, what game do we do next?</p>
<p>Check out how to add high scores:</p>
<ul>
<li><a target="_blank" href="https://michael-karen.medium.com/how-to-save-high-scores-in-local-storage-7860baca9d68">How to Add High Scores in Local Storage</a></li>
</ul>
<p>Thank you, <a target="_blank" href="https://twitter.com/tim_deschryver">Tim Deschryver</a> for being the sounding board of my Tetris journey.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
<h3 id="resources">Resources</h3>
<ul>
<li><p>Here is the <a target="_blank" href="https://github.com/melcor76/js-tetris/tree/blog">code on GitHub</a> for the finished game.</p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=_fQtxKmgJC8">The Story of Tetris</a> on YouTube</p>
</li>
<li><p><a target="_blank" href="https://simon.lc/the-history-of-tetris-randomizers">The history of Tetris randomizers</a></p>
</li>
<li><p><a target="_blank" href="https://tetris.fandom.com/wiki/Tetris_Wiki">Tetris Wiki</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/Alaricus/SimpleTetris">SimpleTetris</a> in only 100 lines of JavaScript</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Game Development: Tetris in Angular]]></title><description><![CDATA[Today, I’m taking you along for a journey in game development with the classic game of Tetris. We are going to touch upon concepts like graphics, game loops, and collision detection. In the end, we will have a fully functioning game with points and l...]]></description><link>https://blog.michaelkaren.dev/game-development-tetris-in-angular-64ef96ce56f7</link><guid isPermaLink="true">https://blog.michaelkaren.dev/game-development-tetris-in-angular-64ef96ce56f7</guid><category><![CDATA[Angular]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Game Development]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 30 Sep 2019 07:06:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075677073/kxGCRefos.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today, I’m taking you along for a journey in game development with the classic game of Tetris. We are going to touch upon concepts like graphics, game loops, and collision detection. In the end, we will have a fully functioning game with points and levels.</p>
<p>I hope you come back if I let you try out the game: <a target="_blank" href="https://focused-mestorf-930f82.netlify.com/">Play the game!</a></p>
<p>The code for the finished game is on <a target="_blank" href="https://github.com/melcor76/ng-tetris/tree/blog">GitHub</a>. Please send me a message if you find something that does not work. Future developments of the game will go into the master branch while the <strong>blog branch</strong> will stay as is.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075648388/85lSuuDwF.gif" alt /></p>
<h2 id="tetris">Tetris</h2>
<p>Tetris was created in 1984, by Alexey Pajitnov. The game requires players to rotate and move falling Tetris pieces. Players clear lines by completing horizontal rows of blocks without empty cells. But, if the pieces reach the top, the game is over!</p>
<p>Tetris is a great game to begin our journey in game development. It contains essential elements of games and can be done without too much effort. The tetrominos are a collection of four blocks, which makes graphics a bit easier than most games.</p>
<p>For more in-detail knowledge about using the canvas, I wrote another article as a primer to this one. It goes through the fundamentals of how to animate an object:</p>
<ul>
<li><a target="_blank" href="https://medium.com/angular-in-depth/how-to-get-started-with-canvas-animations-in-angular-2f797257e5b4">How to get started with Canvas animations in Angular</a></li>
</ul>
<h2 id="setup">Setup</h2>
<p>Let’s start by installing the <a target="_blank" href="https://cli.angular.io/">Angular CLI</a> globally:</p>
<pre><code><span class="hljs-built_in">npm</span> install -g @angular/cli
</code></pre><p>With the CLI installed, we can create a new project with <a target="_blank" href="https://angular.io/cli/new">ng new</a>:</p>
<pre><code>ng <span class="hljs-built_in">new</span> ng-tetris — minimal — defaults
</code></pre><p>The playing board consists of 10 columns and 20 rows. We are using these values often to loop through the board so we can add them to <code>constants.ts</code> together with the size of the blocks:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> COLS = <span class="hljs-number">10</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ROWS = <span class="hljs-number">20</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> BLOCK_SIZE = <span class="hljs-number">30</span>;
</code></pre>
<p>We need something to draw on. I prefer using a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial">canvas</a>, an HTML element which can be used to draw graphics.</p>
<p>We first need to introduce a <code>&amp;lt;canvas&amp;gt;</code> element, which we can do in the component's template. We'll also attach <a target="_blank" href="https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars">a reference variable</a> to the element so that can refer to it from the component class. This is our complete template waiting for some logic to make the magic happen:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> #<span class="hljs-attr">board</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"game-board"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"right-column"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>TETRIS<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Score: {{ points }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lines: {{ lines }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Level: {{ level }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"play()"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"play-button"</span>&gt;</span>Play<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>Here is the <code>board.component.ts</code> starter code:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { Component, ViewChild, ElementRef, OnInit } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { COLS, BLOCK_SIZE, ROWS } <span class="hljs-keyword">from</span> <span class="hljs-string">'./constants'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'game-board'</span>,
  templateUrl: <span class="hljs-string">'board.component.html'</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> BoardComponent <span class="hljs-keyword">implements</span> OnInit {
  <span class="hljs-comment">// Get reference to the canvas.</span>
  <span class="hljs-meta">@ViewChild</span>(<span class="hljs-string">'board'</span>, { <span class="hljs-keyword">static</span>: <span class="hljs-literal">true</span> })
  canvas: ElementRef&lt;HTMLCanvasElement&gt;;

  ctx: CanvasRenderingContext2D;
  points: <span class="hljs-built_in">number</span>;
  lines: <span class="hljs-built_in">number</span>;
  level: <span class="hljs-built_in">number</span>;

  ngOnInit() {
    <span class="hljs-built_in">this</span>.initBoard();
  }

  initBoard() {
    <span class="hljs-comment">// Get the 2D context that we draw on.</span>
    <span class="hljs-built_in">this</span>.ctx = <span class="hljs-built_in">this</span>.canvas.nativeElement.getContext(<span class="hljs-string">'2d'</span>);

    <span class="hljs-comment">// Calculate size of canvas from constants.</span>
    <span class="hljs-built_in">this</span>.ctx.canvas.width = COLS * BLOCK_SIZE;
    <span class="hljs-built_in">this</span>.ctx.canvas.height = ROWS * BLOCK_SIZE;
  }

  play() {}
}
</code></pre>
<p>Change the template in <code>app.component.ts</code> to be the new board component:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">game-board</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">game-board</span>&gt;</span>
</code></pre>
<h3 id="styling">Styling</h3>
<p>It’s nice to have a bit of an 80’s feel to our game. <a target="_blank" href="https://fonts.google.com/specimen/Press+Start+2P">Press Start 2P</a> is a bitmap font based on the font design from 1980s Namco arcade games. We can add it in two steps:</p>
<pre><code><span class="hljs-comment">&lt;!-- index.html --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> *<span class="hljs-attr">href</span>*=<span class="hljs-string">”https://fonts.googleapis.com/css?family</span>=<span class="hljs-string">Press+Start+2P</span>" *<span class="hljs-attr">rel</span>*=<span class="hljs-string">”stylesheet”</span> /&gt;</span>

/* styles.css */
* {
  font-family: 'Press Start 2P', cursive;
}
</code></pre><p>With this, we have our game container styled and ready, waiting for some code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075650169/kIdP1Csg7.png" alt /></p>
<h2 id="the-board">The Board</h2>
<p>The board in Tetris consists of cells, which are either occupied or not. My first thought was to represent a cell with boolean values. But, we can do better by using numbers. We can represent an empty cell with 0, and the colors with numbers 1–7.</p>
<p>The next concept is representing the rows and columns of the game board. We can use an array of numbers to represent a row. And the board is an array of rows. In other words, a two dimensional (2D) array, or matrix.</p>
<p>Let’s create a function that returns an empty board with all cells set to zero. The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill">fill()</a> method comes in handy here:</p>
<pre><code class="lang-ts">getEmptyBoard(): <span class="hljs-built_in">number</span>[][] {
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>.from({ length: ROWS }, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">Array</span>(COLS).fill(<span class="hljs-number">0</span>));
}
</code></pre>
<p>We can call this function when we press play:</p>
<pre><code class="lang-ts">play() {
  <span class="hljs-built_in">this</span>.board = <span class="hljs-built_in">this</span>.boardService.getEmptyBoard();
  <span class="hljs-built_in">console</span>.table(<span class="hljs-built_in">this</span>.board);
}
</code></pre>
<p>By using <code>console.table</code> we see the representation of the board in numbers:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075651552/ZgtoSSVH7.png" alt /></p>
<p>The X and Y coordinates represent the cells of the board. Now that we have the board let’s take a look at the moving parts.</p>
<h2 id="tetrominos">Tetrominos</h2>
<p>A piece in Tetris is a shape consisting of four blocks that move as a unit. They are often called tetrominos and come in seven different patterns and colors. The names I, J, L, O, S, T, and Z are from the resemblance in their shape.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075652973/spZUeXpxi.png" alt /></p>
<p>We represent the J tetromino as a matrix where the number two represents the colored cells. We add the row of zeros to get a center to rotate around:</p>
<pre><code>[<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]<span class="hljs-string">,</span>
[<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>]<span class="hljs-string">,</span>
[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]<span class="hljs-string">;</span>
</code></pre><blockquote>
<p>The tetrominos spawn horizontally with J, L and T spawning flat-side first.</p>
</blockquote>
<p>Let’s specify the Tetris piece in our code with an interface:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">interface</span> IPiece {
  x: <span class="hljs-built_in">number</span>;
  y: <span class="hljs-built_in">number</span>;
  color: <span class="hljs-built_in">string</span>;
  shape: <span class="hljs-built_in">number</span>[][];
}
</code></pre>
<p>We want the Piece class to know its <strong>position</strong> on the board, what <strong>color</strong> it has, and its <strong>shape</strong>. So to be able to draw itself on the board, it needs a reference to the <strong>canvas context</strong>.</p>
<p>For starters, we can hard-code the values of our piece:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Piece <span class="hljs-keyword">implements</span> IPiece {
  x: <span class="hljs-built_in">number</span>;
  y: <span class="hljs-built_in">number</span>;
  color: <span class="hljs-built_in">string</span>;
  shape: <span class="hljs-built_in">number</span>[][];

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> ctx: CanvasRenderingContext2D</span>) {
    <span class="hljs-built_in">this</span>.spawn();
  }

  spawn() {
    <span class="hljs-built_in">this</span>.color = <span class="hljs-string">'blue'</span>;
    <span class="hljs-built_in">this</span>.shape = [[<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]];

    <span class="hljs-comment">// Position where the shape spawns.</span>
    <span class="hljs-built_in">this</span>.x = <span class="hljs-number">3</span>;
    <span class="hljs-built_in">this</span>.y = <span class="hljs-number">0</span>;
  }
}
</code></pre>
<p>To draw the tetromino on the board, we loop through all the cells of the shape. If the value in the cell is greater than zero, then we color that block:</p>
<pre><code class="lang-ts">draw() {
  <span class="hljs-built_in">this</span>.ctx.fillStyle = <span class="hljs-built_in">this</span>.color;
  <span class="hljs-built_in">this</span>.shape.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">value, x</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (value &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-comment">// this.x &amp; this.y = position on the board</span>
        <span class="hljs-comment">// x &amp; y position are the positions of the shape</span>
        <span class="hljs-built_in">this</span>.ctx.fillRect(<span class="hljs-built_in">this</span>.x + x, <span class="hljs-built_in">this</span>.y + y, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>);
      }
    });
  });
}
</code></pre>
<p>You might have noticed that I set the sides of the block to one. That is tiny, so we need to <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale">scale</a> it to the block size:</p>
<pre><code class="lang-js"><span class="hljs-built_in">this</span>.ctx.scale(BLOCK_SIZE, BLOCK_SIZE);
</code></pre>
<p>The board should keep track of the tetromino on the board so we can create and paint it when we press the play button:</p>
<pre><code class="lang-ts">play() {
  <span class="hljs-built_in">this</span>.board = <span class="hljs-built_in">this</span>.boardService.getEmptyBoard();
  <span class="hljs-built_in">this</span>.piece = <span class="hljs-keyword">new</span> Piece(<span class="hljs-built_in">this</span>.ctx);
  <span class="hljs-built_in">this</span>.piece.draw();
}
</code></pre>
<p>The blue J tetromino appears!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075654225/ZhdpxLznn.png" alt /></p>
<p>Next, let’s see about making things happen through our keyboard.</p>
<h2 id="keyboard-input">Keyboard input</h2>
<p>Now, let’s see how we move pieces on the board. The <code>move</code> function changes the current pieces x or y variable to change its position on the board.</p>
<pre><code class="lang-ts">move(p: IPiece) {
  <span class="hljs-built_in">this</span>.x = p.x;
  <span class="hljs-built_in">this</span>.y = p.y;
}
</code></pre>
<p>Next, we map the keys to the key codes:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> KEY {
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> LEFT = <span class="hljs-number">37</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> RIGHT = <span class="hljs-number">39</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> DOWN = <span class="hljs-number">40</span>;
}
</code></pre>
<p>To match the key events to actions we can use object literal lookups. We need the brackets to get computed property names so that we can use our constants. This is a simplified example of how it works:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> X = <span class="hljs-string">'x'</span>;
<span class="hljs-keyword">const</span> a = { [X]: <span class="hljs-number">5</span> };
<span class="hljs-built_in">console</span>.log(a.x); <span class="hljs-comment">// 5</span>
</code></pre>
<p>We want to send in the current tetromino and return a copy of it together with the change in coordinates. For this, we can use the spread operator to get a shallow copy, and then change the coordinates to our desired position.</p>
<blockquote>
<p>In JavaScript, we can use <strong>shallow copying</strong> to copy primitive data types like numbers and strings. In our case the coordinates are numbers. ES6 offers two shallow copy mechanisms: <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign()</a> and the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">spread operator</a>.</p>
</blockquote>
<p>In other words, a lot is going on in this code snippet:</p>
<pre><code class="lang-ts">moves = {
  [KEY.LEFT]:  (p: IPiece): <span class="hljs-function"><span class="hljs-params">IPiece</span> =&gt;</span> ({ ...p, x: p.x - <span class="hljs-number">1</span> }),
  [KEY.RIGHT]: (p: IPiece): <span class="hljs-function"><span class="hljs-params">IPiece</span> =&gt;</span> ({ ...p, x: p.x + <span class="hljs-number">1</span> }),
  [KEY.UP]:    (p: IPiece): <span class="hljs-function"><span class="hljs-params">IPiece</span> =&gt;</span> ({ ...p, y: p.y + <span class="hljs-number">1</span> })
};
</code></pre>
<p>Which we can use like this to get the new state without mutating the original piece. It’s important because we don’t always want to move to a new position.</p>
<pre><code>const p = <span class="hljs-emphasis">*this*</span>.moves[<span class="hljs-string">event.key</span>](<span class="hljs-link">*this*.piece</span>);
</code></pre><p>To listen for keyboard events, we can use the <a target="_blank" href="https://angular.io/api/core/HostListener">@HostListener</a> decorator within our board component:</p>
<pre><code class="lang-ts"><span class="hljs-meta">@HostListener</span>(<span class="hljs-string">'window:keydown'</span>, [<span class="hljs-string">'$event'</span>])
keyEvent(event: KeyboardEvent) {
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.moves[event.keyCode]) {
    <span class="hljs-comment">// If the keyCode exists in our moves stop the event from bubbling.</span>
    event.preventDefault();
    <span class="hljs-comment">// Get the next state of the piece.</span>
    <span class="hljs-keyword">const</span> p = <span class="hljs-built_in">this</span>.moves[event.key](<span class="hljs-built_in">this</span>.piece);
    <span class="hljs-comment">// Move the piece</span>
    <span class="hljs-built_in">this</span>.piece.move(p);
    <span class="hljs-comment">// Clear the old position before drawing</span>
    <span class="hljs-built_in">this</span>.ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-built_in">this</span>.ctx.canvas.width, <span class="hljs-built_in">this</span>.ctx.canvas.height);
    <span class="hljs-comment">// Draw the new position.</span>
    <span class="hljs-built_in">this</span>.piece.draw();
  }
}
</code></pre>
<p>Now we are listening on the keyboard events, and if we press left, right, or down arrows, then we can see the piece moving.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075655483/v1HNWigXk.gif" alt /></p>
<p>We have a movement! However, ghost pieces going through walls are not what we want. 👻</p>
<h2 id="collision-detection">Collision detection</h2>
<p>Tetris would not be a particularly exciting game if all blocks could pass through each other, or if the walls and floor did not stop them. So instead of moving the tetromino, we’ll check for potential collisions first, and then only move the tetromino if it’s safe. We have a few different collisions to consider.</p>
<p>We have a collision when the tetromino:</p>
<ul>
<li><p>Hits the floor.</p>
</li>
<li><p>Moves left or right into a wall.</p>
</li>
<li><p>Hits a block on the board.</p>
</li>
<li><p>Rotates, and the new rotation hits a wall or block.</p>
</li>
</ul>
<p>We already defined the potential new position for the shape. Now we can add a check if this position is valid before we move to it. To check for collisions, we loop through all the spaces in the grid that the tetromino would take up in its potential new position.</p>
<p>The array method best suited for this is <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every">every()</a>. With it, we can check whether all elements in the array pass the tests we provide. We calculate the coordinates of every block of the piece and check that it’s a valid position:</p>
<pre><code class="lang-ts">valid(p: IPiece): <span class="hljs-built_in">boolean</span> {
  <span class="hljs-keyword">return</span> p.shape.every(<span class="hljs-function">(<span class="hljs-params">row, dy</span>) =&gt;</span> {
    <span class="hljs-keyword">return</span> row.every(<span class="hljs-function">(<span class="hljs-params">value, dx</span>) =&gt;</span> {
      <span class="hljs-keyword">let</span> x = p.x + dx;
      <span class="hljs-keyword">let</span> y = p.y + dy;
      <span class="hljs-keyword">return</span> (
        <span class="hljs-built_in">this</span>.isEmpty(value) ||
       (<span class="hljs-built_in">this</span>.insideWalls(x) &amp;&amp;
        <span class="hljs-built_in">this</span>.aboveFloor(y)
      );
    });
  });
}
</code></pre>
<p>By using this method before we move, we make sure that we don’t move anywhere we shouldn’t:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.service.valid(p)) {
  <span class="hljs-built_in">this</span>.piece.move(p);
}
</code></pre>
<p>Let’s try going outside the grid again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075656847/diuTrSor_.gif" alt /></p>
<p>No more ghosting! We can’t leave the playing area anymore.</p>
<p>Now that the floor stops the tetromino, we can add another move called the hard drop. Pressing space drops the tetromino until it collides with something. And remember we need to add the new key mapping and move:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> KEY {
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> SPACE = <span class="hljs-number">32</span>;
  <span class="hljs-comment">// ...</span>
}

moves = {
  [KEY.SPACE]: (p: IPiece): <span class="hljs-function"><span class="hljs-params">IPiece</span> =&gt;</span> ({ ...p, y: p.y + <span class="hljs-number">1</span> })
  <span class="hljs-comment">// ...</span>
};

<span class="hljs-keyword">if</span> (event.keyCode === KEY.SPACE) {
  <span class="hljs-keyword">while</span> (<span class="hljs-built_in">this</span>.service.valid(p, <span class="hljs-built_in">this</span>.board)) {
    <span class="hljs-built_in">this</span>.piece.move(p);
    p = <span class="hljs-built_in">this</span>.moves[KEY.DOWN](<span class="hljs-built_in">this</span>.piece);
  }
}
</code></pre>
<p>What’s next?</p>
<h2 id="rotation">Rotation</h2>
<p>Now we can move around, but it would not be any fun if we can’t rotate the piece. We need to rotate the tetrominos around their center.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075658349/XnNyZOHBU.png" alt /></p>
<p>It has been a while since I studied <a target="_blank" href="https://en.wikipedia.org/wiki/Rotation_matrix">linear algebra</a> in school. But, to rotate clockwise goes something like this:</p>
<blockquote>
<p><em>A rotation by 90 degrees can be accomplished by two reflections at a 45-degree angle so you can take the transpose of the matrix and then multiply it by the permutation matrix that reverses the order of the columns.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075659628/axjXU_8QL.png" alt /></p>
<p>And in JavaScript:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// Transpose matrix</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> y = <span class="hljs-number">0</span>; y &lt; <span class="hljs-built_in">this</span>.shape.length; ++y) {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt; y; ++x) {
    [<span class="hljs-built_in">this</span>.shape[x][y], <span class="hljs-built_in">this</span>.shape[y][x]] = 
    [<span class="hljs-built_in">this</span>.shape[y][x], <span class="hljs-built_in">this</span>.shape[x][y]];
  }
}

<span class="hljs-comment">// Reverse the order of the columns.</span>
<span class="hljs-built_in">this</span>.shape.forEach(<span class="hljs-function"><span class="hljs-params">row</span> =&gt;</span> row.reverse());
</code></pre>
<p>We can add a function that rotates the shape. Earlier we used the spread operator to clone the coordinates. In this case, we are working with a multiple level array but the spread operator only copies one level deep. The rest is copied by reference.</p>
<p>I’m instead using <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">JSON.parse</a> and <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">JSON.stringify</a>. The <code>**stringify()</code><strong> method converts the matrix to a JSON string. The `</strong>parse()`** method parses the JSON string, constructing our matrix back again to a clone.</p>
<pre><code class="lang-ts">rotate(p: IPiece): IPiece {
  <span class="hljs-comment">// Cloning with JSON</span>
  <span class="hljs-keyword">let</span> clone: IPiece = <span class="hljs-built_in">JSON</span>.parse(<span class="hljs-built_in">JSON</span>.stringify(p));

  <span class="hljs-comment">// Do algorithm</span>

  <span class="hljs-keyword">return</span> clone;
}
</code></pre>
<p>Then we add a new state for ArrowUp in <code>board.component.ts</code>.</p>
<pre><code class="lang-ts">[KEY.UP]: (p: IPiece): <span class="hljs-function"><span class="hljs-params">IPiece</span> =&gt;</span> <span class="hljs-built_in">this</span>.service.rotate(p)
</code></pre>
<p>Now we rotate!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075660873/1O5ybg5BE.gif" alt /></p>
<h2 id="randomize-tetromino">Randomize Tetromino</h2>
<p>To be able to get different kinds of pieces, we need to add a bit of randomization to our code.</p>
<p>Following the <a target="_blank" href="https://tetris.fandom.com/wiki/SRS">Super Rotation System</a>, we can take the first position of the pieces and add them to our constants together with the colors:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> COLORS = [
  <span class="hljs-string">'cyan'</span>,
  <span class="hljs-string">'blue'</span>,
  <span class="hljs-string">'orange'</span>,
  <span class="hljs-string">'yellow'</span>,
  <span class="hljs-string">'green'</span>,
  <span class="hljs-string">'purple'</span>,
  <span class="hljs-string">'red'</span>
];
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> SHAPES = [
  [[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>], [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]],
  [[<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]]
  <span class="hljs-comment">// And so on</span>
];
</code></pre>
<p>We need to randomize the index of one of these to pick one piece. To get a random number, we create a function that uses the length of the array.</p>
<pre><code class="lang-ts">randomizeTetrominoType(noOfTypes: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * noOfTypes);
}
</code></pre>
<p>With this method we can get a random tetromino type when we spawn and then set the color and shape from it:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> typeId = <span class="hljs-built_in">this</span>.randomizeTetrominoType(COLORS.length);
<span class="hljs-built_in">this</span>.shape = SHAPES[typeId];
<span class="hljs-built_in">this</span>.color = COLORS[typeId];
</code></pre>
<p>If we press play the page shows pieces with different shapes and colors.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075662307/HHzV5IYHO.gif" alt /></p>
<h2 id="game-loop">Game Loop</h2>
<p>Almost all games have one main function that keeps the game running even when the user isn’t doing anything. This cycle of running the same core function over and over again is called the game loop. In our game, we need a game loop that moves the tetrominos down the screen.</p>
<h3 id="requestanimationframe">RequestAnimationFrame</h3>
<p>To create our game loop, we can use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame">requestAnimationFrame</a>. It tells the browser that we want to animate, and it should call a function to update an animation before the next repaint. In other words, we tell the browser: “Next time you paint on the screen, also run this function because I want to paint something too.”</p>
<blockquote>
<h1 id="animation-is-not-the-art-of-drawings-that-move-but-the-art-of-movements-that-are-drawn-norman-mclaren">“Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren</h1>
</blockquote>
<p>The way to animate with <code>window.requestAnimationFrame()</code> is to create a function that paints a frame and then re-schedules itself. We need to bind the call to <code>this</code>, or it has the window object as its context. Since it doesn't contain the animate function, we get an error.</p>
<pre><code class="lang-ts">animate() {
  <span class="hljs-built_in">this</span>.piece.draw();
  requestAnimationFrame(<span class="hljs-built_in">this</span>.animate.bind(<span class="hljs-built_in">this</span>));
}
</code></pre>
<p>We can remove all our previous calls to <code>draw()</code> and instead call <code>animate()</code> from the <code>play()</code> function to start the animation. If we try our game, it should still run like before.</p>
<h3 id="timer">Timer</h3>
<p>Next, we need a timer. Every time frame, we drop the tetromino. There is an <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame#Notes">example</a> on the MDN page that we can modify to our needs.</p>
<p>We start by creating an object with the info we need:</p>
<pre><code><span class="hljs-string">time</span> <span class="hljs-string">=</span> { <span class="hljs-attr">start:</span> <span class="hljs-number">0</span>, <span class="hljs-attr">elapsed:</span> <span class="hljs-number">0</span>, <span class="hljs-attr">level:</span> <span class="hljs-number">1000</span> }<span class="hljs-string">;</span>
</code></pre><p>In the game loop, we update our game state based on the time interval and then draw the result:</p>
<pre><code class="lang-ts">animate(now = <span class="hljs-number">0</span>) {
  <span class="hljs-comment">// Update elapsed time.</span>
  <span class="hljs-built_in">this</span>.time.elapsed = now - <span class="hljs-built_in">this</span>.time.start;
  <span class="hljs-comment">// If elapsed time has passed time for current level</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.time.elapsed &gt; <span class="hljs-built_in">this</span>.time.level) {
    <span class="hljs-comment">// Reset start time</span>
    <span class="hljs-built_in">this</span>.time.start = now;
    <span class="hljs-built_in">this</span>.drop();
  }
  <span class="hljs-built_in">this</span>.draw();
  requestAnimationFrame(<span class="hljs-built_in">this</span>.animate.bind(<span class="hljs-built_in">this</span>));
}
</code></pre>
<p>We have animation!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075664126/KuY3_qrWD.gif" alt /></p>
<p>Next, let’s look at what happens when we reach the bottom.</p>
<h2 id="freeze">Freeze</h2>
<p>When we can’t move down anymore, we should freeze the piece and spawn a new one. Let’s start by defining <code>freeze()</code>. This function merges the tetromino blocks to the board:</p>
<p>We can’t see anything yet, but by logging the representation of the board, we can see that the shape is on the board.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075665595/WD2tr0lKP.png" alt /></p>
<p>Let’s add a function that draws the board:</p>
<pre><code class="lang-ts">freeze() {
  <span class="hljs-built_in">this</span>.piece.shape.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {
    row.forEach(<span class="hljs-function">(<span class="hljs-params">value, x</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (value &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-built_in">this</span>.board[y + <span class="hljs-built_in">this</span>.piece.y][x + <span class="hljs-built_in">this</span>.piece.x] = value;
      }
    });
  });
}
</code></pre>
<p>Now the draw function should look like this:</p>
<pre><code class="lang-ts">draw() {
  <span class="hljs-built_in">this</span>.ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-built_in">this</span>.ctx.canvas.width, <span class="hljs-built_in">this</span>.ctx.canvas.height);
  <span class="hljs-built_in">this</span>.piece.draw();
  <span class="hljs-built_in">this</span>.drawBoard();
}
</code></pre>
<p>If we run the game, we can see that the pieces are showing up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075666824/aUSjbSaNb.png" alt /></p>
<p>Now that we are freezing the pieces, we need to add new collision detection. This time we have to make sure that we don’t collide with frozen tetrominos on the board. We can do this by checking that the cell is zero. Add this to the <code>valid</code> method and send in the board as an argument:</p>
<pre><code>board[<span class="hljs-string">p.y + y</span>][<span class="hljs-symbol">p.x + x</span>] === 0;
</code></pre><p>Now that we are adding pieces to the board it will quickly get crowded. We should do something about that.</p>
<h2 id="line-clear">Line clear</h2>
<p>To last longer, we need to assemble the tetrominos in rows of blocks that span the entire row, resulting in a line clear. When you do so, the row disappears, causing the ones above it to settle.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075668026/mS6TMwFua.png" alt /></p>
<p>Detecting formed lines is as easy as checking if it has any zeros:</p>
<pre><code class="lang-ts"><span class="hljs-built_in">this</span>.board.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {
  <span class="hljs-comment">// If every value is greater than 0.</span>
  <span class="hljs-keyword">if</span> (row.every(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> value &gt; <span class="hljs-number">0</span>)) {
    <span class="hljs-comment">// Remove the row.</span>
    <span class="hljs-built_in">this</span>.board.splice(y, <span class="hljs-number">1</span>);
    <span class="hljs-comment">// Add a zero filled at the top.</span>
    <span class="hljs-built_in">this</span>.board.unshift(<span class="hljs-built_in">Array</span>(COLS).fill(<span class="hljs-number">0</span>));
  }
});
</code></pre>
<p>We can add a call to this <code>clearLines()</code> function after the <code>freeze()</code> call. We can try playing and hopefully see the rows getting cleared.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075669371/7e0Jwoz7o.gif" alt /></p>
<h2 id="points">Points</h2>
<p>To get a bit more excitement, we need a points system. From the Tetris guideline we get these values:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Points {
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> SINGLE = <span class="hljs-number">100</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> DOUBLE = <span class="hljs-number">300</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> TRIPLE = <span class="hljs-number">500</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> TETRIS = <span class="hljs-number">800</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> SOFT_DROP = <span class="hljs-number">1</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> HARD_DROP = <span class="hljs-number">2</span>;
}
</code></pre>
<p>Let’s add the points for soft and hard drops first in our event handler:</p>
<pre><code class="lang-ts"><span class="hljs-meta">@HostListener</span>(<span class="hljs-string">'window:keydown'</span>, [<span class="hljs-string">'$event'</span>])
  keyEvent(event: KeyboardEvent) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.moves[event.key]) {
      event.preventDefault();
      <span class="hljs-keyword">let</span> p: ITetromino = <span class="hljs-built_in">this</span>.moves[event.key](<span class="hljs-built_in">this</span>.piece);
      <span class="hljs-keyword">if</span> (event.key === <span class="hljs-string">' '</span>) {
        <span class="hljs-keyword">while</span> (<span class="hljs-built_in">this</span>.service.valid(p, <span class="hljs-built_in">this</span>.board)) {
          <span class="hljs-built_in">this</span>.points += Points.HARD_DROP; <span class="hljs-comment">// Points for every drop</span>
          <span class="hljs-built_in">this</span>.piece.move(p);
          p = <span class="hljs-built_in">this</span>.moves[<span class="hljs-string">' '</span>](<span class="hljs-built_in">this</span>.piece);
        }
      } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.service.valid(p, <span class="hljs-built_in">this</span>.board)) {
        <span class="hljs-built_in">this</span>.piece.move(p);
        <span class="hljs-keyword">if</span> (event.key === <span class="hljs-string">'ArrowDown'</span>) {
          <span class="hljs-built_in">this</span>.points += Points.SOFT_DROP; <span class="hljs-comment">// Points if we move down</span>
        }
      }
    }
  }
</code></pre>
<p>Now for the line clear points. Depending on the number of lines, we get the defined points:</p>
<pre><code class="lang-ts">getLineClearPoints(lines: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">number</span> {
  <span class="hljs-keyword">return</span> lines === <span class="hljs-number">1</span> ? Points.SINGLE :
         lines === <span class="hljs-number">2</span> ? Points.DOUBLE :
         lines === <span class="hljs-number">3</span> ? Points.TRIPLE :
         lines === <span class="hljs-number">4</span> ? Points.TETRIS : <span class="hljs-number">0</span>;
}
</code></pre>
<p>For this to work, we need to add a bit of logic to count how many lines we clear:</p>
<pre><code class="lang-ts">clearLines() {
  <span class="hljs-keyword">let</span> lines = <span class="hljs-number">0</span>; <span class="hljs-comment">// Set variable</span>
  <span class="hljs-built_in">this</span>.board.forEach(<span class="hljs-function">(<span class="hljs-params">row, y</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (row.every(<span class="hljs-function"><span class="hljs-params">value</span> =&gt;</span> value !== <span class="hljs-number">0</span>)) {
      lines++; <span class="hljs-comment">// Increase for cleared line</span>
      <span class="hljs-built_in">this</span>.board.splice(y, <span class="hljs-number">1</span>);
      <span class="hljs-built_in">this</span>.board.unshift(<span class="hljs-built_in">Array</span>(COLS).fill(<span class="hljs-number">0</span>));
    }
  });
  <span class="hljs-keyword">if</span> (lines &gt; <span class="hljs-number">0</span>) {
    <span class="hljs-comment">// Add points if we cleared some lines</span>
    <span class="hljs-built_in">this</span>.points += <span class="hljs-built_in">this</span>.getLineClearPoints(lines);
  }
}
</code></pre>
<p>If we try playing now, we can see that we are increasing our score.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075670924/6afzDCvCH.gif" alt /></p>
<h2 id="levels">Levels</h2>
<p>When we get better at Tetris, the speed we start on will get too easy. And too easy means boring. So we need to increase the level of difficulty. We do this by decreasing the interval speed in our game loop.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> LINES_PER_LEVEL = <span class="hljs-number">10</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Level {
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-number">0</span> = <span class="hljs-number">800</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-number">1</span> = <span class="hljs-number">720</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-number">2</span> = <span class="hljs-number">630</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-number">3</span> = <span class="hljs-number">550</span>;
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>We can also show the player which level they are currently on. The logic of keeping track and showing levels and lines is the same as for points. We initialize a value for them, and when we start a new game, we have to reset them.</p>
<p>We can move the initialization of the game to a function and call it in <code>ngOnInit</code> and <code>play</code>:</p>
<pre><code class="lang-ts">resetGame() {
  <span class="hljs-built_in">this</span>.points = <span class="hljs-number">0</span>; 
  <span class="hljs-built_in">this</span>.lines = <span class="hljs-number">0</span>;
  <span class="hljs-built_in">this</span>.level = <span class="hljs-number">0</span>;
  <span class="hljs-built_in">this</span>.board = <span class="hljs-built_in">this</span>.getEmptyBoard();
}
</code></pre>
<p>Depending on the level we get more points for line clears. We multiply the points with the level we are on. And since we start on level 0 add one to it:</p>
<pre><code>(<span class="hljs-keyword">level</span> + <span class="hljs-number">1</span>) * lineClearPoints;
</code></pre><p>We increase the level every time we reach the lines we have per level. We also need to add the time we have on this level:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">if</span> (lines &gt; <span class="hljs-number">0</span>) {
  <span class="hljs-comment">// Calculate points from cleared lines and level.</span>

  <span class="hljs-built_in">this</span>.points += <span class="hljs-built_in">this</span>.service.getLinesClearedPoints(lines, <span class="hljs-built_in">this</span>.level);
  <span class="hljs-built_in">this</span>.lines += lines;

  <span class="hljs-comment">// If we have reached the lines per level</span>
  <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.lines &gt;= LINES_PER_LEVEL) {
    <span class="hljs-comment">// Goto next level</span>
    <span class="hljs-built_in">this</span>.level++;

    <span class="hljs-comment">// Remove lines so we start working for the next level</span>
    <span class="hljs-built_in">this</span>.lines -= LINES_PER_LEVEL;

    <span class="hljs-comment">// Increase speed of game.</span>
    <span class="hljs-built_in">this</span>.time.level = Level[<span class="hljs-built_in">this</span>.level];
  }
}
</code></pre>
<p>Now if we play and clear 10 lines we should see the level increase and our points score double. And of course the game starts moving a bit faster.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075672592/Xs4fruyq6.gif" alt /></p>
<h2 id="game-over">Game Over</h2>
<p>If you play for a while, you notice that the game never ends. The tetrominos keep on falling forever. So we need to know when to end the game.</p>
<p>After we drop we can check if we are still on row 0 and in that case, we can stop the game by exiting the game loop function:</p>
<pre><code><span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.piece.y === <span class="hljs-number">0</span>) {
  <span class="hljs-keyword">this</span>.gameOver();
  <span class="hljs-keyword">return</span>;
}
</code></pre><p>Before we exit, we call <code>cancelAnimationFrame</code> to stop it. Also, we print a message to the user.</p>
<pre><code class="lang-ts">gameOver() {
  cancelAnimationFrame(<span class="hljs-built_in">this</span>.requestId);
  <span class="hljs-built_in">this</span>.ctx.fillStyle = ‘black’;
  <span class="hljs-built_in">this</span>.ctx.fillRect(<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">1.2</span>);
  <span class="hljs-built_in">this</span>.ctx.font = ‘<span class="hljs-number">1</span>px Arial’;
  <span class="hljs-built_in">this</span>.ctx.fillStyle = ‘red’;
  <span class="hljs-built_in">this</span>.ctx.fillText(‘GAME OVER’, <span class="hljs-number">1.8</span>, <span class="hljs-number">4</span>);
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075674168/jx73LZCWf.png" alt /></p>
<h2 id="next-tetromino">Next tetromino</h2>
<p>Let’s add one last thing. The next tetromino. We can add another canvas for this:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> #<span class="hljs-attr">next</span> <span class="hljs-attr">class</span>=<span class="hljs-string">”next”</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
</code></pre><p>Next, we do as we did for our first canvas:</p>
<pre><code class="lang-ts"><span class="hljs-meta">@ViewChild</span>(<span class="hljs-string">'next'</span>, { <span class="hljs-keyword">static</span>: <span class="hljs-literal">true</span> })
canvasNext: ElementRef&lt;HTMLCanvasElement&gt;;

ctxNext: CanvasRenderingContext2D;

initNext() {
  <span class="hljs-built_in">this</span>.ctxNext = <span class="hljs-built_in">this</span>.canvasNext.nativeElement.getContext(<span class="hljs-string">'2d'</span>);

  <span class="hljs-comment">// Size it for four blocks.</span>
  <span class="hljs-built_in">this</span>.ctxNext.canvas.width = <span class="hljs-number">4</span> * BLOCK_SIZE;
  <span class="hljs-built_in">this</span>.ctxNext.canvas.height = <span class="hljs-number">4</span> * BLOCK_SIZE;

  <span class="hljs-built_in">this</span>.ctxNext.scale(BLOCK_SIZE, BLOCK_SIZE);
}

<span class="hljs-comment">// Create and draw it in play function</span>
play() {
  <span class="hljs-comment">// ...</span>
  <span class="hljs-built_in">this</span>.next = <span class="hljs-keyword">new</span> Piece(<span class="hljs-built_in">this</span>.ctx);
  <span class="hljs-built_in">this</span>.next.drawNext(<span class="hljs-built_in">this</span>.ctxNext);
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>We have to change the logic a bit in the <code>drop</code> function. Instead of creating a new piece we set it to the next and instead create a new next piece:</p>
<pre><code class="lang-ts"><span class="hljs-built_in">this</span>.piece = <span class="hljs-built_in">this</span>.next;
<span class="hljs-built_in">this</span>.next = <span class="hljs-keyword">new</span> Piece(<span class="hljs-built_in">this</span>.ctx);
<span class="hljs-built_in">this</span>.next.drawNext(<span class="hljs-built_in">this</span>.ctxNext);
</code></pre>
<p>Now we can be a bit more strategic when we see the next piece coming.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075675515/czygp5Bfe.png" alt /></p>
<h2 id="improvements">Improvements</h2>
<p>There are always improvements that to be made to a game. Some that I can think of:</p>
<ul>
<li><p>Highscore</p>
</li>
<li><p>Pause</p>
</li>
<li><p>Music and FX</p>
</li>
<li><p>AI</p>
</li>
</ul>
<p>So why not fork the repository and implement them!</p>
<h2 id="conclusion">Conclusion</h2>
<p>Today we made a game! We learned how to represent and track the objects we paint on the screen. We learned to move these objects and to respond to the boundaries of the game. I had a lot of fun with this project, and I recommend it as a way of honing your programming skills.</p>
<p>And now that we have taken our first steps into game development, the only question that remains is: What game is next?</p>
<p>Thanks to <a target="_blank" href="https://twitter.com/tim_deschryver">Tim Deschryver</a> for reviewing the article and code.</p>
<p><a target="_blank" href="https://github.com/melcor76/ng-tetris/tree/blog">Code on GitHub</a></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[How to talk with Web Components in React and Angular]]></title><description><![CDATA[In this article, I use Nx to create a monorepo with applications in Angular and React, and a library with Angular Elements. Then we consume these custom elements and communicate with them in our apps.
Here’s what we create in this article:

The appli...]]></description><link>https://blog.michaelkaren.dev/how-to-talk-with-web-components-in-react-and-angular-8deb7d2fb92a</link><guid isPermaLink="true">https://blog.michaelkaren.dev/how-to-talk-with-web-components-in-react-and-angular-8deb7d2fb92a</guid><category><![CDATA[Angular]]></category><category><![CDATA[React]]></category><category><![CDATA[Web Components]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 22 Jul 2019 08:01:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075556799/sWtEABCMH.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this article, I use <strong>Nx</strong> to create a monorepo with applications in <strong>Angular</strong> and<strong> React, </strong>and a library with <strong>Angular Elements</strong>. Then we consume these <strong>custom elements</strong> and communicate with them in our apps.</p>
<p>Here’s what we create in this article:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075529522/kDEN0YnQH.gif" alt /></p>
<p>The application we create has one page for Angular and one for React. The add button and shopping cart are Web Components made with Angular Elements. There is no state between the pages. The main point of the article is to show how we can use the same custom elements in different frameworks.</p>
<p>This isn’t a deep-dive, but I will walk-through the important parts for Web Component support in Angular and React. I’m not going to present all the HTML and CSS that I use but if you want to follow along all the code is here: <a target="_blank" href="https://github.com/melcor76/reactangular">Example code on GitHub.</a> 📜</p>
<h2 id="web-components">Web Components</h2>
<p>Web Components is a web standard for defining new HTML elements in a framework-agnostic way. Since Web Components build on web standards, it opens up opportunities for code sharing across JavaScript frameworks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075531451/MFfuuPRZ0.jpeg" alt /></p>
<p>Web Components are a <strong>set of technologies</strong> that let you create custom HTML elements compatible with regular HTML:</p>
<ul>
<li><p><a target="_blank" href="https://w3c.github.io/webcomponents/spec/custom/">Custom Elements</a> to create custom HTML Elements.</p>
</li>
<li><p><a target="_blank" href="https://w3c.github.io/webcomponents/spec/shadow/">Shadow DOM</a> encapsulates style and markup.</p>
</li>
<li><p><a target="_blank" href="https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-module-system">ES Modules</a> for module handling.</p>
</li>
<li><p><a target="_blank" href="https://html.spec.whatwg.org/multipage/scripting.html#the-template-element/">HTML Template</a> to declare content that can be rendered at run-time.</p>
</li>
</ul>
<p>If you are interested in gaining more knowledge in this technology, then I recommend reading these articles:</p>
<ul>
<li><p><a target="_blank" href="https://medium.com/angular-in-depth/developments-in-web-components-im-excited-about-in-2019-3ae7751c2f64">Developments in Web Components I’m excited about in 2019</a> by <a target="_blank" href="https://twitter.com/maxkoretskyi">Max Koretskyi aka Wizard</a></p>
</li>
<li><p><a target="_blank" href="https://ultimatecourses.com/blog/the-ultimate-guide-to-web-components">The Ultimate Guide to Web Components</a> by <a target="_blank" href="https://medium.com/@stefannhs">Stefan Nieuwenhuis</a></p>
</li>
<li><p><a target="_blank" href="https://link.medium.com/IspQ4OluwY">The State of Web Components</a> by me</p>
</li>
</ul>
<h2 id="angular-elements">Angular Elements</h2>
<p><a target="_blank" href="https://angular.io/guide/elements">Angular Elements</a> provides a way to convert Angular components to native Web Components.</p>
<p>The <code>@angular/elements</code> package exports a <code>[createCustomElement](https://angular.io/api/elements/createCustomElement)()</code> API that provides a bridge from Angular's component interface and change detection functionality to the built-in DOM API.</p>
<p>Transforming a component to a <em>custom element</em> makes all of the required Angular infrastructure available to the browser, mapping Angular functionality to the corresponding native HTML equivalents.</p>
<p>For more in-depth on Angular Elements, check out these articles by <a target="_blank" href="https://twitter.com/Jialipassion">Jia Li</a>:</p>
<ul>
<li><p><a target="_blank" href="https://medium.com/angular-in-depth/angular-elements-how-does-this-magic-work-under-the-hood-3684a0b2be95">Angular Elements: how does this magic work under the hood?</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/angular-in-depth/how-angular-elements-uses-custom-events-mechanism-to-transmit-components-outputs-outside-angular-7b469386f6e2">Learn how Angular Elements transmits Component’s @Outputs outside Angular</a></p>
</li>
</ul>
<p>OK, I wanted to keep the intro brief so we can start coding! 😏</p>
<h2 id="creating-the-workspace">Creating the Workspace</h2>
<p>Since we want to be able to use React, the Angular CLI is not enough this time. Fortunately, <a target="_blank" href="https://nrwl.io/">Nrwl</a> has developed the open-source toolkit <a target="_blank" href="https://nx.dev/angular">Nx</a> that extends the Angular CLI capabilities to <a target="_blank" href="https://nx.dev/angular/guides/react">React</a> and helps us manage workspaces in a <a target="_blank" href="https://en.wikipedia.org/wiki/Monorepo">monorepo</a> way.</p>
<p>We are using Nx to build Angular and React applications with a library of shared web components. Let’s start by creating a workspace:</p>
<pre><code>npx <span class="hljs-keyword">create</span>-nx-workspace reactangular
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075533145/6eDGdoXB1.png" alt /></p>
<p>I’m starting with an empty workspace. After the installation, we need to add Angular and React capabilities to the workspace:</p>
<pre><code><span class="hljs-attribute">cd</span> reactangular
ng add <span class="hljs-variable">@nrwl</span>/angular
ng add <span class="hljs-variable">@nrwl</span>/react
</code></pre><p>Now, we are ready to create the applications.</p>
<h2 id="angular-app">Angular App</h2>
<p>First, we create an Angular application:</p>
<pre><code><span class="hljs-attribute">ng</span> g <span class="hljs-variable">@nrwl</span>/angular:app angularapp --defaults
</code></pre><p>I have added some HTML and styles to spice the page up. It’s not relevant to our story of web components, but if you are interested, you can check the code on <a target="_blank" href="https://github.com/melcor76/reactangular/tree/master/apps/angularapp/src/app">GitHub</a>. Let’s make sure that it’s working:</p>
<pre><code><span class="hljs-attribute">ng</span> serve -o angularapp
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075534677/cJ9jYh3vh.png" alt /></p>
<p>The first application is working! Awesome! 😻</p>
<p>Let’s see if we can get React working now that we have the ball rolling.</p>
<h2 id="react-app">React App</h2>
<p>Next, we create a React application:</p>
<pre><code><span class="hljs-attribute">ng</span> g <span class="hljs-variable">@nrwl</span>/react:app reactapp --defaults
</code></pre><p>Also, I added a bit of fragrance to the <a target="_blank" href="https://github.com/melcor76/reactangular/tree/master/apps/reactapp/src/app">code</a>. Now let’s check that it runs:</p>
<pre><code><span class="hljs-attribute">ng</span> serve reactapp
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075537105/GDupA72nf.png" alt /></p>
<p>It’s also working! Beautiful! 😍</p>
<p>Let’s have a look at the scripts next to get a better developer experience.</p>
<h2 id="running-in-parallel">Running in parallel</h2>
<p>Since we have to run more than one application at once, I use a package called <a target="_blank" href="https://www.npmjs.com/package/concurrently">Concurrently</a> to run multiple commands in parallel.</p>
<pre><code>npm i <span class="hljs-keyword">concurrently</span> -D
</code></pre><p>In this case, I want to start my Angular and React applications at the same time, so edit the <em>start</em> script in<code>package.json.</code></p>
<pre><code>"start": "concurrently \"ng serve -o angularapp\" \"ng serve reactapp <span class="hljs-comment">--port 4201\""</span>
</code></pre><p>Since we need to use different ports, we send in the port flag to the React app. So, instead of running scripts in two terminals, we can just run:</p>
<pre><code>npm <span class="hljs-keyword">start</span>
</code></pre><p>We can start both applications with one script! 🎉</p>
<p>Now that we have our applications running let’s start with the elements library.</p>
<h2 id="angular-elements-library">Angular Elements Library</h2>
<p>We can add a new library project for our Angular Elements:</p>
<pre><code><span class="hljs-attribute">ng</span> g <span class="hljs-variable">@nrwl</span>/angular:lib elements --defaults
</code></pre><p>With one CLI command, we add the elements package and make changes in <code>angular.json</code>:</p>
<pre><code><span class="hljs-attribute">ng</span> add <span class="hljs-variable">@angular</span>/elements
</code></pre><h3 id="add-to-cart-button">Add-to-cart Button</h3>
<p>Now let’s create <code>add-to-cart.component</code> that has the input property <code>type</code> to know what we are adding to the cart and then outputs the <code>addToCart</code> event with this type.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { Component, EventEmitter, Output, Input } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component</span>({
  template: <span class="hljs-string">`
    &lt;button mat-raised-button color="primary" (click)="add()"&gt;Buy&lt;/button&gt;
  `</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AddToCartComponent {
  <span class="hljs-meta">@Input</span>() <span class="hljs-keyword">type</span>: <span class="hljs-built_in">string</span>;
  <span class="hljs-meta">@Output</span>() addToCart = <span class="hljs-keyword">new</span> EventEmitter&lt;<span class="hljs-built_in">string</span>&gt;();

  add() {
    <span class="hljs-built_in">this</span>.addToCart.emit(<span class="hljs-built_in">this</span>.type);
  }
}
</code></pre>
<p>Now that we have the component, we need to change <code>elements.module.ts</code> to define it as a custom element. Notice, that we do not have a regular bootstrap. Instead, we do a manual bootstrap where we define the custom element and then add it to <a target="_blank" href="https://angular.io/guide/entry-components">entryComponents</a>.</p>
<blockquote>
<p>A component can also be bootstrapped imperatively in the module’s <code>*ngDoBootstrap()</code><em> method. The `</em>@NgModule.bootstrap`* property tells the compiler that this is an entry component and it should generate code to bootstrap the application with this component.</p>
</blockquote>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { NgModule, Injector } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { CommonModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common'</span>;
<span class="hljs-keyword">import</span> { BrowserModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/platform-browser'</span>;
<span class="hljs-keyword">import</span> { createCustomElement } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/elements'</span>;
<span class="hljs-keyword">import</span> { AddToCartComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">'./add-to-cart.component'</span>;

<span class="hljs-meta">@NgModule</span>({
  imports: [BrowserModule, CommonModule],
  declarations: [AddToCartComponent],
  entryComponents: [AddToCartComponent]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> ElementsModule {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> injector: Injector</span>) {}

  ngDoBootstrap() {
    <span class="hljs-keyword">const</span> el = createCustomElement(AddToCartComponent, {
      injector: <span class="hljs-built_in">this</span>.injector
    });

    customElements.define(<span class="hljs-string">`add-to-cart-button`</span>, el);
  }
}
</code></pre>
<p>Now, that we have registered the custom element, let’s see how we use it. Wait! I almost forgot one thing. For a pleasant development experience, you can add this code to <code>index.ts.</code></p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { platformBrowserDynamic } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/platform-browser-dynamic'</span>;
<span class="hljs-keyword">import</span> { ElementsModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./lib/elements.module'</span>;

platformBrowserDynamic()
  .bootstrapModule(ElementsModule)
  .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(err));
</code></pre>
<p>If you want to take the next step and build your Angular Elements then <a target="_blank" href="https://twitter.com/ManfredSteyer">Manfred Steyer</a> is your guy. Check out his tool <a target="_blank" href="https://www.npmjs.com/package/ngx-build-plus">ngx-build-plus</a> and his articles on this subject:</p>
<ul>
<li><a target="_blank" href="https://www.softwarearchitekt.at/post/2019/01/27/building-angular-elements-with-the-cli.aspx">Your Options For Building Angular Elements With The CLI</a></li>
</ul>
<h2 id="web-component-in-angular">Web component in Angular</h2>
<p>It’s time to consume our custom element in Angular. First of all, we need to import it in <code>app.component.ts</code>:</p>
<pre><code><span class="hljs-attribute">import</span> <span class="hljs-string">'<span class="hljs-variable">@reactangular</span>/elements'</span>;
</code></pre><p>Now, we can use the custom element in <code>app.component.html</code>:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">add-to-cart-button</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">add-to-cart-button</span>&gt;</span>
</code></pre>
<blockquote>
<p>Nx does this by default but make sure the target in tsconfig.json is es2015.</p>
</blockquote>
<p>If we save and try to run, we get an error message. I wanted to show it since it’s a very nice error that says what we need to do. 😍</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075539109/vxcpjKoXh.png" alt /></p>
<p>So, since we have a Web Component then let’s do as the message suggests and add <code>CUSTOM_ELEMENTS_SCHEMA</code> in <code>app.module.ts</code>.</p>
<pre><code><span class="hljs-keyword">schemas</span>: [CUSTOM_ELEMENTS_SCHEMA]
</code></pre><p>It tells the Angular compiler not to error when seeing non-standard element tags in components’ templates. Now we see our custom element!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075540778/qF9kMhzEg.png" alt /></p>
<p>We can set the type to <em>Angular</em> and catch the <em>addToCart</em> event of the button.</p>
<pre><code>&lt;<span class="hljs-keyword">add</span>-<span class="hljs-keyword">to</span>-cart-button <span class="hljs-keyword">type</span>="Angular" (addToCart)="buy($event)"&gt;&lt;/<span class="hljs-keyword">add</span>-<span class="hljs-keyword">to</span>-cart-button&gt;
</code></pre><p>If we add a buy function that console logs the event:</p>
<pre><code>buy(<span class="hljs-keyword">type</span>) {
  console.log(<span class="hljs-keyword">type</span>);
}
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075542302/EKGdxsbET.png" alt /></p>
<p>We can see that the event created by the <a target="_blank" href="https://angular.io/api/core/EventEmitter">EventEmitter</a> is a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent">CustomEvent</a>. The data that we emitted, “Angular,” can be seen in the detail attribute, where we can pick it up if needed.</p>
<p>Let’s see how we do the same thing in React.</p>
<h2 id="web-component-in-react">Web component in React</h2>
<p>First, we need to import the custom elements in <code>app.tsx</code>:</p>
<pre><code><span class="hljs-attribute">import</span> <span class="hljs-string">'<span class="hljs-variable">@reactangular</span>/elements'</span>;
</code></pre><p>When we add the custom element, VS Code starts complaining:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075543730/zTQ1mB76R.png" alt /></p>
<p>We need to add a <code>intrincic.d.ts</code> file, which serves a similar purpose as <code>CUSTOM_ELEMENTS_SCHEMA</code> in Angular.</p>
<pre><code><span class="hljs-keyword">declare</span> <span class="hljs-keyword">namespace</span> JSX {  
  <span class="hljs-keyword">interface</span> IntrinsicElements {    
    [elemName: <span class="hljs-built_in">string</span>]: <span class="hljs-built_in">any</span>;  
  }
}
</code></pre><p>We also need to add a couple of polyfills:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-string">'reflect-metadata'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'zone.js'</span>;
</code></pre><p>Angular uses <a target="_blank" href="https://github.com/angular/zone.js/">zone.js</a> by default for change detection, so you have to make sure that it’s loaded into the browser when using React. Next level would be to turn off <em>zone.js</em> and do manual change detection.</p>
<ul>
<li><a target="_blank" href="https://blog.angularindepth.com/do-you-still-think-that-ngzone-zone-js-is-required-for-change-detection-in-angular-16f7a575afef">Do you still think that NgZone (zone.js) is required for change detection in Angular?</a> by <a target="_blank" href="https://twitter.com/maxkoretskyi">Max Koretskyi aka Wizard</a></li>
</ul>
<p>Now we can see the component, and if we click it, we can see the type <em>React</em> in the console. The connection from React to the Custom element is working!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075545307/RHXEEXd9r.png" alt /></p>
<p>That’s awesome! Let’s create another custom element!</p>
<h2 id="cart-component">Cart Component</h2>
<p>Next, let’s create a shopping cart. It should be an icon with a badge that says how many items we have in the cart.</p>
<p>The best way to create a fully self-contained component is to embed the images into the component using DATA URIs. You would encode the image file into a text format, like Base64, and then use that text data in the <code>src</code> attribute:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"data:image/png;base64,your-base-64-encoded-image-data"</span> /&gt;</span>
</code></pre><p>There are many ways to encode the icon, and one is to run this command in the console (if you are using a good console):</p>
<pre><code><span class="hljs-selector-tag">base64</span> <span class="hljs-selector-tag">cart</span><span class="hljs-selector-class">.png</span>
</code></pre><p>After adding the styles, the cart component looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075548049/XzsoLcGgb.png" alt /></p>
<h2 id="view-encapsulation">View Encapsulation</h2>
<p>If we add the component to a page and inspect the HTML it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075549826/XXmhncMze.png" alt /></p>
<p>Let’s change to ViewEncapsulation.ShadowDom and now we get #shadow-root for our component:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075551367/_4OFVh5NV.png" alt /></p>
<p>If <em>Custom elements</em> are the way to create a new HTML, <em>Shadow DOM</em> is the way you provide its HTML and CSS. It’s optional, but it provides advantages like CSS scoping and DOM encapsulation.</p>
<p>If we were using <code>ViewEncapsulation.Emulated</code>, we would have to worry about styles bleeding in and out of the component; using <code>ShadowDOM</code> solves this issue by placing the styles inside of the <code>#shadow-root</code>.</p>
<p>You can read more on this here:</p>
<ul>
<li><a target="_blank" href="https://developers.google.com/web/fundamentals/web-components/shadowdom">Shadow DOM v1: Self-Contained Web Components</a></li>
</ul>
<h2 id="cart-component-in-angular">Cart component in Angular</h2>
<p>Now we need to get the communication between the button and shopping cart to get working.</p>
<p>The cart has an input property named <code>counter</code> that we can pass to it. Let’s create a local counter that we pass to the shopping cart.</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">shopping-cart</span> [<span class="hljs-attr">counter</span>]=<span class="hljs-string">"counter"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">shopping-cart</span>&gt;</span>
</code></pre><p>Now to see that it works we can add to the counter every time we click the button.</p>
<pre><code><span class="hljs-selector-tag">buy</span>(<span class="hljs-attribute">type</span>: CustomEvent) {
  <span class="hljs-selector-tag">this</span><span class="hljs-selector-class">.counter</span>++;
}
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075553276/eayHTaHmH.gif" alt /></p>
<p>We have communication between our web components!</p>
<p>Let’s see if we can do the same in React.</p>
<h2 id="cart-component-in-react">Cart component in React</h2>
<p>To get the communications flowing in the React component, we need a couple of things. First, we need some local state in the constructor:</p>
<pre><code><span class="hljs-attr">this.state</span> = { counter: <span class="hljs-number">0</span> }<span class="hljs-comment">;</span>
</code></pre><p>Then we can use the <code>counter</code> in the element.</p>
<pre><code>&lt;shopping-cart counter={<span class="hljs-keyword">this</span>.state.counter} /&gt;
</code></pre><p>Next, we need to update the state when clicking the button. For this, we need to reference the button element.</p>
<pre><code>&lt;<span class="hljs-keyword">add</span>-<span class="hljs-keyword">to</span>-cart-button <span class="hljs-keyword">type</span>="React" <span class="hljs-keyword">ref</span>={this.buttonRef} /&gt;
</code></pre><p>And then listen for the button events. We can map the Web Component events in the <code>componentDidMount()</code> life-cycle hook. Only showing the essential parts, it looks something like this:</p>
<pre><code class="lang-js">
<span class="hljs-keyword">import</span> React, { Component } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'@reactangular/elements'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Component</span> </span>{
  private buttonRef;
  <span class="hljs-keyword">constructor</span>(props) {
    <span class="hljs-built_in">super</span>(props);
    <span class="hljs-built_in">this</span>.state = { <span class="hljs-attr">counter</span>: <span class="hljs-number">0</span> };
    <span class="hljs-built_in">this</span>.buttonRef = React.createRef();
  }

  componentDidMount() {
    <span class="hljs-built_in">this</span>.buttonRef.current.addEventListener(<span class="hljs-string">'addToCart'</span>, <span class="hljs-function">() =&gt;</span>
      <span class="hljs-built_in">this</span>.setState({ <span class="hljs-attr">counter</span>: <span class="hljs-built_in">this</span>.state.counter + <span class="hljs-number">1</span> })
    );
  }

  componentWillUnmount() {
    <span class="hljs-built_in">this</span>.buttonRef.current.removeEventListener(<span class="hljs-string">'addToCart'</span>);
  }

  render() {
    <span class="hljs-keyword">return</span> (
      <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">shopping-cart</span> <span class="hljs-attr">counter</span>=<span class="hljs-string">{this.statecounter}</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">add-to-cart-button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"React"</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">{this.buttonRef}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/&gt;</span></span>
    );
  }
}
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>Or if you are more into hooks, <a target="_blank" href="https://gist.github.com/melcor76/7c5c6235821db70ea780703f71a136e0">here’s a Gist for that</a>.</p>
<p>And now we should be able to communicate between the components!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075555035/8OOgk4a4E.gif" alt /></p>
<p>Beautiful! We have achieved what we wanted! 🎉</p>
<h2 id="conclusion">Conclusion</h2>
<p>So, in the end we were able to use the same components created with Angular Elements in both Angular and React. I don’t know about you, but I think this is awesome! 🚀 
In Angular, it was straightforward to consume and communicate with the custom element. React was a bit more tricky, but not too hard.</p>
<p>Using Nx helped us to get started fast with creating a monorepo with applications and a library. It really shines when you are using multiple frameworks together.</p>
<p>If you are working in an environment with multiple frameworks, then Web Components could be an option. It’s great to be able to share native components with different frameworks. I’m sure you can think of some use cases for them. I only recently dove into this rabbit hole of technologies and I like what I’m seeing! 🐰</p>
<h3 id="call-to-action">Call to Action</h3>
<p>I always enjoy feedback, so please 👏, 📝 and <a target="_blank" href="https://twitter.com/intent/tweet?text=I+enjoyed+%22How+to+talk+with+Web+Components+in+React+and%C2%A0Angular%22+by+%40melcor76+%23angular+https%3A%2F%2Fblog.angularindepth.com%2Fhow-to-talk-with-web-components-in-react-and-angular-8deb7d2fb92a">tweet 🐦</a>.
Follow me on <a target="_blank" href="https://twitter.com/melcor76">Twitter</a> and <a target="_blank" href="https://medium.com/@michael.karen">Medium</a> for blog updates.</p>
<h3 id="resources">Resources</h3>
<ul>
<li><p><a target="_blank" href="https://github.com/melcor76/reactangular">Example code on GitHub.</a> 📜</p>
</li>
<li><p><a target="_blank" href="https://nx.dev/">Nx</a></p>
</li>
<li><p><a target="_blank" href="https://angular.io/guide/elements">Angular Elements Docs</a></p>
</li>
<li><p><a target="_blank" href="https://blog.nrwl.io/building-angular-and-react-applications-together-with-nx-78b5578de598">Building Angular and React Applications Together With Nx</a> by <a target="_blank" href="https://twitter.com/victorsavkin">Victor Savkin</a></p>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[The State of Web Components]]></title><description><![CDATA[Has the modern Web Platform evolved to the point where we can start using native components? As developers, we know that reusing code is a good idea. Does this mean we should use Web Components everywhere, or is this taking it a step too far?
These a...]]></description><link>https://blog.michaelkaren.dev/the-state-of-web-components-e3f746a22d75</link><guid isPermaLink="true">https://blog.michaelkaren.dev/the-state-of-web-components-e3f746a22d75</guid><category><![CDATA[Web Components]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Mon, 22 Jul 2019 04:16:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075451093/bkgrzHwmQ.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Has the modern Web Platform evolved to the point where we can start using native components? As developers, we know that reusing code is a good idea. Does this mean we should use Web Components everywhere, or is this taking it a step too far?</p>
<p>These are some of the questions I try to answer in this article. However, for those who are wondering what I am talking about, let’s start from the beginning.</p>
<h2 id="why-web-standards">Why Web Standards?</h2>
<p>Before there were any rules, the browser manufacturers kept introducing new features to better their competition. Browsers were diversified, and developers often had to make multiple versions of websites.</p>
<p>Web standards were finally introduced to protect the web ecosystem. Browser makers started working in a more standardized way unifying the browser stack.</p>
<p>The key groups for web standards are:</p>
<ul>
<li><p>The World Wide Web Consortium (<a target="_blank" href="https://www.w3.org/">W3C</a>)</p>
</li>
<li><p>The Web Hypertext Application Technology Working Group (<a target="_blank" href="https://whatwg.org/">WHATWG</a>).</p>
</li>
</ul>
<p>These are the community of people producing the standards that build up the web platform.</p>
<h2 id="web-components">Web Components</h2>
<p>In 2010–2011, people at Google started crafting the first drafts of what we now know as <a target="_blank" href="https://www.webcomponents.org/introduction">Web Components</a>. The specifications are a set of web platform APIs that let you extend the browser’s built-in HTML tags. Components built on the Web Component standards work across modern browsers and with any JavaScript library or framework that works with HTML.</p>
<blockquote>
<h1 id="web-components-are-framework-agnostic-components-based-on-web-standards">Web Components are framework agnostic components based on web standards.</h1>
</blockquote>
<p>These are the main specifications in the umbrella term that is Web Components: ☔️</p>
<ul>
<li><p><a target="_blank" href="https://w3c.github.io/webcomponents/spec/custom/">Custom Elements</a> let developers create their HTML Elements.</p>
</li>
<li><p><a target="_blank" href="https://w3c.github.io/webcomponents/spec/shadow/">Shadow DOM</a> lets us encapsulate style and markup in web components.</p>
</li>
<li><p><a target="_blank" href="https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-module-system">ES Modules</a> is the ECMAScript standard for working with modules.</p>
</li>
<li><p><a target="_blank" href="https://html.spec.whatwg.org/multipage/scripting.html#the-template-element/">HTML Template</a> defines how to declare fragments of markup that go unused at page load, but can be instantiated later on at runtime.</p>
<blockquote>
<p>Sometimes people use Web components and Custom elements interchangeably.</p>
</blockquote>
</li>
</ul>
<p>HTML imports were part of the spec before ES6 modules replaced them. There are now new proposals on <a target="_blank" href="https://github.com/w3c/webcomponents/issues/645">HTML Modules</a> and <a target="_blank" href="https://github.com/w3c/webcomponents/issues/759">CSS Modules</a>.</p>
<h2 id="how-do-they-work">How do they work?</h2>
<p>Here’s a simplified example of how to create a Web component:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MagicButton</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
  <span class="hljs-comment">// Magic goes here</span>
}

customElements.define(<span class="hljs-string">'magic-button'</span>, MagicButton);
</code></pre><p>The class for our custom element is a regular JavaScript class which extends the native <code>HTMLElement</code>. When we call <code>customeElements.define(...)</code> we register the custom element in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry">CustomElementRegistry</a>. Then we can use it with regular HTML:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">magic-button</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">magic-button</span>&gt;</span>
</code></pre><p>Note that according to the <a target="_blank" href="https://github.com/w3c/webcomponents/">specifications</a>, your element needs to have at least one dash in its name to avoid conflicts with existing elements.</p>
<h2 id="why-use-web-components">Why use Web Components?</h2>
<p>Why should we write Web Components instead of writing components in our favorite framework? I mean these web standards move slowly while the frameworks move so fast we don’t even remember their version numbers anymore. ⚡️</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075438490/vFZx--hdH.jpeg" alt /></p>
<p>What problem does providing a native component model solve?</p>
<p>They let you write <strong>encapsulated </strong>and<strong> reusable components</strong>. With Web Components, we gain <strong>interoperability</strong>. By having a standard interface and expressed as real HTML, they work with all the popular frameworks. Web components implemented using different libraries can even mix on the same page. We create them once and can then use them almost anywhere.</p>
<p>There are some excellent use cases for Web Components. For example, it’s popular with companies to unify the look and feel for their sites by writing their own <a target="_blank" href="https://medium.muz.li/what-is-a-design-system-1e43d19e7696">Design Systems</a>. By leveraging Web Components, they can share UI components across frameworks.</p>
<p>Another reason could be when a company or team decides to change tech stacks, because of <a target="_blank" href="https://blog.daftcode.pl/hype-driven-development-3469fc2e9b22">Hype Driven Development</a> or some important reason. If the library components are Web Components, then we don’t have to rewrite them.</p>
<p>Even people that are not familiar with programming but are familiar with HTML should be able to drop in a Web component on their page. The ease of use makes them perfect for enhancing content sites. Since it’s standard HTML, a maintainer of a Content Management System (CMS) can add it themselves.</p>
<p>So, we have some reasons to use Web Components, but can we use them in the browsers today?</p>
<h2 id="browser-support">Browser support</h2>
<p>When the <a target="_blank" href="https://blogs.windows.com/msedgedev/2019/04/08/microsoft-edge-preview-channel-details">Chromium-based Edge</a> arrives, Web Components are finally going to be available in all evergreen browsers.</p>
<p><img src="https://cdn-images-1.medium.com/max/2198/1*A32TxzGbavFKugs5HDRKkw.png" alt="Screenshot from* [https://webcomponents.org](https://cdn.hashnode.com/res/hashnode/image/upload/v1618075440278/EnobskS_o.html)*" /><em>Screenshot from</em> <a target="_blank" href="https://webcomponents.org/">https://webcomponents.org</a>**</p>
<p>I’m sure someone is asking: What about Internet Explorer, a product Microsoft officially discontinued in 2015?</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075441732/HKzoy9Y9A.jpeg" alt /></p>
<p>As you can see on <a target="_blank" href="https://netmarketshare.com/browser-market-share.aspx">this page</a> 7,7% (May 2019) of desktop users are still stuck in on Internet Explorer. That’s more than are using Edge! 😱</p>
<p>Luckily, we have <a target="_blank" href="https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs">polyfills</a> for them!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075443305/aNfLjAHwx.png" alt /></p>
<p>With support in evergreen browsers and good polyfills, we can use Web Components in basically any browser, including mobile. ✔️</p>
<h2 id="framework-support">Framework support</h2>
<p>As you can see on the page <a target="_blank" href="https://custom-elements-everywhere.com/">Custom Elements Everywhere</a>, the support for Custom Elements is excellent and getting even better all the time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075444889/qWfiHO7Vw.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075446394/DqvfGHSWv.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075447787/07Xi7xgSo.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075449218/KuCxOCv-K.png" alt /></p>
<p>Even the frameworks with the worst Custom elements support are slowly but surely working on improving the situation, and workarounds are available.</p>
<p>Web Components work with any JavaScript library or framework that works with HTML. ✔️</p>
<h2 id="is-anyone-using-web-components">Is anyone using Web Components?</h2>
<p>According to <a target="_blank" href="https://www.chromestatus.com">Chrome Platform Status</a>, about 8% (mid-2019) of all pages today use Web components. That makes it one of the most successful new web platform features in the last years. 📈</p>
<p>We can find Web components on popular sites like YouTube and GitHub. Moreover, some big companies have decided that Web Components is the best way to implement Design systems going forward. Like Ionic with <a target="_blank" href="https://stenciljs.com/">Stencil</a> and Salesforce with their <a target="_blank" href="https://developer.salesforce.com/docs/component-library/overview/components">Lightning Web Components</a>.</p>
<p>Here is a talk about the state of web components from Google I/O 2019:</p>
<h2 id="frameworks">Frameworks</h2>
<p>Wasn’t one of the points of Web components to get rid of frameworks? 
While it’s fine to write your components without frameworks, let me tell you in one word why you might want one: Boilerplate!</p>
<p>Here are some popular frameworks to check out:</p>
<ul>
<li><p><a target="_blank" href="https://lit-element.polymer-project.org/">LitElement</a></p>
</li>
<li><p><a target="_blank" href="https://stenciljs.com/">Stencil</a></p>
</li>
<li><p><a target="_blank" href="https://skatejs.netlify.com/">SkateJS</a></p>
</li>
</ul>
<p>It can also be possible to create web components with your favorite JavaScript framework. For example, <a target="_blank" href="https://angular.io/guide/elements">Angular Elements</a> provides a way to wrap Angular components as web components.</p>
<h2 id="ui-libraries">UI Libraries 📚</h2>
<p>Since Web Components work in all frameworks, creating UI libraries seems like a good idea. There are some great libraries out there. I have not done an extensive search, but here are a few examples:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/material-components/material-components-web-components">Material Web Components</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/vaadin/vaadin">Vaadin</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/wiredjs/wired-elements">Wired Elements</a></p>
</li>
<li><p><a target="_blank" href="https://ionicframework.com/docs/components">Ionic</a></p>
</li>
</ul>
<h2 id="are-there-no-downsides"><strong>Are there no downsides?</strong></h2>
<p>I have been very positive on Web Components in this article. There are, of course, some downsides to them as well. I have touched upon some of them briefly but let’s try to summarize the main points I can think of:</p>
<ul>
<li><p>Web standards can move slowly.</p>
</li>
<li><p>Polyfills for Internet Explorer.</p>
</li>
<li><p>Don’t work friction-less with all frameworks.</p>
</li>
</ul>
<p>Look, I love my JavaScript frameworks. I work with React and Angular, and they are fantastic. I’m sure Vue and Svelte and what-not are equally impressive. Web components are not going to replace them. They solve different problems, so there should be no animosity between these technologies.</p>
<h2 id="conclusion">Conclusion</h2>
<p>If you have followed along with this article, you see that Web Components are used today and supported by all modern browsers. Moreover, there are polyfills for when you need to support the Jurassic kind. There are some excellent use cases for Web Components, and these are gaining in popularity.</p>
<p>It took 10 years for browser vendors to unite and standardize ES5. Another six years to get back together for ES2015. It took 15 years for HTML5 to be standardized. We fought cross-browser compatibility for more than a decade.</p>
<p>Enough with the framework wars. Let’s unite. Let’s embrace Web Components. 👐 🚀</p>
<p>Thanks to <a target="_blank" href="https://twitter.com/LayZeeDK">Lars Gyrup Brink Nielsen</a> for helping me review this article!</p>
<h3 id="resources"><strong>Resources</strong></h3>
<ul>
<li><p><a target="_blank" href="https://medium.com/angular-in-depth/developments-in-web-components-im-excited-about-in-2019-3ae7751c2f64">Developments in Web Components I’m excited about in 2019</a> by <a target="_blank" href="https://twitter.com/maxkoretskyi">Max Koretskyi aka Wizard</a></p>
</li>
<li><p><a target="_blank" href="https://dev.to/ionic/why-we-use-web-components-2c1i">Why We Use Web Components</a> by <a target="_blank" href="https://twitter.com/maxlynch">Max Lynch</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@gilfink/understanding-the-customelementregistry-object-74408a25a3d4">Understanding the CustomElementRegistry Object</a> by <a target="_blank" href="https://twitter.com/gilfink">Gil Fink</a></p>
</li>
<li><p><a target="_blank" href="https://blog.bitsrc.io/9-web-component-ui-libraries-you-should-know-in-2019-9d4476c3f103">9 Web Components UI Libraries You Should Know in 2019</a> by <a target="_blank" href="https://medium.com/@JonathanSaring">Jonathan Saring</a></p>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
]]></content:encoded></item><item><title><![CDATA[How to get started with Canvas animations in Angular]]></title><description><![CDATA[I love playing games. And I love coding too. So, one day, I got thinking, why not use those coding skills to make a game? But it sounds hard. How would one even get started?

With baby steps. 👣

First, we need some 2D graphics. In this case, it’s mo...]]></description><link>https://blog.michaelkaren.dev/how-to-get-started-with-canvas-animations-in-angular-2f797257e5b4</link><guid isPermaLink="true">https://blog.michaelkaren.dev/how-to-get-started-with-canvas-animations-in-angular-2f797257e5b4</guid><category><![CDATA[Angular]]></category><dc:creator><![CDATA[Michael Karén]]></dc:creator><pubDate>Wed, 05 Jun 2019 11:52:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075470600/TyqFh_Kt1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I love playing games. And I love coding too. So, one day, I got thinking, why not use those coding skills to make a game? But it sounds hard. How would one even get started?</p>
<blockquote>
<h1 id="with-baby-steps">With baby steps. 👣</h1>
</blockquote>
<p>First, we need some 2D graphics. In this case, it’s moving some blocks on the screen. So, in this article, I will show how to draw and animate objects using the <a target="_blank" href="https://www.w3schools.com/html/html5_canvas.asp">HTML5 Canvas</a> and JavaScript. I will also go through some techniques to optimize performance. Who knows, it might come in handy some day.</p>
<blockquote>
<h1 id="animation-is-not-the-art-of-drawings-that-move-but-the-art-of-movements-that-are-drawn-norman-mclaren">“Animation is not the art of drawings that move but the art of movements that are drawn.” — Norman McLaren</h1>
</blockquote>
<p><img src="https://cdn-images-1.medium.com/max/9600/0*P920hd3fOZ3IS9nF" alt="Photo by [JESHOOTS.COM](https://cdn.hashnode.com/res/hashnode/image/upload/v1618075457528/dWt58Fw8_.html) on [Unsplash](https://unsplash.com?utm_source=medium&amp;utm_medium=referral)" /><em>Photo by <a target="_blank" href="https://unsplash.com/@jeshoots?utm_source=medium&amp;utm_medium=referral">JESHOOTS.COM</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></em></p>
<h2 id="introduction">Introduction</h2>
<p>Apple introduced canvas in 2004 to power applications and the Safari browser. A few years later it was standardized by the <a target="_blank" href="https://en.wikipedia.org/wiki/WHATWG">WHATWG</a>. It comes with finer grained control over rendering but with the cost of having to manage every detail manually. In other words, it can handle many objects, but we need to code everything in detail.</p>
<p>The canvas has a 2D <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D">drawing context</a> used for drawing shapes, text, images, and other objects. First, we choose the color and brush, and then we paint. We can change the brush and color before every new drawing, or we can continue with what we have.</p>
<p><a target="_blank" href="https://www.w3schools.com/html/html5_canvas.asp">Canvas</a> uses <strong>immediate rendering</strong>: When we draw, it immediately renders on the screen. But, it is a fire-and-forget system. After we paint something, the canvas forgets about the object and only knows it as pixels. So there is no object that we can move. Instead, we have to draw it again.</p>
<p>Doing animations on Canvas is like making a stop-motion movie. In every frame need to move the objects a little bit to animate them.</p>
<h2 id="using-canvas">Using Canvas ✏️</h2>
<p>To get started, we need to add a canvas element in our HTML. We'll also attach <a target="_blank" href="https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ref-vars">a reference variable</a> to the element so that we'll be able to refer to it from the component class:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">canvas</span> #<span class="hljs-attr">canvas</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"600"</span> <span class="hljs-attr">height</span>=<span class="hljs-string">"300"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">canvas</span>&gt;</span>
</code></pre><p>In the component class, we can then use the <code>**@ViewChild()</code><strong> decorator to inject a reference to the canvas.
In </strong>Angular 8**, a new <code>static</code> flag has been introduced not to break existing applications. Read more about it <a target="_blank" href="https://angular.io/api/core/ViewChild#viewchild">here</a>. Since I want access to the canvas in the <code>ngOnInit</code> hook I set it to true.</p>
<pre><code><span class="hljs-variable">@ViewChild</span>(<span class="hljs-string">'canvas'</span>, { <span class="hljs-attribute">static</span>: true }) 
<span class="hljs-attribute">canvas</span>: ElementRef&lt;HTMLCanvasElement&gt;;
</code></pre><p>Once the component has initialized, we’ll have access to the Canvas DOM node, as well as its drawing context:</p>
<pre><code><span class="hljs-keyword">this</span>.ctx = <span class="hljs-keyword">this</span>.canvas.nativeElement.getContext(<span class="hljs-string">'2d'</span>);
</code></pre><p>Here is the starting code for the component:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> { Component, ViewChild, ElementRef, OnInit } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;

<span class="hljs-meta">@Component</span>({
  selector: <span class="hljs-string">'app-root'</span>,
  template: <span class="hljs-string">`
    &lt;canvas #canvas width="600" height="300"&gt;&lt;/canvas&gt;
    &lt;button (click)="animate()"&gt;Play&lt;/button&gt;   
  `</span>,
  styles: [<span class="hljs-string">'canvas { border-style: solid }'</span>]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppComponent <span class="hljs-keyword">implements</span> OnInit {
  <span class="hljs-meta">@ViewChild</span>(<span class="hljs-string">'canvas'</span>, { <span class="hljs-keyword">static</span>: <span class="hljs-literal">true</span> })
  canvas: ElementRef&lt;HTMLCanvasElement&gt;;  

  <span class="hljs-keyword">private</span> ctx: CanvasRenderingContext2D;

  ngOnInit(): <span class="hljs-built_in">void</span> {
    <span class="hljs-built_in">this</span>.ctx = <span class="hljs-built_in">this</span>.canvas.nativeElement.getContext(<span class="hljs-string">'2d'</span>);
  }

  animate(): <span class="hljs-built_in">void</span> {}
}
</code></pre>
<p>Now we have a canvas and a button to start the animation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075458917/uIa_OOo0s.png" alt /></p>
<p>Let’s paint something on it!</p>
<h2 id="painting">Painting 🔵</h2>
<p>Once we have a canvas context in the component class, we can draw on it using the standard <a target="_blank" href="https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D">canvas context API</a>. We can use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect">fillRect()</a> to draw a square. It draws a filled rectangle colored by the current fill style.</p>
<pre><code>ctx<span class="hljs-selector-class">.fillRect</span>(x, y, <span class="hljs-attribute">width</span>, <span class="hljs-attribute">height</span>);
</code></pre><p>So to draw a small red rectangle with a side of 5 pixels:</p>
<pre><code><span class="hljs-keyword">this</span>.ctx.fillStyle = <span class="hljs-string">'red'</span>;
<span class="hljs-keyword">this</span>.ctx.fillRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">5</span>, <span class="hljs-number">5</span>);
</code></pre><p>To outline the square, we could use <code>strokeRect()</code>:</p>
<pre><code><span class="hljs-keyword">this</span>.ctx.strokeRect(z * x, z * y, z, z);
</code></pre><p>Let’s create a Square class with a drawing method that draws squares:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Square {
  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> ctx: CanvasRenderingContext2D</span>) {}

  draw(x: <span class="hljs-built_in">number</span>, y: <span class="hljs-built_in">number</span>, z: <span class="hljs-built_in">number</span>) {
    <span class="hljs-built_in">this</span>.ctx.fillRect(z * x, z * y, z, z);
  }
}
</code></pre>
<p>I’m using <code>z</code> here for the side lengths of the squares. 
Let’s try to use it in <code>animate()</code>:</p>
<pre><code>animate() {
  <span class="hljs-keyword">this</span>.ctx.fillStyle = <span class="hljs-string">'red'</span>;
  <span class="hljs-keyword">const</span> square = new Square(<span class="hljs-keyword">this</span>.ctx);
  square.draw(<span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">20</span>);
}
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075460416/sVi2RZMYP.png" alt /></p>
<p>We have painted our first element on the canvas! 🎉</p>
<p>Check out some more advanced examples on <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#Rectangular_shape_example">MDN</a>.</p>
<blockquote>
<h1 id="like-this-blog-post-share-ithttpstwittercomintenttweettextienjoyed22howtogetstartedwithcanvasanimationsinangular22by40melcor7623angularhttps3a2f2fmediumcom2fp2fhow-to-get-started-with-canvas-animations-in-angular-2f797257e5b4-on-twitter">Like this blog post? <a target="_blank" href="https://twitter.com/intent/tweet?text=I+enjoyed+%22How+to+get+started+with+Canvas+animations+in+Angular%22+by+%40melcor76+%23angular+https%3A%2F%2Fmedium.com%2Fp%2Fhow-to-get-started-with-canvas-animations-in-angular-2f797257e5b4">Share it</a> on Twitter! 🐦</h1>
</blockquote>
<h2 id="animation">Animation 🎥</h2>
<p>Now, let’s see if we can get our block to move on the canvas. We can create a function for this. With a loop, we can move the x value on the canvas and draw the object over and over again. Here I move the block to the right until it reaches the canvas end. We send in y for vertical position and z for size.</p>
<pre><code>move(y: <span class="hljs-built_in">number</span>, z: <span class="hljs-built_in">number</span>) {
  <span class="hljs-keyword">const</span> max = <span class="hljs-built_in">this</span>.ctx.canvas.width / z;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt; max; x++) {
    <span class="hljs-built_in">this</span>.draw(x, y, z);
  }
}
</code></pre><p>Let’s change from drawing the square to moving it:</p>
<pre><code><span class="hljs-attribute">square</span>.move(<span class="hljs-number">1</span>, <span class="hljs-number">30</span>);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075461918/RFDgGaM7M.png" alt /></p>
<p>OK, we were able to draw the square as we wanted. But we have two issues:</p>
<ol>
<li><p>We are not cleaning up after us.</p>
</li>
<li><p>It’s too fast to see the animation.</p>
</li>
</ol>
<p>We need to clear away the old block. What we can do is to erase the pixels in a rectangular area with <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clearRect">clearRect()</a>. By using the width and height of the canvas, we can clean it between paints:</p>
<pre><code class="lang-ts">move(y: <span class="hljs-built_in">number</span>, z: <span class="hljs-built_in">number</span>) {
  <span class="hljs-keyword">const</span> max = <span class="hljs-built_in">this</span>.ctx.canvas.width / z;
  <span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">this</span>.ctx.canvas;
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>; x &lt; max; x++) {
    <span class="hljs-built_in">this</span>.ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);
    <span class="hljs-built_in">this</span>.draw(x, y, z);
  }
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075463441/wgAzqxIYp.png" alt /></p>
<p>Great! We fixed the first problem. Now let’s try to slow down the painting so we can see the animation.</p>
<p>You might be familiar with <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval"><code>setInterval(function, delay)</code></a>. It starts repeatedly executing the specified <code>function</code> every <code>delay</code> milliseconds. 
I set the interval to 200 ms, which means the code will run five times a second.</p>
<pre><code class="lang-ts">move(y: <span class="hljs-built_in">number</span>, z: <span class="hljs-built_in">number</span>) {
  <span class="hljs-keyword">const</span> max = <span class="hljs-built_in">this</span>.ctx.canvas.width / z;
  <span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">this</span>.ctx.canvas;
  <span class="hljs-keyword">let</span> x = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">const</span> i = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">this</span>.ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, canvas.width, canvas.height);      
    <span class="hljs-built_in">this</span>.draw(x, y, z);
    x++;
    <span class="hljs-keyword">if</span> (x &gt;= max) {
      <span class="hljs-built_in">clearInterval</span>(i);
    }
  }, <span class="hljs-number">200</span>);    
}
</code></pre>
<p>To stop a timer created by <code>setInterval</code>, you need to call <code>clearInterval</code> and give it the identifier for the interval you want to cancel. The id to use is the one that is returned by <code>setInterval</code>, and this is why we need to store it.</p>
<p>We can now see that if we press the button, we get a square that moves from left to right.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075464985/ibI0aknAg.gif" alt /></p>
<p>But, if we press the play button several times, we can see that there is a problem when we try to animate multiple squares at the same time. It’s not working when every block has an interval that clears the board and paints on its own.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075466730/7fKdD763T.gif" alt /></p>
<p>It’s all over the place! Let’s see how we can fix this.</p>
<h3 id="multiple-objects">Multiple objects</h3>
<p>To be able to run the animations for several blocks, we need to rethink the logic. We only need one interval that paints all the objects simultaneously. Every time we press the play button, we add a new Square to a squares-array. The interval then clears the screen and paints all the objects in the array. This way, we avoid the flicker we had before.</p>
<pre><code class="lang-ts"><span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">this</span>.ctx.clearRect(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-built_in">this</span>.width, <span class="hljs-built_in">this</span>.height);
  <span class="hljs-built_in">this</span>.squares.forEach(<span class="hljs-function">(<span class="hljs-params">square: Square</span>) =&gt;</span> {
    square.moveRight();
  });
}, <span class="hljs-number">200</span>);
</code></pre>
<p>We can move the coordinates to the square model since we don’t need to know about its internals to move it. Instead of a general move command we could call it with commands to move in different directions.</p>
<pre><code class="lang-ts"><span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> Square {
  <span class="hljs-keyword">private</span> color = <span class="hljs-string">'red'</span>;
  <span class="hljs-keyword">private</span> x = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">private</span> y = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">private</span> z = <span class="hljs-number">30</span>;

  <span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> ctx: CanvasRenderingContext2D</span>) {}

  moveRight() {
    <span class="hljs-built_in">this</span>.x++;
    <span class="hljs-built_in">this</span>.draw();
  }

  <span class="hljs-keyword">private</span> draw() {
    <span class="hljs-built_in">this</span>.ctx.fillStyle = <span class="hljs-built_in">this</span>.color;
    <span class="hljs-built_in">this</span>.ctx.fillRect(<span class="hljs-built_in">this</span>.z * <span class="hljs-built_in">this</span>.x, <span class="hljs-built_in">this</span>.z * <span class="hljs-built_in">this</span>.y, <span class="hljs-built_in">this</span>.z, <span class="hljs-built_in">this</span>.z);
  }
}
</code></pre>
<p>And now we get better animations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618075468602/p19Jskztk.gif" alt /></p>
<p>What we did here is the first step of making a <strong>game loop</strong>. This loop is the heart of every game. It’s a controlled infinite loop that keeps your game running — it’s the place where all your little pieces will be updated and drawn on the screen.</p>
<h2 id="optimize-animations">🚶Optimize animations 🏃</h2>
<p>Another option for animating is to use <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame"><code>requestAnimationFrame</code></a>. It tells the browser that you wish to perform an animation and requests the browser to call a function to update an animation before the next repaint. In other words, we tell the browser: “Next time you paint on the screen, also run this function because I want to paint something too.”</p>
<p>The way to animate with <code>requestAnimationFrame</code> is to create a function that paints a frame and then schedules itself to invoke again. With this, we get an asynchronous loop that will execute when we draw on the canvas. We will be invoking the animate method over and over again until we decide to stop.</p>
<pre><code>animate() {
  <span class="hljs-comment">// Do stuff</span>
  <span class="hljs-keyword">const</span> id = requestAnimationFrame(<span class="hljs-keyword">this</span>.animate);  
}
</code></pre><blockquote>
<p>There is no recursion here, since the function is not calling itself. It is <code>requestAnimationFrame</code> that is asking for <code>animate</code> to be called.</p>
</blockquote>
<p>The <code>requestAnimationFrame</code> method returns an id that we use for canceling the scheduled animation frame. To cancel a scheduled animation frame, you can use the <code>cancelAnimationFrame</code> method. This method should be passed the id for the frame you wish to cancel.</p>
<pre><code><span class="hljs-selector-tag">cancelAnimationFrame</span>(id);
</code></pre><p>So, in conclusion, why should we use <code>requestAnimationFrame</code> instead of <code>setInterval</code> or <code>setTimeout</code>?</p>
<ul>
<li><p>It enables browser optimizations.</p>
</li>
<li><p>It handles the frame rate.</p>
</li>
<li><p>Animations only run when visible.</p>
</li>
</ul>
<p>Another gotcha with <code>requestAnimationFrame</code> is that when we re-schedule we need to bind the call to <code>this</code>, or it will have the window object as its context. Since the window object doesn't contain the <code>animate`` function, we get an error like:</code>Cannot read property ‘animate' of undefined.`</p>
<pre><code>animate() {
  <span class="hljs-comment">// Do stuff</span>
  requestAnimationFrame(<span class="hljs-keyword">this</span>.animate.bind(<span class="hljs-keyword">this</span>));
}
</code></pre><h3 id="what-about-change-detection">What about Change Detection?</h3>
<p>Angular applications execute inside an “Angular Zone”, which makes change detection automatically run without us having to do anything. When events like a mouse click or an HTTP response occur, we enter the zone and run the event handling code. Then, we exit and Angular performs change detection for the application. In most cases, you don’t need to worry about this. But when we fire timers frequently like like <code>setInterval</code>, <code>setTimeout</code>or <code>requestAnimationFrame</code>, we are also firing off change detection.</p>
<p>By default, every <code>requestAnimationFrame</code> runs inside NgZone and triggers change detection. This could mean that we end up running change detection 60 times a second. Since our application is small and Angular’s change detection is fast, we will most likely not notice it. But it could become a problem, so how do we solve it?</p>
<p>To run animations outside the zone, we use the <code>ngZone.runOutsideAngular</code> function. This function accepts a callback where we can execute the animate function.</p>
<pre><code><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> ngZone: NgZone</span>) {}

...

<span class="hljs-built_in">this</span>.ngZone.runOutsideAngular(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.animate());
</code></pre><p>This code runs the first frame outside the <code>NgZone</code>, and it will also run all the subsequent frames outside the zone. With this small change, we've achieved a potentially significant performance improvement to the animation loop.</p>
<p><a target="_blank" href="https://twitter.com/maxkoretskyi">Max Koretskyi aka Wizard</a>, has more about change detection:</p>
<ul>
<li><p><a target="_blank" href="https://medium.com/angular-in-depth/a-gentle-introduction-into-change-detection-in-angular-33f9ffff6f10">A gentle introduction into change detection in Angular</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/angular-in-depth/everything-you-need-to-know-about-change-detection-in-angular-8006c51d206f">Everything you need to know about change detection in Angular</a></p>
</li>
</ul>
<p>We don’t need all this optimization in our simple animation but to see some example code, I have prepared a StackBlitz.</p>
<p>https://stackblitz.com/edit/angular-canvas-animations</p>
<h2 id="conclusion">Conclusion</h2>
<p>In this article, you learned how to use the HTML5 Canvas and its 2D graphics context. I showed how to draw simple shapes, and finally, we were able to animate multiple objects on the canvas. We learned how to use <code>setInterval</code>to create an animation loop that keeps track of the objects on the screen.</p>
<p>We also learned how to optimize animations with <code>requestAnimationFrame</code> and how we can run outside the “Angular Zone”.</p>
<p>With this intro to canvas animations, we have taken our first steps into game development. I think we are ready to start on a real game next:</p>
<ul>
<li><a target="_blank" href="https://medium.com/angular-in-depth/game-development-tetris-in-angular-64ef96ce56f7">Game Development: Tetris in Angular</a></li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.educative.io/courses/game-development-js-tetris">https://www.educative.io/courses/game-development-js-tetris</a></div>
<h3 id="resources">Resources 🔧</h3>
<ul>
<li><p><a target="_blank" href="https://teropa.info/blog/2016/12/12/graphics-in-angular-2.html#canvas-graphics">SVG and Canvas graphics in Angular 2</a> by <a target="_blank" href="https://twitter.com/teropa">Tero Parviainen</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/@krzysztof.grzybek89/how-runoutsideangular-might-reduce-change-detection-calls-in-your-app-6b4dab6e374d">How <code>runOutsideAngular</code> might reduce change detection calls in your app</a> by <a target="_blank" href="https://twitter.com/k__grzybek">Krzysztof Grzybek</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">MDN web docs Canvas API</a></p>
</li>
</ul>
]]></content:encoded></item></channel></rss>