<?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: Christian Diederich</title>
    <description>The latest articles on DEV Community by Christian Diederich (@chrdiede).</description>
    <link>https://dev.to/chrdiede</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%2F180251%2Fb6f00140-b2b1-4abc-8584-45fd4362899c.jpg</url>
      <title>DEV Community: Christian Diederich</title>
      <link>https://dev.to/chrdiede</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chrdiede"/>
    <language>en</language>
    <item>
      <title>I published a book about HTTP — it's free now (in German)</title>
      <dc:creator>Christian Diederich</dc:creator>
      <pubDate>Sun, 06 Apr 2025 05:56:49 +0000</pubDate>
      <link>https://dev.to/chrdiede/i-published-a-book-about-http-its-free-now-in-german-2dc</link>
      <guid>https://dev.to/chrdiede/i-published-a-book-about-http-its-free-now-in-german-2dc</guid>
      <description>&lt;p&gt;I have to put it into perspective:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technically it is a book, but it is actually a &lt;a href="https://en.wikipedia.org/wiki/Zine" rel="noopener noreferrer"&gt;zine&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I have already published it in 2023.&lt;/li&gt;
&lt;li&gt;It's written in German.&lt;/li&gt;
&lt;li&gt;It is &lt;a href="https://www.amazon.de/dp/3911235003" rel="noopener noreferrer"&gt;no longer available in book form&lt;/a&gt;, only on my blog in digital form.&lt;/li&gt;
&lt;li&gt;I did everything myself: content, production, distribution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, I did pretty much everything on my own. I was an author, graphic designer, book producer and publisher. The idea was to regularly publish zines about certain topics in software and web development with a bit of humor in an entertaining and easy-to-understand way.&lt;/p&gt;

&lt;p&gt;However, it turned out that the idea was too niche and not worth the effort. But it was fun and maybe I'll take up the subject again at some point. After all, there are still 299 &lt;a href="https://en.wikipedia.org/wiki/ISBN" rel="noopener noreferrer"&gt;ISBN&lt;/a&gt; left of the 300 I bought... 😅&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.diede.dev/blog/i-published-a-book-about-http" rel="noopener noreferrer"&gt;➡️ Here you can read it for free — in German&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>🍎 Kinetics for web developers</title>
      <dc:creator>Christian Diederich</dc:creator>
      <pubDate>Mon, 17 Mar 2025 11:11:37 +0000</pubDate>
      <link>https://dev.to/chrdiede/kinetics-for-web-developers-b8c</link>
      <guid>https://dev.to/chrdiede/kinetics-for-web-developers-b8c</guid>
      <description>&lt;p&gt;Mechanics and web development are not really topics that can be easily combined. Nevertheless, I'm going to try to introduce you to the world of kinetics, a branch of (technical) mechanics, using my JavaScript library &lt;em&gt;Whiskey Kinetics&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Don't expect to learn a lot of useful things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kinetics and the question of equilibrium
&lt;/h2&gt;

&lt;p&gt;In mechanics, kinetics basically describes the movement of a body, taking into account forces (and masses).&lt;/p&gt;

&lt;p&gt;Similar to statics, also a branch of mechanics, all forces acting on a body must neutralize each other. &lt;strong&gt;The sum of all forces must therefore always be 0!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Want an example?&lt;/p&gt;

&lt;p&gt;Imagine an apple hanging on a tree. The apple has a mass of 0.1 kg. A weight force of 0.981 N acts vertically downwards on this apple due to the acceleration of gravity. This follows Newton's 2nd law &lt;code&gt;mass * acceleration = force&lt;/code&gt;: 0.1 kg mass multiplied by the acceleration of gravity of 9.81 m/s² results in a weight force of 0.981 Newton.&lt;/p&gt;

&lt;p&gt;However, the apple does not fall, but remains in place. Therefore, exactly the same force must act in the opposite direction on the apple at the same time. This is the only way it can remain in place. This counterforce is exerted by the apple's stem, which in turn is attached to the tree. The stem therefore exerts a force of 0.981 N on the apple, but in the opposite direction to the weight force. &lt;code&gt;0.981 N - 0.981 N = 0&lt;/code&gt;. The equilibrium of forces is established. The apple hangs.&lt;/p&gt;

&lt;p&gt;Enough theory. Let's simulate it in &lt;em&gt;Whiskey Kinetics&lt;/em&gt; by injecting the following web component into the DOM:&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;whiskey-kinetics&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"450"&lt;/span&gt;
  &lt;span class="na"&gt;data-worker=&lt;/span&gt;&lt;span class="s"&gt;"./wk-apple.mjs"&lt;/span&gt;
  &lt;span class="na"&gt;data-attr-duration=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/whiskey-kinetics&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ℹ️ As you are reading a static version of this article, you will only see an animated GIF of the result. I therefore recommend that you &lt;a href="https://www.diede.dev/blog/kinetics-for-web-developers" rel="noopener noreferrer"&gt;read the original article and run the simulation in your browser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fx0u27c4qr0a9tj1qxx6n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fx0u27c4qr0a9tj1qxx6n.gif" alt="Simulation of an apple #1" width="790" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't be confused if nothing happens. You are looking at a fairly static simulation. But that will change in the following.&lt;/p&gt;

&lt;p&gt;As time goes on, the apple grows and eventually reaches a juicy mass of 0.2 kg. The stem would now have to exert a force of 1.96 N, which it cannot do due to its strength. The stem breaks, and suddenly, it can no longer withstand the force of the weight. The apple falls.&lt;/p&gt;

&lt;p&gt;But what about the force equilibrium? The constant weight force of 1.96 N still acts on the apple when it falls. Also, when falling, the forces acting on the apple must neutralize each other. This means that a new, invisible force must be acting on the apple somewhere so that Newton's 2nd law is not violated.&lt;/p&gt;

&lt;p&gt;The so-called inertial force sets in and acts against the direction of acceleration. You know this force from a vehicle accelerating &lt;em&gt;forwards&lt;/em&gt;. The inertial force pushes you &lt;em&gt;backwards&lt;/em&gt; into the seat.&lt;/p&gt;

&lt;p&gt;In the case of our apple, just like the good old force of the stem, it acts upwards against the direction of acceleration (direction of fall). When the stem breaks, it is immediately 100% present and keeps the balance of forces as if the stem had never broken. In purely mathematical terms, the inertial force is an equivalent replacement for the stem. In reality, however, it is somehow not because the apple still falls and obviously cannot adequately replace the stem. The inertial force is therefore also referred to as an pseudo force because it is somehow different. But that shouldn't bother us any further at this point. The important thing is that the apple falls and the equilibrium of forces is still established.&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;whiskey-kinetics&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"450"&lt;/span&gt;
  &lt;span class="na"&gt;data-worker=&lt;/span&gt;&lt;span class="s"&gt;"./wk-apple.mjs"&lt;/span&gt;
  &lt;span class="na"&gt;data-attr-duration=&lt;/span&gt;&lt;span class="s"&gt;"5.4"&lt;/span&gt;
  &lt;span class="na"&gt;data-attr-grow=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/whiskey-kinetics&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fxy3qrcup9pjno4yg49f8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxy3qrcup9pjno4yg49f8.gif" alt="Simulation of an apple #2" width="790" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's assume that the tree is standing on a very deep precipice and the apple falls for a really long time. How would the story continue? After all, the force of weight is constant. And according to our current knowledge, the inertial force would also be constant. However, a constant inertial force would result in a constant (gravitational) acceleration and this in turn would cause the apple to fall faster and faster. If the precipice were infinitely deep, the falling speed of the apple would also be infinitely fast at some point. Even before Einstein can veto this, we learn about another force: the drag force exerted by the surrounding air.&lt;/p&gt;

&lt;p&gt;The drag increases as the speed of the apple increases and acts in the same direction as the inertial force, i.e., in the opposite direction of the weight force. Due to the equilibrium of forces, the inertial force must inevitably become smaller. However, a smaller inertial force only means that the apple no longer accelerates quite as quickly. But it still accelerates, and as a result, the drag force becomes even greater. At some point, the time is reached where the drag force is just as great as the weight force of the apple. Mathematically, there is then no more room for the inertial force. It becomes 0. At that moment, the apple has reached its final speed and, from then on, falls at a constant speed.&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;whiskey-kinetics&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"450"&lt;/span&gt;
  &lt;span class="na"&gt;data-worker=&lt;/span&gt;&lt;span class="s"&gt;"./wk-apple.mjs"&lt;/span&gt;
  &lt;span class="na"&gt;data-attr-duration=&lt;/span&gt;&lt;span class="s"&gt;"20"&lt;/span&gt;
  &lt;span class="na"&gt;data-attr-grow=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/whiskey-kinetics&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fp5b5a0zw4gvkyvxrcc5r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fp5b5a0zw4gvkyvxrcc5r.gif" alt="Simulation of an apple #3" width="790" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how kinetics works. Simply put.&lt;/p&gt;

&lt;h2&gt;
  
  
  Whiskey Kinetics
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Whiskey Kinetics&lt;/em&gt; is the name of my library, which I use to calculate such things. Admittedly, it offers no real added value. I just developed it for fun. &lt;a href="https://github.com/cd/whiskey-kinetics" rel="noopener noreferrer"&gt;You can have a look at it on GitHub.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the previous interactive examples show, calculation scenarios can be easily integrated via web components.&lt;/p&gt;

&lt;p&gt;The custom element &lt;code&gt;&amp;lt;whiskey-kinetics&amp;gt;&lt;/code&gt; always refers to the same simulation file (&lt;code&gt;wk-apple.mjs&lt;/code&gt;) and generates different results based on a few modified parameters that you can define yourself (&lt;code&gt;data-attr-duration&lt;/code&gt; for the duration of the simulation and &lt;code&gt;data-attr-grow&lt;/code&gt; for a growing apple).&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;wk-apple.mjs&lt;/code&gt; itself, the scenario is modeled, the individual frames are calculated within a web worker thread, and then the corresponding frames are rendered in a &lt;code&gt;Canvas&lt;/code&gt; element using &lt;code&gt;window.requestAnimationFrame()&lt;/code&gt;. Each frame represents a certain period of time, for example 0.001 seconds. The smaller the period, the more accurate the simulation and the longer the calculation time.&lt;/p&gt;

&lt;p&gt;Each calculation scenario consists of objects of the type&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Particle&lt;/code&gt;, which represents a mass point, or&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Link&lt;/code&gt;, which establishes a connection between two mass points and can simulate real material behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are no more types or classes. These two are sufficient to carry out a large number of different simulations.&lt;/p&gt;

&lt;p&gt;The apple scenario, for example, consists of only 3 objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apple (&lt;code&gt;Particle&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Tree (&lt;code&gt;Particle&lt;/code&gt;, which here merely fulfills the role of a fixed point)&lt;/li&gt;
&lt;li&gt;Stem (&lt;code&gt;Link&lt;/code&gt; that connects the tree to the apple)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Schematic structure of the &lt;code&gt;wk-apple.mjs&lt;/code&gt;:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Particle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Vec2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./whiskey-kinetics.mjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Modeling the scenario&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Particle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... options ... */&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;apple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Particle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... options ... */&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;stem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* ... options ... */&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Set simulation and animation parameters&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&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;steps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&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;durationPerStep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;steps&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;fps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&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;denominator&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="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steps&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;fps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Prepare frame data for the animation (result)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;posApple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;speedApple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;weightApple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;isGrowing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;inertialForce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;dragForce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;forceStem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Calculate the frames&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Timestamp&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;durationPerStep&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Update apple's weight&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isGrowing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grow&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;stem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroyed&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;isGrowing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initalWeightApple&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt; &lt;span class="o"&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="c1"&gt;// Apply gravity to the apple&lt;/span&gt;
    &lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addAcceleration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vec2D&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="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;9.81&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Update / Calcuate the apple and stem&lt;/span&gt;
    &lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;stem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Record relevant frame data&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;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;denominator&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posApple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speedApple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;velocity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;weightApple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isGrowing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isGrowing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inertialForce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dragForce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forceStem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* .. */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Simulation is done&lt;/span&gt;
  &lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fps&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// In this function, the result is drawn based on the calculated&lt;/span&gt;
&lt;span class="c1"&gt;// frame data ('data.frames') and the current frame index.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;draw&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;frameIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;beginPath&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="nf"&gt;ellipse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posApple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;frameIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="c1"&gt;// ....&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  More examples
&lt;/h2&gt;

&lt;p&gt;This 4-joint crane, which moves a heavy ball and gets faster and faster, shows a somewhat more complex scenario:&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;whiskey-kinetics&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"450"&lt;/span&gt;
  &lt;span class="na"&gt;data-worker=&lt;/span&gt;&lt;span class="s"&gt;"./wk-four-bar.mjs"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/whiskey-kinetics&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fjs1cou8payb1iz6caj3l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjs1cou8payb1iz6caj3l.gif" alt="Simulation of a crane" width="790" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both the apple examples and the crane are modeled abstractly, as the geometry of the objects (or parts) is not really important, but rather the movements they perform. However, if you want to examine the object itself, you can use the same components (&lt;code&gt;Particle&lt;/code&gt;, &lt;code&gt;Link&lt;/code&gt;) to model geometries as a mesh. This allows you to load and inspect parts with a specific geometry. The principle is called &lt;a href="https://en.wikipedia.org/wiki/Finite_element_method" rel="noopener noreferrer"&gt;Finite Element Method&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To illustrate this, the last example shows a simple beam with cut-outs that is pulled at the end of the beam. Let 's see what weak points the component/geometry has and where it is likely to break.&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;whiskey-kinetics&lt;/span&gt;
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt;
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;
  &lt;span class="na"&gt;data-worker=&lt;/span&gt;&lt;span class="s"&gt;"./wk-beam.mjs"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/whiskey-kinetics&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2F43gpvzt97o7xg56ablz6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F43gpvzt97o7xg56ablz6.gif" alt="Simulation of a beam" width="500" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Forces act on objects. All forces must neutralize each other. Always.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Whiskey Kinetics&lt;/em&gt; is purely a fun project. Nevertheless, it can be used to simulate realistic material and movement behavior in both abstract and geometric ways.&lt;/li&gt;
&lt;li&gt;The apple doesn't fall far from the tree, unless the precipice is very deep.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>learning</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
