<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nevin Katz</title>
    <description>The latest articles on DEV Community by Nevin Katz (@nevkatz).</description>
    <link>https://dev.to/nevkatz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F594050%2F1fcbad7d-ac08-429d-a634-94a02ae1f034.png</url>
      <title>DEV Community: Nevin Katz</title>
      <link>https://dev.to/nevkatz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nevkatz"/>
    <language>en</language>
    <item>
      <title>About Me —Nevin Katz</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Sat, 07 Aug 2021 14:28:09 +0000</pubDate>
      <link>https://dev.to/nevkatz/about-me-nevin-katz-252h</link>
      <guid>https://dev.to/nevkatz/about-me-nevin-katz-252h</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---vs_c36r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2ATZ3x1CRyjNzGPN7B_4QNhQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---vs_c36r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2ATZ3x1CRyjNzGPN7B_4QNhQ.jpeg"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@intricateexplorer?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener nofollow"&gt;Intricate Explorer&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/windy-road?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener nofollow"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi there, and thanks for dropping by. I am a web and app developer and private tutor living in the Boston area. While I grew up in Virginia, I have now spent more of my life in Massachusetts. Outside of work I enjoy illustration, running, writing about technology, and losing to my son at chess.&lt;/p&gt;

&lt;p&gt;My history as a developer is a fairly roundabout journey. I started programming in BASIC on my Commodore 128 during the age of floppy disks, following tutorials from &lt;em&gt;3–2–1 Contact&lt;/em&gt; magazines and building pint-sized games. After middle school, my interests veered towards track, cross country, the sciences, playing in a college band, teaching, and illustration—and I ended up taking a long break from programming. I then came back to it as an adult when my interests in education, visual media, and technology started to converge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Education, Media, and Tech
&lt;/h3&gt;

&lt;p&gt;In earlier days, I majored in Biology at Swarthmore College and graduated with an interest in pursuing a career with a focus on education and an emphasis on science and technology. I earned an Ed. M. in Teaching and Curriculum at the Harvard Graduate School of Education. I then went on to teach science at the middle school and high school levels in Cambridge and Western Mass. While teaching, I wrote and illustrated &lt;a href="http://www.birdleymedia.com"&gt;Dr. Birdley Teaches Science&lt;/a&gt;, a nationally-published series of nine comics-based science resource books for grades 5 through 12.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--11GS3bGJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/349/1%2ATyzt4q23DoWcND6tjGcPbg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--11GS3bGJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/349/1%2ATyzt4q23DoWcND6tjGcPbg.jpeg"&gt;&lt;/a&gt;Dr. Birdley, the title character in the book series.&lt;/p&gt;

&lt;p&gt;After teaching for eight years and writing the &lt;em&gt;Birdley&lt;/em&gt; series, I gravitated towards writing a science curriculum and developed a renewed interest in web development. I remember reading Lynda Weinman’s book on &lt;em&gt;Designing Web Graphics (5th Edition)&lt;/em&gt; and realizing how the advent of the web was giving programming a new visual realm that captured my interest. I started learning programming again on my own, learning ActionScript and building an early version of the Birdley site as an initial portfolio piece.&lt;/p&gt;

&lt;p&gt;While I was initially looking for freelance tech and design work, I was asked to come onboard as a full-time online learning specialist at &lt;a href="http://www.edc.org"&gt;Education Development Center (EDC)&lt;/a&gt;. It was 2008, so Flash was still a thing, blogs and wikis were proliferating, and online learning was still thought of as the “wave of the future.” In addition to facilitating and writing online courses, I consulted on developing a Physics CD for government schools in India and developed graphics for our online courses and conferences. I also created Flash multimedia and coded up course pages using HTML, CSS, and occasionally jQuery. (Back then, building a jQuery show-hide felt like a big deal.) Around that time, I started to become interested in mobile development and felt I was hitting my ceiling as far as my coding skills. I did not feel developed enough to build what I wanted to build.&lt;/p&gt;

&lt;p&gt;Around this time, I started working with students and adults as a private tutor, homework coach, and test prep coach. I found that the opportunity to work directly with students and impact their growth helped to balance out my work in web development, and I have always enjoyed seeing my students grow and succeed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coursework and Coding Coherence
&lt;/h3&gt;

&lt;p&gt;While at EDC, a supervisor of mine noticed my inclination towards programming and encouraged me to seek out formal coursework. In the Spring of 2012, I enrolled at the Harvard Extension School and started out with a web development fundamentals course. It was there that I noticed that my coding journey felt more coherent with an organized learning path. My next course, CS50, was where I really became entranced by programming, and I went on to earn a Software Engineering Certificate by 2016.&lt;/p&gt;

&lt;h4&gt;
  
  
  Projects
&lt;/h4&gt;

&lt;p&gt;Among the highlights of the certificate program were the projects. Along the way, I returned to my interest in game development, building a small dungeon crawler for the iPhone, a cross-platform marble labyrinth game, and a Battleship Game in Objective-C and Java. And as an homage to a Commodore game I built, I remember staying up until 3am finishing a multiplayer white water rafting iOS game with three other guys over Skype. I also took a brief foray into bioinformatics, developing a gene sequence alignment tool in Ocaml using the Needleman-Wunsch Algorithm.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exams
&lt;/h4&gt;

&lt;p&gt;Most of my coursework involved taking CS exams alongside undergraduates, which were quite challenging. Preparing for them helped me to sharpen my CS knowledge and taking them gave me a renewed appreciation for the challenging tests my students go through. In fact, some of the test-taking strategies I recommend to my students come from my experience with what worked when preparing for and taking my CS exams, which had strict time limits and stressed higher-level thinking.&lt;/p&gt;

&lt;h4&gt;
  
  
  Recent interests
&lt;/h4&gt;

&lt;p&gt;Since completing my certificate, I have focused on learning vanilla JavaScript, CSS, PHP, Drupal, and Android app development with Cordova. While I handle back-end work when I need to, I still gravitate towards front-end web development. I am currently learning Vue and React and enjoy exploring the HTML5 Canvas API and SVG animation. Since I also tutor AP Computer Science, I also try to stay up on my Java skills.&lt;/p&gt;

&lt;h3&gt;
  
  
  My role at EDC
&lt;/h3&gt;

&lt;p&gt;Over time, my role at EDC has morphed into a tech lead for a group of websites in our U.S. Division and an app developer for our International Division. As a tech lead, I manage the development of Drupal sites, which entails a mix of custom web development, project management, and collaboration with other web developers. I also have had the opportunity to mentor junior developers and other staff with webmaster responsibilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stepping Stone
&lt;/h4&gt;

&lt;p&gt;As an app developer, I am building an internal app authoring system known as Stepping Stone, which consists of two components: an authoring site where staff can build app content in a no-code environment, and a suite of apps that can run that content offline. As part of the project, I built an API that allows the apps to either download directly or import a content package from a flash drive. Stepping Stone apps serve a range of purposes, including reading literacy evaluation, teacher training, early grades phonics and reading, and mental health provider workshops. The apps have been used in a number of EDC projects in a range of areas, including Mali, Zambia, and the Philippines.&lt;/p&gt;

&lt;p&gt;Aside from my work with Stepping Stone, I also consult on how best to integrate eLearning solutions, such as Articulate Rise, Twine, and H5P into our eLearning products.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Writing
&lt;/h3&gt;

&lt;p&gt;As a relatively new writer on Medium, I enjoy writing tutorials and articles about technology, web development, and science. While &lt;a href="https://medium.com/all-things-science"&gt;All Things Science&lt;/a&gt; publication is the home for my science articles, I have also written coding tutorials and tech articles for &lt;a href="https://medium.com/geekculture"&gt;Geek Culture&lt;/a&gt;, &lt;a href="https://javascript.plainenglish.io/"&gt;JavaScript in Plain English&lt;/a&gt;, &lt;a href="https://betterprogramming.pub"&gt;Better Programming&lt;/a&gt;, &lt;a href="https://bootcamp.uxdesign.cc/"&gt;Bootcamp&lt;/a&gt;, &lt;a href="https://medium.com/the-first-time"&gt;The First Time&lt;/a&gt;, &lt;a href="https://medium.com/the-first-time"&gt;About Me Stories&lt;/a&gt;, and &lt;a href="https://medium.com/codex"&gt;CodeX&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Reach Out
&lt;/h3&gt;

&lt;p&gt;Subscribe to my &lt;a href="https://buttondown.email/nevkatz"&gt;email list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out my tech blog at &lt;a href="http://nevkatz.github.io"&gt;nevkatz.github.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Find me on &lt;a href="http://twitter.com/nevkatz"&gt;Twitter&lt;/a&gt;, &lt;a href="https://nevkatz.medium.com"&gt;Medium&lt;/a&gt;, &lt;a href="https://codebase.so/user/nevkatz"&gt;Codebase.so&lt;/a&gt;, &lt;a href="https://polywork.com/nevkatz"&gt;Polywork&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/nevin-katz-7744244/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Take a look at my side projects on &lt;a href="https://github.com/nevkatz"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Wander through my front-end experiments on &lt;a href="https://codepen.io/nevkatz"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reach out through &lt;a href="https://nevinkatztutoring.com"&gt;Nevin Katz Tutoring&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And feel free to shoot me an email at &lt;a href="//mailto:nevkatz@gmail.com"&gt;nevkatz@gmail.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Journey Into Node JS!</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Sat, 07 Aug 2021 14:08:46 +0000</pubDate>
      <link>https://dev.to/nevkatz/journey-into-node-js-2b6a</link>
      <guid>https://dev.to/nevkatz/journey-into-node-js-2b6a</guid>
      <description>&lt;p&gt;Suppose you want a program that can handle server-side operations, like writing to a database or a file system, but you feel that content management systems like WordPress and Drupal have more features than you need — and may not be worth the maintenance and setup steps.&lt;/p&gt;

&lt;p&gt;Or suppose you speak Javascript as your native tongue. but want to try writing a desktop application that can output files.&lt;/p&gt;

&lt;p&gt;If you find yourself in this situation or a variant thereof, I recommend exploring Node JS — a lightweight open-source platform for developing server-side applications with Javascript.&lt;/p&gt;

&lt;p&gt;As a developer who has mainly used Drupal content management systems or Android apps to interact with databases and file systems, I am finding Node JS to be an exciting foray into using Javascript to run server-side applications using a lightweight solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;Using Node JS requires a familiarity with the command line, and if your machine does not already have it, you will need to &lt;a href="https://nodejs.org/en/download/package-manager/"&gt;install&lt;/a&gt; it on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hello World
&lt;/h3&gt;

&lt;p&gt;Once you have Node installed, running a &lt;a href="https://nodejs.org/en/docs/guides/getting-started-guide/"&gt;Hello World&lt;/a&gt; program is pretty straightforward. Putting that out there now because for me, getting something to work is usually my first step on the journey. That said, this post focuses mainly on what Node JS is and why it is unique.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;Node JS, originally released in 2009 by Ryan Dahl, helps to redefine Javascript’s place in the world by making it efficient at running server-side applications.&lt;/p&gt;

&lt;p&gt;While it was not the first Javascript server side platform — that credit goes to Netscape’s LiveWire Pro Web in 1996 — it is set apart by being event-driven — in other words, being drivable by events such as user clicks. It is also distinguished by being able to do interact with clients, files, and databases efficiently without holding up other tasks.&lt;/p&gt;

&lt;p&gt;And with the right modules, such as &lt;a href="https://nodejs.org/api/fs.html"&gt;fs (file system)&lt;/a&gt;, &lt;a href="https://nodejs.org/api/http.html"&gt;http&lt;/a&gt;, and &lt;a href="https://www.w3schools.com/nodejs/nodejs_mysql.asp"&gt;MySQL&lt;/a&gt;, can enable server programs to interact with the file system, a database, and the browser client.&lt;/p&gt;

&lt;h3&gt;
  
  
  What draws me to Node
&lt;/h3&gt;

&lt;p&gt;Of all of Node’s features, the file system capability is currently what draws me to it. While Node is widely used for websites and web applications, I am right now interested in using it to create local desktop applications that can create and modify files, create directories — essentially taking what a user creates and making useful content packages out of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Intro to Blocking and Non-blocking I/O
&lt;/h3&gt;

&lt;p&gt;One “under the hood” feature that makes Node JS useful is non-blocking I/O, or non-blocking input/output.&lt;/p&gt;

&lt;p&gt;What does this mean?&lt;/p&gt;

&lt;p&gt;I/O, or input/output, refers to a program interacting with the outside world, either by receiving or sending information.&lt;/p&gt;

&lt;p&gt;An I/O interaction usually occurs in the context of a &lt;strong&gt;thread&lt;/strong&gt;, or a singular sequential flow of control in a program.&lt;/p&gt;

&lt;p&gt;While some steps in a thread may involve an I/O operation, others may involve operations within the program. During an I/O operation, the program sends out a request, and gets a response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blocking versus Non-Blocking
&lt;/h3&gt;

&lt;p&gt;If an I/O operation is &lt;em&gt;blocking&lt;/em&gt;, it means that after a program sends an I/O request, nothing happens in a given thread until a response is received and the operation is complete. If it is &lt;em&gt;non-blocking&lt;/em&gt;, it means that the thread can keep going with something else while it waits for a response.&lt;/p&gt;

&lt;p&gt;In my case, I am primarily interested in I/O operations occuring between the server program and the browser client, as well as the server program and the file system.&lt;/p&gt;

&lt;p&gt;Before we look at the details of Non-Blocking I/O, let’s first take a closer look at threads and the processes they reside in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Threads and Processes
&lt;/h3&gt;

&lt;p&gt;When a program and its resources are loaded into memory and begins to run, it is called a &lt;strong&gt;process&lt;/strong&gt;. Within this process, there are one or more units of execution called &lt;strong&gt;threads&lt;/strong&gt;. These can be thought of as mini-processes within a process. In processes with multiple threads, these threads share the same memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Single-Threaded versus Multi-Threaded
&lt;/h3&gt;

&lt;p&gt;Different programming languages have different ways of handling processes and threads. Some, like Javascript, can run just one unit of execution at a time, and are called &lt;strong&gt;single-threaded.&lt;/strong&gt; Others, like Java and C#, can multi-task and have multiple threads running within one process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blocking I/O
&lt;/h3&gt;

&lt;p&gt;While Java can follow multiple instructions at a time, it also uses &lt;strong&gt;blocking I/O&lt;/strong&gt;, which means that a thread that is reading or writing a file is blocked until it finishes that file task. In other words, it stops what it is doing until the file input/output process is complete before moving on.&lt;/p&gt;

&lt;p&gt;And that’s fine if you have Java’s multiple threads, but on a single-threaded Javascript application, it would hold everything up and make your program less efficient than it could be.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-blocking I/O
&lt;/h3&gt;

&lt;p&gt;Because blocking I/O introduces this inefficiency, Node JS has &lt;strong&gt;non-blocking I/O&lt;/strong&gt;, which allows it to send out a request to the file system and move on to another operation while it waits for a response to that request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-blocking operations in Node JS are asynchronous
&lt;/h3&gt;

&lt;p&gt;As an aside, non-blocking operations in Javascript are asynchronous (or async for short), which means that the request-and-response sequence does not require continual attention by the program or occur as consecutive steps. You can start learning about async requests at &lt;a href="https://www.w3schools.com/js/js_asynchronous.asp"&gt;w3schools&lt;/a&gt;, and a post here on async requests will be coming soon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hope this helps!
&lt;/h3&gt;

&lt;p&gt;This has been a quick look at Node JS and non-blocking I/O. More information about blocking and non-blocking I/O can be found at the &lt;a href="https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/"&gt;Node JS&lt;/a&gt; website.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Returning to a Drupal 7/9 Migration — with Paragraphs</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Fri, 06 Aug 2021 19:54:29 +0000</pubDate>
      <link>https://dev.to/nevkatz/returning-to-a-drupal-7-9-migration-with-paragraphs-59po</link>
      <guid>https://dev.to/nevkatz/returning-to-a-drupal-7-9-migration-with-paragraphs-59po</guid>
      <description>&lt;p&gt;After a week of migrating our multisite system from D8 to D9 on our test server, I am now shifting to migrating another site from Drupal 7 to Drupal 9. Thankfully, this is just one site and not a multisite system. It is primarily used as a content management service so that both Android apps and Powershell applications can pull down and organize content with a series of GET requests. That said, there are a few complexities: It uses the Group module, which allows us to assign content permissions based on project teams. It also has a custom module that allows us to simulate how particular activities will look in a mobile app. Finally, the videos use the media module so those may have to be re-added.&lt;/p&gt;

&lt;p&gt;I started migration tests back in March 2021 and then put the whole thing on pause when it became clear that a lot of changes to both content and configuration would be happening.&lt;/p&gt;

&lt;p&gt;Now I am back in it. My first step is to refresh my local setup based on our production site. Then I will be turning off all the modules we will not need again in order to simplify the migration process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paragraphs
&lt;/h2&gt;

&lt;p&gt;Because this is a fairly simple site, we get a lot of mileage out of Drupal's out-of-the-box graphic user interface. That said, we do need to write custom scripts to migrate paragraphs. For those new to paragraphs, they are essentially "fields of fields." The paragraphs modules is similar to the Field Collection module except that it is  compatible with Drupal 8 and 9.&lt;/p&gt;

&lt;p&gt;After a lot of effort, I was able to get a paragraphs migration protocol working back in the Spring, and since then, we have had a proliferation in the number of paragraph types - and the nodes that use them - on our live site. So I will be writing additional scripts that will move over all those new paragraphs and their nodes to D9. We may also have to re-add some videos.&lt;/p&gt;

&lt;p&gt;That's about it for now. If you develop in Drupal and are curious as to how this goes, check back here for further updates.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>My Experience with a Drupal 8/9 Update Part 3: Database Updates</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Fri, 06 Aug 2021 16:18:56 +0000</pubDate>
      <link>https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-3-database-updates-30na</link>
      <guid>https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-3-database-updates-30na</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-c8j"&gt;Part 1&lt;/a&gt; | &lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-2-the-remote-site-12c7"&gt;Part 2&lt;/a&gt; | Part 3&lt;/p&gt;

&lt;p&gt;Thanks for stopping by. This is my third post in a series detailing my experience with updating our 24-site multisite system from Drupal 8 to Drupal 9 this week in our staging environment. I hope you come away with a little insight on how to handle this in your own projects or on website upgrades in general.&lt;/p&gt;

&lt;p&gt;The Drupal 8/9 transition has consisted of two main parts: the codebase upgrade and the database upgrade.&lt;/p&gt;

&lt;p&gt;The codebase upgrade was challenging when I tried to migrate directly from Drupal 8 to Drupal 9 due to version conflicts with Composer. After hitting these roadblocks, I ended up switching my approach and starting from with a Drupal 9.2.3 Vanilla site, re-adding the modules and themes. This was the way to go, as most of the Composer updates were smooth after that with minimal dependency issues.&lt;/p&gt;

&lt;p&gt;Since then, our work has been primarily focused on making database updates to each of the 24 sites.&lt;/p&gt;

&lt;p&gt;One surprise from this upgrade was how many updates were needed to our site's theme. In addition to changing the versioning, there were several places where we had to change the syntax in our Drupal API calls. Fortunately, Acquia Cloud, our server provider, has a nice log system that allowed me to check into the errors resulting in the white screens I encountered during our database updates. &lt;/p&gt;

&lt;p&gt;Another interesting find was that layout builder was automatically enabled for our homepages, which caused our homepage text to be hidden. Figuring out how to turn it off was tricky at first, but I ultimately found a way to do it with two clicks and a save.&lt;/p&gt;

&lt;p&gt;One question I have yet to contend with is how best to handle local development. Now that Acquia Dev Desktop has reached EOL, I am trying out Lando. The caveat is that setting up multisites with Lando looks complex. I'm going to give it a try with just one site to see how it goes. &lt;/p&gt;

&lt;p&gt;I have been focusing on database updates over the past 24 hours and they have gone fairly smooth. Every so often there is a module I need to add or a theme issue I need to resolve, but for the most part everything works and I can plot out our roadmap - as opposed to when I was starting, where I couldn't see two feet in front of me. As a result, I am now able to coordinate with our program sites around the globe to make sure we can handle any content updates that occur between now and deployment.&lt;/p&gt;

&lt;p&gt;We are just about nearing the finish line, and this has been quite a learning curve. I hope my experience is informative for other Drupal devs looking to upgrade their sites from 8 to 9.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elsewhere
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://medium.com/geekculture/7-tips-on-upgrading-from-drupal-8-to-drupal-9-648f519d6e7e?sk=fe2d0816cb852a7b5ca3dfaf0b6fa131"&gt;7 Tips on Upgrading from Drupal 8 to Drupal 9&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>My Experience with a Drupal 8/9 Update  Part 2: The Remote Site</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Wed, 04 Aug 2021 19:22:58 +0000</pubDate>
      <link>https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-2-the-remote-site-12c7</link>
      <guid>https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-2-the-remote-site-12c7</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-c8j"&gt;Part 1&lt;/a&gt; | Part 2 |  &lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-3-database-updates-30na"&gt;Part 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, this is Part 2 of my writeup on my Drupal 8/9 upgrade. &lt;/p&gt;

&lt;p&gt;After a day of adding back the themes and all my modules to a local 9.2.3 setup with Lando, my local site is now up and running. &lt;/p&gt;

&lt;p&gt;BUT...the first remote site gives me a WSOD. So that is the first puzzle of the day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I am now working on getting my remote site working as well. On the Acquia Logs I am getting this nice little error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;
&lt;code&gt;
Uncaught PHP Exception InvalidArgumentException: "No converter has been registered for paramconverter.latest_revision" at /mnt/www/html/abemultisite1ysumx4zdc3/docroot/core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php line 39 request_id="v-5d494db2-f558-11eb-82e1-0a7156243103" 
&lt;/code&gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let's see if I can track this down.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I suspect this may have to do with the Acquia Connector module.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Acquia's &lt;a href="https://docs.acquia.com/cloud-platform/create/install/drupal9/"&gt;Drupal 9 Installation Guide&lt;/a&gt; could be a good resource for other Acquia D9 sites. May be too far along with this one to make use of it, though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Just ran &lt;code&gt;composer run enable-asset-packagist &lt;/code&gt; within the lightning profile and then ran &lt;code&gt;composer update&lt;/code&gt; at root.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Just added Acquia Connector and Acquia search. They are off, but I want to be prepared. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alrighty, I am at the update.php page. Get ready for over 112 updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is a warning that lightning and lightning media are not present and are required in schema, but I know they are. It didn't stop me on my local. I'm going to update the database manually and then run the update.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ran the database update and the main hub site now works remotely!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ah, I am getting messages on French translation files being imported. Very interesting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The layout of the page is off. I wonder what could be causing that. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Turning off layout builder on the front page fixed the layout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Turned on devel entity updates to fix an issue with compact date range.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Running &lt;code&gt;drush entup&lt;/code&gt; in live dev mode updated the compact date range on the second try. (On the first try, there was an autoload.php error.) &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, good progress today. Both the Hub site and the france site work remotely after their updates. There are warnings about deprecated modules and such but those are for another day. Overall now the rest of this D8/D9 upgrade seems feasible now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elsewhere
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Elsewhere
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nevkatz.medium.com/7-tips-on-upgrading-from-drupal-8-to-drupal-9-648f519d6e7e?sk=fe2d0816cb852a7b5ca3dfaf0b6fa131"&gt;7 Tips on Upgrading from Drupal 8 to Drupal 9&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
    </item>
    <item>
      <title>My Experience with a Drupal 8/9 Update Part 1: The Local Environment</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Tue, 03 Aug 2021 17:51:25 +0000</pubDate>
      <link>https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-c8j</link>
      <guid>https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-c8j</guid>
      <description>&lt;p&gt;Part 1 | &lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-2-the-remote-site-12c7"&gt;Part 2&lt;/a&gt; |  &lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-3-database-updates-30na"&gt;Part 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Monday night was one of those nights that I couldn't look away. I kept trying to upgrade my Drupal 8 site using a number of strategies, all to no avail. By the end of a long night I was soundly defeated by Drupal and its nefarious sidekick, Composer. &lt;/p&gt;

&lt;p&gt;At least they seem adversaries in those moments. In the best of times, they are great allies that just get a little cantankerous sometimes.&lt;/p&gt;

&lt;p&gt;One day later and I am back at it again - working on upgrading a multiple-website system from Drupal 8 to Drupal 9. &lt;/p&gt;

&lt;p&gt;In this article I am listing out the Drupal migration tips and tricks that I wish I had known at the outset of this journey.&lt;/p&gt;

&lt;p&gt;While this will not entail a complete rebuild along the lines of Drupal 7 to Drupal 9,, one challenge is that this is a Drupal multisite system where 20+ sites have to be upgraded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Jargon
&lt;/h2&gt;

&lt;p&gt;For those of you new to the jargon, Drupal is a content management system with endless possibilities but also endless headaches at times. Composer is a dependency manager that helps to keep Drupal's various dependencies all straightened out.  &lt;/p&gt;

&lt;p&gt;Symfony is a popular PHP framework that you're not supposed to have to adjust - it's like node_modules in that regard. It was throwing errors during the direct upgrade and the core reason I am changing my approach from a direct migration to a ground-up build.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach
&lt;/h2&gt;

&lt;p&gt;My strategies: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Starting at Drupal 9.0.1 since it is closest to Drupal 8.9.17.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using Lando for my local setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Starting with a Vanilla Site, then will make a backup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;settings.php file and directory structure is modeled after our current site, which resides on Acquia Cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git repo comes from our current site; I swapped in new vendor, the web directory, and other key directories that are all 9.0.1.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Starting with a Drupal 9 instance
&lt;/h2&gt;

&lt;p&gt;At first, I was trying a direct upgrade from Drupal 8 to Drupal 9. Because this introduced too many complications, I have switched to building a 9.0.1 site from the ground up. &lt;/p&gt;

&lt;p&gt;Once I'm ready I plan to add the contrib modules and import my database.&lt;/p&gt;

&lt;p&gt;My approach of building the D9 site from the ground up and then adding in assets is for several reasons: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We want to switch our local systems from Acquia Dev Desktop to Lando, and this is a good opportunity.&lt;/li&gt;
&lt;li&gt;Upgrading a D8 install directly to D9 introduces issues with symfony dependencies that are hard to parse out. &lt;/li&gt;
&lt;li&gt;lightning modules upgrades got especially tough, so starting with D9 allows me to  reinstall the correct versions more easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways Thus Far
&lt;/h2&gt;

&lt;p&gt;A few things I have learned: &lt;/p&gt;

&lt;p&gt;If your webroot is not toplevel you have to update it in multiple places in composer.json.&lt;/p&gt;

&lt;p&gt;You get into a chicken-and-egg situation with composer you can update all at once with &lt;code&gt;composer require resource1:x.x.x resource:y.y.y --with-all-dependencies&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sometimes obliterating composer.lock and vendor directories are a great way to go.&lt;/p&gt;

&lt;p&gt;I'll probably update this post as I find out more. Hope this helps other Drupallers out there.&lt;/p&gt;

&lt;h2&gt;
  
  
  General Updates
&lt;/h2&gt;

&lt;p&gt;Below are some updates I posted throughout the day (8/3/21).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;My local blank hub site is working. Yay!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I am now gradually adding modules with Composer and listing out the ones that do not install. For those, we will see if we can turn them off on our 20+ live sites before the code upgrade.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overall my trust in Composer is returning after the debacle yesterday.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After installing the required modules, I then installed the theme. This requires changing some compatibility in their .yml files. Backing up the site while the base theme is installed has been critical. Replacing &lt;code&gt;core:'8.x'&lt;/code&gt; with &lt;code&gt;core_version_requirement: ^8 || ^9&lt;/code&gt; in the &lt;code&gt;theme.info.yml&lt;/code&gt; files seems necessary but not sufficient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I just installed the Upgrade Status module, which tells me that none of my modules are ready for Drupal 10. Who cares about 10? I'm still trying to get to 9! It also may help me to figure out why my themes are incompatible. This way I can learn about why they don't work without enabling them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Well, well, well. Even though the themes are in the green now, I am back to getting a symfony error related to a dependency injection.  This is what drove me to switch strategies, but now I have a better idea of what triggers it. It seems to be a theme issue.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The error from admin/reports/dblog is below.&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "path.alias_manager". Did you mean this: "path_alias.manager"? in Drupal\Component\DependencyInjection\Container-&amp;gt;get() (line 151 of /app/docroot/core/lib/Drupal/Component/DependencyInjection/Container.php).
&lt;/code&gt;
&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;After a bit of searching I ran across &lt;a href="https://www.drupal.org/project/rules/issues/3101026"&gt;this resource&lt;/a&gt;, which was the key. I had to change &lt;code&gt;path.alias_manager&lt;/code&gt; to &lt;code&gt;path_alias.manager&lt;/code&gt; in three places.&lt;/li&gt;
&lt;li&gt;It worked! The Porto theme now shows up. &lt;/li&gt;
&lt;li&gt;Importing the database from our hub site still causes errors.&lt;/li&gt;
&lt;li&gt;It is amazing what I am learning by re-adding all the site assets. I now see that I have needed some profiles in our  &lt;code&gt;profiles&lt;/code&gt; directory. On the &lt;code&gt;update.php&lt;/code&gt; page Now I see a bunch more missing modules that I thought were optional.&lt;/li&gt;
&lt;li&gt;All modules are added. The lightning media and entity_embed_link module had to be added manually to get to the update screen.&lt;/li&gt;
&lt;li&gt;I am now going through 112 database updates.&lt;/li&gt;
&lt;li&gt;Getting a white screen, but running &lt;code&gt;lando logs&lt;/code&gt; indicated it was due to one line of deprecated code in the theme. I am changing &lt;code&gt;entity_load_multiple_by_properties&lt;/code&gt; to &lt;code&gt;loadByProperties&lt;/code&gt; in my &lt;code&gt;porto.theme&lt;/code&gt; file. &lt;/li&gt;
&lt;li&gt;The first site works!&lt;/li&gt;
&lt;li&gt;Just tested on the remote site is still a work in progress. I will need make some changes to settings.php but we are moving along. That's all for now!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Elsewhere
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-2-the-remote-site-12c7"&gt;Part 2&lt;/a&gt; |  &lt;a href="https://dev.to/nevkatz/my-experience-with-a-drupal-8-9-update-part-3-database-updates-30na"&gt;Part 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nevkatz.medium.com/7-tips-on-upgrading-from-drupal-8-to-drupal-9-648f519d6e7e?sk=fe2d0816cb852a7b5ca3dfaf0b6fa131"&gt;7 Tips on Upgrading from Drupal 8 to Drupal 9&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>php</category>
      <category>programming</category>
    </item>
    <item>
      <title>An Example of a Closure in JavaScript</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Mon, 02 Aug 2021 00:51:07 +0000</pubDate>
      <link>https://dev.to/nevkatz/an-example-of-a-closure-in-javascript-36ak</link>
      <guid>https://dev.to/nevkatz/an-example-of-a-closure-in-javascript-36ak</guid>
      <description>&lt;p&gt;Hi everyone, &lt;/p&gt;

&lt;p&gt;The concept of the closure is one of the tougher concepts for me when I first started learning JavaScript in depth. If you are new to the concept, a closure is essentially a function bundled together with its surrounding state, which typically includes variables that the closure needs. A closure is typically a function within a larger function, which serves as a "bubble." All the variables within this larger function bubble are only accessible by methods in the closure.&lt;/p&gt;

&lt;p&gt;The JavaScript engine is smart enough to realize that the variables are needed, so the engine's garbage collector does not obliterate them.&lt;/p&gt;

&lt;p&gt;Below is a quick example of an object with four functions that are actually closures. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;increment&lt;/code&gt;, and &lt;code&gt;reset&lt;/code&gt;. They all act on a variable called &lt;code&gt;count&lt;/code&gt;, which sits within the immediately invoked function expression (IIFE) holding the closure.&lt;/p&gt;

&lt;p&gt;Each function, which comes bundled with its surrounding environment, is a closure. &lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://jsfiddle.net/nevkatz/nm631eq5//embedded/html,js,result//dark" width="100%" height="600"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;get&lt;/code&gt; method will simply get the &lt;code&gt;count&lt;/code&gt; value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;set&lt;/code&gt; method sets the &lt;code&gt;count&lt;/code&gt; value to any value we want.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;increment&lt;/code&gt; method will increment the existing value by the amount passed in as a parameter. If no value is passed in, it increments the value by 1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the &lt;code&gt;reset&lt;/code&gt; method resets the value to zero.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These methods are the only way the user can access the &lt;code&gt;count&lt;/code&gt; value. In this way, the use of a closure causes the &lt;code&gt;count&lt;/code&gt; value to act in a similar way to that of a private variable in a Java object; it cannot be accessed outside the object, so methods are required to retrieve its value or update it.&lt;/p&gt;

&lt;p&gt;In the demo, you will see that an &lt;code&gt;init&lt;/code&gt; method grabs some references to the HTML elements we print to and then calls all the methods. Take a look at how they are called and see if you can understand what causes these particular values to be printed out.&lt;/p&gt;

&lt;p&gt;I hope this quick post gives you a solid idea of what closures are about. Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  Elsewhere
&lt;/h2&gt;

&lt;p&gt;For a tutorial on closures with an easy on-ramp, check out &lt;a href="https://javascript.plainenglish.io/javascript-closures-and-their-scope-bubbles-a6bef7a4824e?sk=a0bf906dc1895a6b21508ef82479df7e"&gt;JavaScript Closures and Their Scope Bubbles&lt;/a&gt; on Medium.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Create an Animated Banner with Vanilla JavaScript and the Canvas API</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Thu, 24 Jun 2021 04:42:31 +0000</pubDate>
      <link>https://dev.to/nevkatz/create-an-animated-banner-with-vanilla-js-and-canvas-5cpl</link>
      <guid>https://dev.to/nevkatz/create-an-animated-banner-with-vanilla-js-and-canvas-5cpl</guid>
      <description>&lt;p&gt;While the JavaScript Canvas API has tremendous potential for rich, performant animations, every step of the work has to be achieved manually. With the amount of effort it takes to make an animation, a ready-made library can make the work more efficient.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a micro-library in vanilla JavaScript intended for the creation of HTML5 canvas animations. We will then use this library to make an animated banner composed of text, images, and shapes.&lt;/p&gt;

&lt;p&gt;Below is a quick CodePen of the final animation we will build.&lt;/p&gt;

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

&lt;p&gt;Working with the Canvas API is different from working with the HTML DOM or SVG DOM APIs, in that you do not have an organized hierarchy of elements. Instead, you have a  element, which contains a bitmap that you can render graphics on using the API’s methods.&lt;/p&gt;

&lt;p&gt;While the  element can be cleared and redrawn with each animation frame, it will not remember the state of its bitmap from one frame to the next — so you have to create your own methods for storing the state of each image, shape, or text box between frames. This is where JavaScript objects come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Objects
&lt;/h2&gt;

&lt;p&gt;For this library, we will create a JavaScript object for each graphic element. Each object will store the properties of its corresponding graphic, such as position, speed, and color. It will also be tethered to its own personal element, which can be used to render a visual representation of the object. By wiring an object to each piece of the animation, the object’s properties allow the program to remember the state of its corresponding shape, image, or text between frames. The canvas forgets, but our objects will not.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we want this to work
&lt;/h2&gt;

&lt;p&gt;The goal of the library is to create and animate graphic elements — shapes, text, and images.&lt;/p&gt;

&lt;p&gt;Here is an example of how we would create an object. Notice how we assign it properties. Once we declare it as a new utils.graphic, it should call methods that add a newcanvas element — a layer, if you will — to a central staging element in the DOM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6V9zEOeP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2388/1%2AAvV2AG1yQK1S44LB3UETxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6V9zEOeP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2388/1%2AAvV2AG1yQK1S44LB3UETxQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we should be able to render and animate the object by calling an animate method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logo_circle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And clicking a “restart” button — or the stage element itself —should call a reset method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logo_circle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is how it should work — you should create the object and call the methods, and the library should take care of the details.&lt;/p&gt;

&lt;p&gt;Let’s get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Write the Markup and CSS
&lt;/h2&gt;

&lt;p&gt;For the HTML markup, we will create a button and a container for all our  elements. The container will have an id of stage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"stage"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"restart"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Restart&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s write CSS styles that achieve the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;set the dimensions and border of the stage container&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;give the stage container position:relative so that our canvas layers will be stacked inside it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;style the body to center our elements&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;allow canvas layers to stack on top of each other by giving them position:absolute&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--24wTd9cA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AzcDI-cH5pK8wgbL3QsZ_PQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--24wTd9cA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AzcDI-cH5pK8wgbL3QsZ_PQ.png" alt="The main styles."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The main styles.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Now let’s create a nice-looking style for the button that restarts the animation. Below is a close-up of the button followed by its CSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8OSWAoPI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2ApKtp_PkZu0k7rtGzMDiGOQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8OSWAoPI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2ApKtp_PkZu0k7rtGzMDiGOQ.png" alt="The button."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The button.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--guRQMuVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AxHgopqsgaOJnLCGEK1es2w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--guRQMuVX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2AxHgopqsgaOJnLCGEK1es2w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Make the JavaScript Wrapper
&lt;/h2&gt;

&lt;p&gt;On to the JavaScript. Let’s create a wrapper that will hold our library’s contents. We will start with an empty object named utils.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s add an immediately-invoked function expression (IIFE), which serves as our wrapper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;The empty utils object then gets passed into our wrapper. Once inside, it will be known as pen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The wrapper allows us to define variables and methods within an enclosed namespace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set the Stage
&lt;/h2&gt;

&lt;p&gt;Our first task is to tell our module where to add the canvas layers, so let’s plan to write a method that does that based on an id that gets passed in. Since our target element has an id of stage, we should be able to call the method like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setStage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also want to be able to set the background-color of the stage as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setBackgroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightpink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s build up our code so it can handle this. Within our wrapper, let’s add a variable called stage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, let’s write a quick method called setStage, which sets the stage variable when called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

   &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setStage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stageId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Because setStage can be called from outside the wrapper, it allows us to switch the DOM element we are drawing to, thus opening the possibility of handling multiple banners.&lt;/p&gt;

&lt;p&gt;Finally, let’s write the method for setting the background color of the stage element.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

     &lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setStage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stageId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

     &lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setBackgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
             &lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Build the Graphic Constructor
&lt;/h2&gt;

&lt;p&gt;Now let’s create a constructor function for the graphic elements we will add. The constructor will have several purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;creating an array for tracking animation frame requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;creating a new canvas element for each graphic, setting its properties, and appending it to the stage&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;obtaining our context — essentially a bundle of drawing methods for the new canvas&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;adding canvas and context as properties to our graphic object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;adding all properties from the passed-in object&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;setting a new cur property for storing the state of the graphic&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Starting the constructor
&lt;/h3&gt;

&lt;p&gt;Let’s start by defining the constructor function for a graphic object. Notice how it is attached to our main pen object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Our constructor accepts one object as a parameter and sets it to an empty object if the parameter is absent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an array for tracking frame requests
&lt;/h3&gt;

&lt;p&gt;Within the constructor, let’s create an array for tracking animation frame requests. This will become important if you press the “restart” button when an animation is in progress. We will use this later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reqIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a canvas element
&lt;/h3&gt;

&lt;p&gt;Now let’s create a new canvas layer for this object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reqIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set canvas properties
&lt;/h3&gt;

&lt;p&gt;In the same constructor, let’s set the canvas width and height equal to the clientWidth and clientHeight of the current stage element, respectively. And because each canvas is intended as a visual, we will give it a role of img.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Because each canvas is intended as a visual element, we will give it a role of img.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;role&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the passed-in object has a label property, let’s use that to set the aria-label attribute of the canvas for accessibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-label&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And if the object has a zIndex property, let’s add that to the style attribute of the canvas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s append our canvas to the stage element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, let’s grab the context reference for the canvas so we can access the drawing methods.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we’ve established the graphic object’s canvas and context, let’s iterate through all the properties of the parameter object and add them to the graphic object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;his&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set the current property
&lt;/h3&gt;

&lt;p&gt;Because the canvas does not intrinsically store its state, we will keep track of the properties that animate with a property called cur. It has three possible inner properties: x, y, and alpha. At the outset, we will make its properties equal to those of start.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cur&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep start from changing along with cur, we use spread ... syntax to break it into key-value pairs — and then use curly braces to rebuild these parts into a new object. This way, we avoid syncing the two properties.&lt;/p&gt;

&lt;p&gt;The full constructor for the graphic object is below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V0Gkt7bD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2656/1%2A1SBShRsfuSW4o0yTePvbMA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V0Gkt7bD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2656/1%2A1SBShRsfuSW4o0yTePvbMA.png" alt="Building the graphic constructor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Building the graphic constructor.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 5: Plan the Methods
&lt;/h2&gt;

&lt;p&gt;Now that we have built a constructor for our JavaScript objects, let’s start writing some methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;four render methods that can draw out the shape, text, or image based on its object’s properties&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;updateProps, which updates the properties of the object before the next animation frame is drawn&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;checkCanvasAlpha, which updates the globalAlpha property of the object’s canvas rendering context if its alpha value is changing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;animate, which changes how the object is represented on its canvas —and then calls itself if another frame is needed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cancelFrames, which cancels any remaining frame requests if our animation has been restarted&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;reset, which returns the object and its canvas to their original states&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To give every object we create access to all these methods, we will attach each method to the prototype *of the graphic object — a template of sorts that the object inherits. We can attach a method to a prototype using this syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;methodname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;Let’s apply this method in the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Write the Shape Rendering Methods
&lt;/h2&gt;

&lt;p&gt;Let’s write rectRender and circleRender, which will render the two types of shapes we need for our banner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rectangle
&lt;/h3&gt;

&lt;p&gt;The rectRender method involves setting the fillStyle and then calling fillRect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l0P_RHU7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2892/1%2A9-7d3WYKlws2A5fsHQxZwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l0P_RHU7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2892/1%2A9-7d3WYKlws2A5fsHQxZwg.png" alt="The rectRender method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The rectRender method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h3&gt;
  
  
  Circle
&lt;/h3&gt;

&lt;p&gt;The circleRender method is more complex— as it involves using the center coordinates, radius, fill, and stroke properties. Notice that it uses the arc method to draw an arc that is 2π radians, or 360 degrees.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pD16Ure2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3028/1%2AUirV0Zm3Ua9G4f9TVvYACA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pD16Ure2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3028/1%2AUirV0Zm3Ua9G4f9TVvYACA.png" alt="The circleRender method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The circleRender method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 7: Write the Text and Image Methods
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Text
&lt;/h3&gt;

&lt;p&gt;The textRender method involves setting a couple new properties, such as font and textAlign.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tz-w6cMW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2488/1%2AH8Sq7nQ9cKetNx8sW5rTBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tz-w6cMW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2488/1%2AH8Sq7nQ9cKetNx8sW5rTBA.png" alt="The textRender method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The textRender method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h3&gt;
  
  
  Image
&lt;/h3&gt;

&lt;p&gt;The imageRender method will have an inner render() function that it calls either right away or after it loads the image.&lt;/p&gt;

&lt;p&gt;This render function also checks for a scale property. If one exists, it will multiply the image width and height by the scale value. For instance, if a scale value of 0.75 is passed in, the image’s width and height will be resized to 75% of its natural dimensions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--onhcEsvn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2724/1%2A6uOJPlFOyHiczBDPfBH8bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--onhcEsvn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2724/1%2A6uOJPlFOyHiczBDPfBH8bg.png" alt="The imageRender method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The imageRender method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Because we cannot move forward until the image data first loads, we check to see if we have an Image object with a src. If not, we do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;create a new Image() object,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;set its src attribute,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;listen for an image onload event,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;and call therender() function when the image loads.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the image and its src are already defined, that means the image data has been loaded, so we render it immediately. Here is how it plays out in code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rqaSRzFY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2016/1%2A23E15-YLX1f6qeAE5kcxFg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rqaSRzFY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2016/1%2A23E15-YLX1f6qeAE5kcxFg.png" alt="Checking the image source."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;Checking the image source.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;And below is the complete imageRender method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--onhcEsvn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2724/1%2A6uOJPlFOyHiczBDPfBH8bg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--onhcEsvn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2724/1%2A6uOJPlFOyHiczBDPfBH8bg.png" alt="The imageRender method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The imageRender method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 7: Write the Update and Alpha Check Methods
&lt;/h2&gt;

&lt;p&gt;Let’s now write a method for updating the properties of the object that should be changing. These properties may include x, y, oralpha.&lt;/p&gt;

&lt;p&gt;So let’s now iterate through the properties in the object’s speed attribute using for...in syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compare current and ending values
&lt;/h3&gt;

&lt;p&gt;Once we lock onto a property, we will compare its value in cur with its value in stop. If cur is not at the stop value yet, we capture how far away they are in diff.&lt;/p&gt;

&lt;p&gt;If the diff is less than the absolute value of thespeed for this property, that’s close enough — so we set it to the stop value. If not, we increment the current property by the speed value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

     &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, the difference between start and stop does not have to be divisible by speed for the stop value to be reached. Full method below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UpkaONk2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2724/1%2A04Lj0fG45UxhQkp5VaqJQw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UpkaONk2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2724/1%2A04Lj0fG45UxhQkp5VaqJQw.png" alt="The updateProps method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The updateProps method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h3&gt;
  
  
  The alpha check
&lt;/h3&gt;

&lt;p&gt;Let’s write a quick method for transferring an object’s current alpha value to the globalAlpha property of its canvas rendering context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GwRuJ2yg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2928/1%2AuIZNSNSSKWx3G2OD63jYGA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GwRuJ2yg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2928/1%2AuIZNSNSSKWx3G2OD63jYGA.png" alt="The checkCanvasAlpha method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The checkCanvasAlpha method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 8: Write the Animate Method
&lt;/h2&gt;

&lt;p&gt;Now let’s write the animate method, which will clear the canvas, update the object, render one frame, delay if necessary, and request that it be called again if needed.&lt;/p&gt;

&lt;p&gt;Adding delay values for some objects help to choreograph their movements so they don’t all rush in at once .Let’s start by writing a promise-based helper function for the delay called sleep.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sleep = (ms) =&amp;gt; new Promise(resolve =&amp;gt; setTimeout(resolve, ms));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We will enclose this helper in a newanimate method, which isasync so we can use await sleep later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3oGLJjWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3064/1%2AQEQcHo0fktRqGYKznDKPVw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3oGLJjWn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3064/1%2AQEQcHo0fktRqGYKznDKPVw.png" alt="A start to the animate method with the sleep helper function."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;A start to the animate method with the sleep helper function.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Before moving ahead, let’s equip ourselves with one other helper function that checks on properties that are changing to see if another animation frame is needed. This will return a boolean value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uqjlD3oh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3064/1%2AoWYNi_nGj1vbyUH8XxeRFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uqjlD3oh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3064/1%2AoWYNi_nGj1vbyUH8XxeRFQ.png" alt="The frameNeeded function."&gt;&lt;/a&gt;&lt;em&gt;The frameNeeded function.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that we have created our helpers, let’s go ahead and clear our canvas element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clearRect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the first frame of this animation always reflects the initial properties, let’s update our properties only if the first frame has passed. We use this.started to check on this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;started&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateProps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
         &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkCanvasAlpha&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, let’s assemble the name of the render function by concatenating type with the string "Render". After that, we’ll call the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;func&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Render&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;]();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this animation has not been flagged as started and a delay value exists, we delay. The await blocks further progress on this method until the delay ends. Once it ends, we flag the animation as having started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;started&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;started&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;At this point, we can now check if another animation frame is needed. If it is, we request another animation frame. Below is how this part of the method looks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TOkYK3G4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2388/1%2AKfBFw5fZKVcDvEzSfUvdYg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TOkYK3G4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2388/1%2AKfBFw5fZKVcDvEzSfUvdYg.png" alt="If another frame is needed, let’s request one."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;If another frame is needed, let’s request one.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Notice that we call obj.animate() within the anim function, which then gets passed into window.requestAnimationFrame. When it comes time for the next frame, the anim function will kick off as a callback.&lt;/p&gt;

&lt;p&gt;As a result, this animation method will pass a call to itself into window.getAnimationFrame. These frame requests continue until the properties that are changing reach their stopping point, or until the animation restarts. We also collect request ID’s so we can cancel our frame requests if the animation is restarted.&lt;/p&gt;

&lt;p&gt;Here is the whole method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YkxwxX7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3096/1%2AjU5G75Mm53FkHlPMbVrzgA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YkxwxX7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3096/1%2AjU5G75Mm53FkHlPMbVrzgA.png" alt="The entire animate method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The entire animate method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 9: Write the Frame Cancel and Reset Methods
&lt;/h2&gt;

&lt;p&gt;If the user resets the animation, we want to cancel all frame requests. So let’s write a cancelFrames method that will be called when we trigger a reset.&lt;/p&gt;

&lt;p&gt;Here we have a while loop that runs as long as we have request ID’s in our reqIds array. We pop each reqID off the array and then use it to cancel the animation frame.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2E9hl_-z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2252/1%2AMpER_scpUl1ti5Rli2Psmg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2E9hl_-z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2252/1%2AMpER_scpUl1ti5Rli2Psmg.png" alt="The cancelFrames method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The cancelFrames method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h3&gt;
  
  
  Reset
&lt;/h3&gt;

&lt;p&gt;Below is the reset method, which will do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reset the started flag to false.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;return all cur attributes to their starting values&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sync the globalAlpha of the rendering context with the cur.alpha value, if it exists&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;call the cancelFrames method we just wrote.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WD4STBIm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2288/1%2AVuDL1it_leXjxiAtFCxrVQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WD4STBIm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2288/1%2AVuDL1it_leXjxiAtFCxrVQ.png" alt="The reset method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The reset method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Now let’s go back and replacethis.cur = {...this.start} within our original graphic constructor. In addition to resetting the cur properties, this will also initialize the canvas rendering context and the started flag. We can add it right at the end of the constructor, as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;graphic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

   &lt;span class="c1"&gt;// hidden code&lt;/span&gt;

   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Congratulations!
&lt;/h3&gt;

&lt;p&gt;You have finished the micro-library. Now let’s put it to work by creating the banner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10: Lay the groundwork for the banner
&lt;/h2&gt;

&lt;p&gt;Our banner will have a logo made of several parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a circle that descends from above&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a rectangle that rises from below&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;text saying “Nev’s” that slides in diagonally&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;text saying “Ice Cream” that fades in&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a small ice cream cone image that fades in&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, there will be two elements outside the logo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a large three-scope cone that slides in from the right&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;text saying “42 Flavors!” that slides in from the left&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are now outside of the library, so if you are working with files rather than a code sandbox, I recommend writing this banner-specific logic in a new JavaScript file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set the stage, colors, and constants
&lt;/h3&gt;

&lt;p&gt;Let’s start by creating a new wrapper for our banner logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s set the stage and background color.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setStage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setBackgroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightpink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, let’s initialize a colors constant to store hex codes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;demo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

      &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setStage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setBackgroundColor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lightpink&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;orange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffc44e&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#4795a7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;darkgreen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#356f7d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;demo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And while staying in the wrapper, let’s create aliases for the image URLs, which point to the image files in the public &lt;a href="https://github.com/nevkatz/canvas-demos"&gt;GitHub repository&lt;/a&gt; for this demo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;small_cone_src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://raw.githubusercontent.com/nevkatz/canvas-demos/main/demo1/images/cone-small-vert.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;large_cone_src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://raw.githubusercontent.com/nevkatz/canvas-demos/main/demo1/images/ice-cream.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;With our foundational code in place, let’s create our seven JavaScript objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 11: The Three-Scoop Cone
&lt;/h2&gt;

&lt;p&gt;Below is the code for our large ice cream cone with a few notable properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a descriptive label so screen readers pick it up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;aspeed property with x since it slides in horizontally from the right.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a scale property of 0.75 to make the image width and height 75% of the image’s natural dimensions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e2xAnwoc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2320/1%2A3ILEE-iW9SFMkM7bYRu05w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e2xAnwoc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2320/1%2A3ILEE-iW9SFMkM7bYRu05w.png" alt="The object for the large ice cream cone."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The object for the large ice cream cone.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;Notice in particular two other properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a type property that determines the rendering method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a label property that sets the aria-label attribute of its  element.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 12: The Logo Circle
&lt;/h2&gt;

&lt;p&gt;For our circle, the speed property only contains y since it drops from above while keeping its horizontal position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SGiVdddP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2048/1%2AGzFvug85Cx6MdO4UTD8FeQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SGiVdddP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2048/1%2AGzFvug85Cx6MdO4UTD8FeQ.png" alt="The logo circle object."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The logo circle object.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 13: The Logo’s Rectangle
&lt;/h2&gt;

&lt;p&gt;The rectangle's y value of its speed is negative since it is moving up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JAQhKAdi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2184/1%2AiT1DePYvZyppNYUNfOhKqQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JAQhKAdi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2184/1%2AiT1DePYvZyppNYUNfOhKqQ.png" alt="The object for the rectangle in the logo."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The object for the rectangle in the logo.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 14: The Ice Cream Text
&lt;/h2&gt;

&lt;p&gt;Notice that the “Ice Cream” text stays in the same spot the whole time. The only property changing is its alpha.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aj43ItTA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2152/1%2A5ErUocRFGTgP7GuzIHm9_w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aj43ItTA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2152/1%2A5ErUocRFGTgP7GuzIHm9_w.png" alt="The ice cream text object."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The ice cream text object.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 15: The &lt;em&gt;Nev’s&lt;/em&gt; Text
&lt;/h2&gt;

&lt;p&gt;Below is the code for the “Nev’s” text in the logo. The negative coordinates within the start property will make the text start out off-stage. After a half-second delay, it will slide diagonally into place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f50M41ls--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2120/1%2AUg9ld6xS5Af8YgOa8qrPAg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f50M41ls--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2120/1%2AUg9ld6xS5Af8YgOa8qrPAg.png" alt="The “Nev’s” text object."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The “Nev’s” text object.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 16: The Logo’s Small Ice Cream Cone
&lt;/h2&gt;

&lt;p&gt;Below is the code for the small ice cream cone. We will use the threealpha values here to modify the &lt;code&gt;globalAlpha&lt;/code&gt; property of the &amp;lt;canvas&amp;gt; element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1yRGDrYL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2252/1%2A2Xe4ZLoIwdknb1NhRxbKrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1yRGDrYL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2252/1%2A2Xe4ZLoIwdknb1NhRxbKrg.png" alt="The object for the small ice cream cone in the logo."&gt;&lt;/a&gt;&lt;em&gt;The object for the small ice cream cone in the logo.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 17: The “42 Flavors!” Text
&lt;/h2&gt;

&lt;p&gt;Below is the code for the “42 Flavors!” text. Notice the long delay value because it has to slide in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WonHF61f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2252/1%2AL973ScZAAFRQiO7PtvLHnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WonHF61f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2252/1%2AL973ScZAAFRQiO7PtvLHnw.png" alt="The “42 Flavors!” text object."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The “42 Flavors!” text object.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;
&lt;h2&gt;
  
  
  Step 18: The Kickoff Method
&lt;/h2&gt;

&lt;p&gt;Having initialized all seven objects, let’s now write a kickoff method called init. This will be the one method we attach to our inner pen object so we can call it from the outside. Here is the method shell with an array containing the objects we just created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;logo_rect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
               &lt;span class="nx"&gt;logo_circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="nx"&gt;flavors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
               &lt;span class="nx"&gt;large_cone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="nx"&gt;nevs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
               &lt;span class="nx"&gt;ic_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="nx"&gt;small_cone&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;While staying within this method, we will iterate through the array using for...of and call the animate method on each object. This is what starts the animation when a user first lands on the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  The click listener
&lt;/h3&gt;

&lt;p&gt;Because the animation can happen fast, it helps if the user can restart it — either by clicking the restart button or the image itself. Here is the plan.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Grab references to the restart button and stage with querySelectorAll&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Loop through both elements with for...of&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For each element, listen for a click event.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Handle a click by calling animate and then reset on each JavaScript object.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;els&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#restart,#stage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;els&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Below is the entire init method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--axy2IQ3R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2692/1%2AYGSwxkbSyd3q8YUbhPZ2Eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--axy2IQ3R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2692/1%2AYGSwxkbSyd3q8YUbhPZ2Eg.png" alt="The init method."&gt;&lt;/a&gt;&lt;/p&gt;
&lt;center&gt;&lt;small&gt;&lt;em&gt;The init method.&lt;/em&gt;&lt;/small&gt;&lt;/center&gt;

&lt;p&gt;After writing the init method, you can now call demo.init() outside your wrapper to make your animated banner come to life.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Finished Banner
&lt;/h2&gt;

&lt;p&gt;Below is the completed Pen once again so you can compare it with your work. The code for this tutorial is also available for download on &lt;a href="https://github.com/nevkatz/canvas-demos"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;If you want to design HTML5 animations at a reasonable pace, you can benefit from having a library to reach for. While third party libraries abound, you can also build a lightweight, custom-made library like this one that is tailored to your project’s needs.&lt;/p&gt;

&lt;p&gt;Thanks for reading, and I hope you found this helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elsewhere
&lt;/h2&gt;

&lt;p&gt;Below are two other JavaScript articles that you may enjoy reading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://betterprogramming.pub/create-your-own-html5-canvas-toolkit-with-vanilla-javascript-1d2ad1047219?sk=d381699afd03f1a953acbebd17503b86"&gt;Create Your Own HTML5 Canvas Toolkit With Vanilla JavaScript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://betterprogramming.pub/7-approaches-to-rewriting-javascript-from-my-early-days-c6ada526d55f?sk=943c7f6366a06aa724d18451671cb35d"&gt;7 Tricks I Use To Rewrite JavaScript Code From My Early Days&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>9 Tips for Tech Demo Teams</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Thu, 03 Jun 2021 23:45:48 +0000</pubDate>
      <link>https://dev.to/nevkatz/9-tips-for-tech-demo-teams-e5o</link>
      <guid>https://dev.to/nevkatz/9-tips-for-tech-demo-teams-e5o</guid>
      <description>&lt;p&gt;Hi all,&lt;/p&gt;

&lt;p&gt;After holding a demo of a new entrepreneurship app with our team, I was inspired to write an &lt;a href="https://medium.com/geekculture/9-tips-for-tech-demo-teams-c22ffb4d099f?sk=ebe1f6d501cb8728e7900cb55d9fed71"&gt; article&lt;/a&gt; for teams who are planning to give a tech demo. The tips that I discuss in detail are the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify the audience.&lt;/li&gt;
&lt;li&gt;Discuss the features you will focus on.&lt;/li&gt;
&lt;li&gt;Plan out how to handle critical questions.&lt;/li&gt;
&lt;li&gt;Test the features you plan to demo relentlessly.&lt;/li&gt;
&lt;li&gt;Establish roles.&lt;/li&gt;
&lt;li&gt;Work out the logistics.&lt;/li&gt;
&lt;li&gt;Set limits on preparation.&lt;/li&gt;
&lt;li&gt;Stay flexible under adversity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me know what you think of it and I hope it helps with your demo planning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/geekculture/9-tips-for-tech-demo-teams-c22ffb4d099f?sk=ebe1f6d501cb8728e7900cb55d9fed71"&gt;9 Tips for Tech Demo Teams&lt;/a&gt;, Geek Culture&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>testdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Create Your Own HTML5 Canvas Toolkit With Vanilla JavaScript</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Thu, 27 May 2021 17:27:50 +0000</pubDate>
      <link>https://dev.to/nevkatz/create-your-own-html5-canvas-toolkit-with-vanilla-javascript-4gl9</link>
      <guid>https://dev.to/nevkatz/create-your-own-html5-canvas-toolkit-with-vanilla-javascript-4gl9</guid>
      <description>&lt;p&gt;Happy Thursday, everyone - wanted to reach out with a quick &lt;a href="https://betterprogramming.pub/create-your-own-html5-canvas-toolkit-with-vanilla-javascript-1d2ad1047219?sk=d381699afd03f1a953acbebd17503b86"&gt;tutorial&lt;/a&gt; on how to build a flexible and easily readable HTML5 Canvas toolkit using Vanilla JavaScript. &lt;/p&gt;

&lt;p&gt;A little background: when I started at EDC over 12 years ago, I came in as a Flash developer. Once Flash lost prominence, I learned more programming, dove headfirst into the web and app development space, and moved to developing interactives with JavaScript. Given the untimely demise of Flash, it was a good move.&lt;/p&gt;

&lt;p&gt;The advent of HTML5 brought with it the &lt;code&gt;canvas&lt;/code&gt; element, which could be controlled with JS. One of the challenges I found fairly early with the canvas API was that it was very low level - so I started trying HTML5 canvas frameworks like EaselJS and KineticJS. The former was awesome but felt overly complex for what I needed. And the latter lost support shortly after I tried using it. Because the framework landscape is ever-changing and does not always have the options I have in mind, I have found it empowering to create canvas utility methods that do exactly what I want and can be called easily.&lt;/p&gt;

&lt;p&gt;In this article, I go over how to add methods for creating a circle and a polygon. That said, I'd be happy to write tutorials on other methods - such as text, animations, and images - if people are interested. Thanks, and have a great day.&lt;/p&gt;

</description>
      <category>html</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>7 Tricks I Use To Rewrite JavaScript Code From My Early Days</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Wed, 26 May 2021 12:19:54 +0000</pubDate>
      <link>https://dev.to/nevkatz/7-tricks-i-use-to-rewrite-javascript-code-from-my-early-days-1745</link>
      <guid>https://dev.to/nevkatz/7-tricks-i-use-to-rewrite-javascript-code-from-my-early-days-1745</guid>
      <description>&lt;p&gt;For the past four years, I have been working on a Cordova app that runs on JavaScript. The codebase has grown to the point where working on it often feels like wandering through streets and alleys of a large city. And looking at some of the earlier modules feels like sauntering into old buildings I originally constructed years ago.&lt;/p&gt;

&lt;p&gt;While my JS coding has evolved over this time, I often run into code in the app that feels inefficient and outdated - and it bothers me to the point where I usually feel compelled to eventually refactor it so that it is more compact, readable, and understandable.&lt;/p&gt;

&lt;p&gt;Here are &lt;a href="https://betterprogramming.pub/7-approaches-to-rewriting-javascript-from-my-early-days-c6ada526d55f?sk=943c7f6366a06aa724d18451671cb35d"&gt;7 time-tested tricks&lt;/a&gt; I use to rewrite my JavaScript code from those early days, published this month in Better Programming. I hope you find them useful. Enjoy!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>refactorit</category>
    </item>
    <item>
      <title>Debugging Tactics</title>
      <dc:creator>Nevin Katz</dc:creator>
      <pubDate>Mon, 03 May 2021 21:07:58 +0000</pubDate>
      <link>https://dev.to/nevkatz/debugging-tactics-2o8e</link>
      <guid>https://dev.to/nevkatz/debugging-tactics-2o8e</guid>
      <description>&lt;p&gt;&lt;em&gt;“At some point, everything's gonna go south on you and you're going to say, this is it. This is how I end. Now you can either accept that, or you can get to work.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;—Mark Watney, &lt;em&gt;The Martian&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;This quote inspired me to write an &lt;a href="https://nevkatz.medium.com/7-strategies-for-finding-the-toughest-bugs-in-your-code-19b40573b4c2?sk=b3a91b91d1be9369ffec8cd900c9fd4a"&gt;article&lt;/a&gt; on how to survive when faced with a seemingly insurmountable bug in your project. Before you scream into the void about your ever-elusive bug, check out &lt;a href="https://nevkatz.medium.com/7-strategies-for-finding-the-toughest-bugs-in-your-code-19b40573b4c2?sk=b3a91b91d1be9369ffec8cd900c9fd4a"&gt;Seven Strategies for Finding the Toughest Bugs in Your Code&lt;/a&gt;. Who knows - it may be hiding in plain sight.&lt;/p&gt;

&lt;p&gt;Encounters with tough-to-solve bugs can make coding feel like a rollercoaster of hopelessness and euphoria. And sometimes you are the only one who will have the background knowledge needed to solve them efficiently.&lt;/p&gt;

&lt;p&gt;If you've already been at it for hours, you're not alone. &lt;/p&gt;

&lt;p&gt;And if it has been a bug-free week so far, there's still time - so keep some of these tips in your back pocket next time you find yourself down the rabbit hole. &lt;/p&gt;

&lt;p&gt;You can do it.&lt;/p&gt;

</description>
      <category>java</category>
      <category>javascript</category>
      <category>python</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
