<?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: Duc Phat</title>
    <description>The latest articles on DEV Community by Duc Phat (@imaphatduc).</description>
    <link>https://dev.to/imaphatduc</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%2F873203%2F858c4228-242b-4e5e-bd82-278bafe26610.jpeg</url>
      <title>DEV Community: Duc Phat</title>
      <link>https://dev.to/imaphatduc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imaphatduc"/>
    <language>en</language>
    <item>
      <title>Cubecubed 💖 d3.js</title>
      <dc:creator>Duc Phat</dc:creator>
      <pubDate>Thu, 21 Jul 2022 14:33:45 +0000</pubDate>
      <link>https://dev.to/imaphatduc/cubecubed-d3js-64f</link>
      <guid>https://dev.to/imaphatduc/cubecubed-d3js-64f</guid>
      <description>&lt;p&gt;&lt;a href="https://d3js.org" rel="noopener noreferrer"&gt;d3.js&lt;/a&gt; is a JavaScript library used to manipulate the DOM through cake-simply syntax. You can think of it as the next-gen version of jQuery, but not quite. d3.js specifically focuses on data visualization. In addition, it helps you work with animations played by the tweening way (aka not WebAPI's &lt;code&gt;requestAnimationFrame&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/imaphatduc/cubecubed" rel="noopener noreferrer"&gt;Cubecubed&lt;/a&gt; intensively uses d3 in all SVG-related cubicon classes. In this article, I will show you the basic things you need to know about d3, and in the end explain how Cubecubed uses it to abstract the SVG rendering process in classes.&lt;/p&gt;

&lt;p&gt;So, let's start with the basic d3 methods.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  &lt;code&gt;append()&lt;/code&gt;, &lt;code&gt;select()&lt;/code&gt;, &lt;code&gt;attr()&lt;/code&gt; and &lt;code&gt;style()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In &lt;code&gt;index.html&lt;/code&gt;, we define these tags inside the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element:&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;h1&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;World&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is another way to achieve this entirely in JavaScript. We don't need to edit the HTML file then.&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;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&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="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&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="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&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="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&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="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;World&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;When we call &lt;code&gt;select("body")&lt;/code&gt; method, d3 will find the first body element and return a d3 selection object of it.&lt;/p&gt;

&lt;p&gt;Next, we select the first &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; like so:&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;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&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;Then, if we apply an attribute to the element, we can simply chain the code above with &lt;code&gt;attr()&lt;/code&gt; 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;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&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="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&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;hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rendered HTML on the browser will be like so:&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;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;World&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can we apply CSS styles to the element? You guess it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h1&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="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&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;hello&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="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&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;red&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;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52xn1f9v3ytu82iy2i8h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F52xn1f9v3ytu82iy2i8h.jpg" alt="Data Visualization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The magic of data join
&lt;/h2&gt;

&lt;p&gt;Consider this HTML structure:&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;h1&amp;gt;&lt;/span&gt;red&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;green&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;blue&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How can we add the corresponding color to each of the h1 element? One way to do this is adding classes, &lt;code&gt;select()&lt;/code&gt; the elements and apply colors to each of them. Something like this will work:&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;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;red&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"green"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;green&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;blue&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.red&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="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&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="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.green&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="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&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="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.blue&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="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color&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="s2"&gt;blue&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;What are the downsides of this approach? We have to add custom classes to the three h1 elements, and then violate the DRY principle by rewriting the classes when applying colors. Imagine the larger problem where we have hundreds of elements, I don't know about you, but to me I won't bother add hundreds of classes and then write hundreds of &lt;code&gt;select()&lt;/code&gt; methods.&lt;/p&gt;

&lt;p&gt;Maybe you have different approach from mine, but there is an awesome method built into d3 that perfectly works with this situation. That is the &lt;code&gt;data()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;First, let's define an array of color strings.&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;colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&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="s2"&gt;green&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="s2"&gt;blue&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;After that, we bibidi-babidi-booo with these lines of code.&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;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selectAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&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="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And boom, everything just works!&lt;/p&gt;

&lt;p&gt;What is going on here? First, we select all h1 elements, then call the &lt;code&gt;data()&lt;/code&gt; method on them. From this point, every next method in the current chain can take in an anonymous function with &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;i&lt;/code&gt; as parameters. These two parameters are exactly like those are in JavaScript &lt;code&gt;map()&lt;/code&gt; method: &lt;code&gt;d&lt;/code&gt; is the current item, and &lt;code&gt;i&lt;/code&gt; is its index in the array.&lt;/p&gt;

&lt;p&gt;With just three lines of code, we don't need to add any classes or call any method a hundred times. The reasonable result is that the array (along with objects are the &lt;code&gt;data&lt;/code&gt; in d3) needs to be updated to a hundred times then, which is no big deal if you have an active data store running.&lt;/p&gt;

&lt;p&gt;This is the nature of the term "data visualization" of d3. With more and more data passed into the &lt;code&gt;data()&lt;/code&gt; method, we can even create many SVG elements to easily visialize the data with graphs or charts.&lt;/p&gt;

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

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

&lt;h2&gt;
  
  
  &lt;code&gt;transition()&lt;/code&gt; kickstart
&lt;/h2&gt;

&lt;p&gt;The next thing that makes d3 a beast is its &lt;code&gt;transition()&lt;/code&gt; method. I used this in all types of SVG animation in Cubecubed.&lt;/p&gt;

&lt;p&gt;No more talking, let's dive into the code right now.&lt;/p&gt;

&lt;p&gt;First, we append an SVG &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle" rel="noopener noreferrer"&gt;&lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt;&lt;/a&gt; element into the body. The returned selection should be assigned to a variable.&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;circleSelection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body&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="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;circle&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="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;r&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill&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="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stroke&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="s2"&gt;#ffc777&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;To translate the rendered circle, we call the &lt;code&gt;transition()&lt;/code&gt; on the selection variable.&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;circleSelection&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transform&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="s2"&gt;translate(50, 50)&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;In the code above, we set the delay time (the amount of time before the animation can be played - in milliseconds, so 1000ms = 1s), along with the duration of the animation. Specifically, the animation waits 1 second, then slowly tweens the SVG &lt;code&gt;transform&lt;/code&gt; attributes until it reaches the value of &lt;code&gt;translate(50, 50)&lt;/code&gt;. The tween takes 2 seconds to finish itself.&lt;/p&gt;

&lt;p&gt;The reason why we tween the &lt;code&gt;translate&lt;/code&gt; attribute but not the &lt;code&gt;cx&lt;/code&gt; and &lt;code&gt;cy&lt;/code&gt; is that it appears in all SVG elements, while the two latter ones are defined specifically for &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt;. In Cubecubed, cubicon types have different base elements, from &lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;line&amp;gt;&lt;/code&gt; and so on. By that point, I want to utilize the &lt;code&gt;Translate&lt;/code&gt; animation class for all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cubecubed's principle for creating new cubicon types
&lt;/h2&gt;

&lt;p&gt;All cubicon types should be derived from &lt;code&gt;Cubicon&lt;/code&gt; abstract class. There are two mandatory properties: &lt;code&gt;g_cubiconWrapper&lt;/code&gt; and &lt;code&gt;def_cubiconBase&lt;/code&gt; that you need to assign d3 selections to in the constructor. The former is an SVG &lt;code&gt;&amp;lt;g&amp;gt;&lt;/code&gt; element that wraps around the latter, which is any SVG element that directly renders itself on the screen.&lt;/p&gt;

&lt;p&gt;All &lt;code&gt;append()&lt;/code&gt; method should be put inside the constructor. If you place it in the &lt;code&gt;render()&lt;/code&gt; method, the HTML structure will be filled with the appended elements every time the users call the method, which results in a mess.&lt;/p&gt;

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

&lt;p&gt;That's all you need to know about d3 library and how Cubecubed renders its cubicons.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>d3</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How the animation engine of Cubecubed works?</title>
      <dc:creator>Duc Phat</dc:creator>
      <pubDate>Thu, 30 Jun 2022 07:44:16 +0000</pubDate>
      <link>https://dev.to/imaphatduc/how-the-animation-engine-of-cubecubed-works-4m06</link>
      <guid>https://dev.to/imaphatduc/how-the-animation-engine-of-cubecubed-works-4m06</guid>
      <description>&lt;p&gt;Hello, everyone. It has been a tough day to me so far. Nah, it's okay, I can continue working with Cubecubed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=hZuYICAEN9Y"&gt;Summer of Math Exposition 2&lt;/a&gt; (#SoME2) &lt;del&gt;deadline&lt;/del&gt; is coming to town. If you haven't heard about it but want to make an explanatory math video then I would encourage you to join in the competition. August 15 is the deadline (we are much far from there).&lt;/p&gt;

&lt;p&gt;Cubecubed is the tool our team use for the final entry. It's not so great because it lacks a lot of features we need.&lt;/p&gt;

&lt;p&gt;But my point is not just that.&lt;/p&gt;

&lt;p&gt;As I said in the last article, my ambition for maintaining Cubecubed is to build a tool for teachers and students to visually interact with math. Cubecubed, still, has not gained much popularity, nor Manim nor any other visualization tools out there. So now, I am here, listing them to spread the word of teaching and learning math in a new way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The first version - the bad, the worst and the horrible
&lt;/h2&gt;

&lt;p&gt;Back when I first implemented the animation engine, it was a complete mess. The code is even the mystery to me, let alone other people. Maybe they just pass by the &lt;a href="https://github.com/imaphatduc/cubecubed"&gt;repo&lt;/a&gt; to see what is inside, or they want to contribute to it. I realized that is not fair to them. So I simplified it to a whole new level.&lt;/p&gt;

&lt;p&gt;Now I want to share it with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new one
&lt;/h2&gt;

&lt;p&gt;Let this small &lt;a href="https://imaphatduc.github.io/cubecubed/assets/videos/simpleScene.mp4"&gt;video&lt;/a&gt; exemplify it.&lt;/p&gt;

&lt;p&gt;The full code listing for the video is &lt;a href="https://imaphatduc.github.io/cubecubed/#/quickstart?id=all-code"&gt;here&lt;/a&gt;. We will not talk about the whole thing, but focus more on the animation stuff.&lt;/p&gt;

&lt;p&gt;Let's play the first animation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cubicon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;square1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="p"&gt;})]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;group.play()&lt;/code&gt; takes in an array of animations to play, which are technically called a &lt;code&gt;queue&lt;/code&gt; in Cubecubed. The current queue has only one animation &lt;code&gt;Create&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The man behind the mystery - &lt;code&gt;groupElapsed&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;Group&lt;/code&gt; class, &lt;code&gt;groupElapsed&lt;/code&gt; is a trivial property. It is the heart of the animation engine. When the engine sees the above line of code, it will play all of the animations included in the queue then calculate the time needed (which we call &lt;code&gt;queueElapsed&lt;/code&gt;) to finish them. &lt;code&gt;queueElapsed&lt;/code&gt; now has the value of 2000 (2 seconds).&lt;/p&gt;

&lt;p&gt;Move on to the next queue!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cubicon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;square2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Rotate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;cubicon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;square1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;degree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&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;
  
  
  Line up, guys!
&lt;/h3&gt;

&lt;p&gt;We all want the second queue plays after the last one has finished. Actually, this is a thing in Cubecubed. Queues are played sequentially, one after another. So what is the magic here? If you inspect the code of Cubecubed on GitHub, you'll see the &lt;code&gt;play()&lt;/code&gt; method of all animation classes take &lt;code&gt;sleepTime&lt;/code&gt; as a parameter. &lt;code&gt;sleepTime&lt;/code&gt; is the amount of time to wait before playing.&lt;/p&gt;

&lt;p&gt;But how can we calculate this &lt;code&gt;sleepTime&lt;/code&gt; magic?&lt;/p&gt;

&lt;p&gt;It's really simple. &lt;code&gt;sleepTime&lt;/code&gt; is just &lt;code&gt;Group().groupElapsed&lt;/code&gt; in disguise. Passing the former to the &lt;code&gt;play()&lt;/code&gt; methods solves everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Queue-mon says: "Just play, don't wait"
&lt;/h3&gt;

&lt;p&gt;We can see there are two animations in the queue now, &lt;code&gt;Create&lt;/code&gt; and &lt;code&gt;Rotate&lt;/code&gt;. Keep in mind, all animations in the &lt;strong&gt;same&lt;/strong&gt; queue will play asynchronously. But what exactly happens behind the scene?&lt;/p&gt;

&lt;p&gt;Similar to the last queue, the current one needs to calculate the &lt;code&gt;queueElapsed&lt;/code&gt;. But how?&lt;/p&gt;

&lt;p&gt;(Just to remind you, &lt;code&gt;groupElapsed&lt;/code&gt; is now 2000)&lt;/p&gt;

&lt;p&gt;Because the animations play asynchronously, we just need to take their maximum duration. Pseudocode: &lt;code&gt;queueElapsed = max(2000, 3000) = 3000&lt;/code&gt;, then &lt;code&gt;groupElapsed = groupElapsed + queueElapsed = 2000 + 3000 = 5000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Any next queues will have to wait 5 seconds, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guide for contributions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qB8S5Zo7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9p2wq09m0mqoh1eshwg4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qB8S5Zo7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9p2wq09m0mqoh1eshwg4.png" alt="camelCase" width="880" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you plan to code a new animation and create a PR to the GitHub repo, make sure the class has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;the constructor which takes in &lt;code&gt;params&lt;/code&gt; parameters, an object with &lt;code&gt;cubicon&lt;/code&gt;, &lt;code&gt;duration&lt;/code&gt; and &lt;code&gt;ease&lt;/code&gt; properties. If the &lt;code&gt;cubicon&lt;/code&gt; property accepts two or more cubicon types, please define the union TypeScript type for it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a &lt;code&gt;play(sleepTime: number)&lt;/code&gt; method. Then, create a private method, name it as the (camelCase) form of the class name (CamelCase). Finally, call it from the &lt;code&gt;play()&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Phew, just imagine how many words I would have written in this article if the animation engine did not improve. It would be a... Anyway, that is everything of the animation engine. In the next article, I will talk about &lt;a href="https://github.com/d3/d3"&gt;d3&lt;/a&gt; and how to render cubicons with it. It will definitely the great resource for you if you want to contribute to the Cubecubed project. So, stay tuned.&lt;/p&gt;

</description>
      <category>contributorswanted</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>github</category>
    </item>
    <item>
      <title>My story with Cubecubed</title>
      <dc:creator>Duc Phat</dc:creator>
      <pubDate>Mon, 06 Jun 2022 14:14:51 +0000</pubDate>
      <link>https://dev.to/imaphatduc/my-story-with-cubecubed-2da2</link>
      <guid>https://dev.to/imaphatduc/my-story-with-cubecubed-2da2</guid>
      <description>&lt;p&gt;Hello fellow developers on the Dev Community, this is my first post here. Today I want to tell you my journey with Cubecubed - a visualization engine for playing math animations right on the browser. Though it's just a small project of mine, I'm very proud of it. This is not a promotion post for its GitHub repo, but a story I want to tell you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manim and Me
&lt;/h2&gt;

&lt;p&gt;Just a little bit about myself: I'm a math enthusiast and a big fan of 3Blue1Brown's videos using the Manim engine.&lt;/p&gt;

&lt;p&gt;When I first saw Grant's videos on YouTube, I was so inspired by the quality of them. After that, I learned that Grant used a Python library called Manim to produce those videos. The first time I used Manim, it took me about half a day to just install it on my Windows machine (though Linux is completely ok). I have to tell you, the engine is great, but the installation and MP4 converting process is a pain in the ass. Besides of that, I want Manim to be accessible for everyone, ranging from teachers and students to math lovers like me, especially the ones who don't know how to code, and don't spend time learning it.&lt;/p&gt;

&lt;p&gt;So I had an idea: why don't I create a web version of Manim and turn it to a web app? That way, the users can click around, use the UI to achieve exactly the things that can be done by programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let the &lt;del&gt;journey&lt;/del&gt; problems begin!
&lt;/h2&gt;

&lt;p&gt;I tried Django. Frankly said, I'm too lazy to learn a whole new framework in a language that I'm not comfortable to work with. But there is a much larger problem: the users spend time creating math animations but cannot view the result immediately. I mean, they use the application and convert their Manim project to an MP4 file; if anything goes wrong they have to go all over again to find the "bug" and have no idea where it is. Even when they fix the "bug", they have to painfully wait for the converting process (and unfortunately, they find more bugs).&lt;/p&gt;

&lt;p&gt;I thought, "what can be the solution for both of those issues?" You can make a guess... That's right, the web! The browser is a wonderful place for playing dynamic animations and creating front-ends.&lt;/p&gt;

&lt;p&gt;From that time being, I took time to search for promising JavaScript libraries, and spent a lot of time playing with Three.js and Anime.js and GSAP and much more. Some of which are simply bloated for my use case, and the others don't have enough features. Then I met my best friend: d3.js. It's tiny yet powerful, and above all, the 'transition()' method. Paradise!&lt;/p&gt;

&lt;h2&gt;
  
  
  Publicize my project
&lt;/h2&gt;

&lt;p&gt;In December 2021, the first commit of Cubecubed was pushed to GitHub after a ton of customizations and refactoring. The first cubicons (equivalent to 'mobject' in Manim) were implemented, the name 'Cubecubed' and the project's logo was 'thought-provokingly' created.&lt;/p&gt;

&lt;p&gt;Initially, I wrote it in JavaScript, and some people on Reddit suggested me to covert it to TypeScript. I did convert it, with the help of an awesome developer on GitHub (@marvin-j97). I want to give a big thanks to the contributors, along with the people who saw my posts on Reddit and gave me nice words and suggestions to improve Cubecubed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://imaphatduc.github.io/cubecubed/#/showcase"&gt;Here&lt;/a&gt; are some showcase videos made by Cubecubed.&lt;/p&gt;

&lt;h2&gt;
  
  
  And that's it!
&lt;/h2&gt;

&lt;p&gt;Cubecubed is the project that I put a lot of time and efforts into. The making of it is always an enjoyable journey to me. I want to say that, the most important things are not GitHub stars but the time you spend fixing bugs and learning new things.&lt;/p&gt;

&lt;p&gt;Have a nice day everyone. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>motivation</category>
    </item>
  </channel>
</rss>
