<?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: Miriam Zusin</title>
    <description>The latest articles on DEV Community by Miriam Zusin (@mzusin).</description>
    <link>https://dev.to/mzusin</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%2F1073921%2F1ca496d9-2c4a-4f01-b005-ed4b107383ba.jpeg</url>
      <title>DEV Community: Miriam Zusin</title>
      <link>https://dev.to/mzusin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mzusin"/>
    <language>en</language>
    <item>
      <title>How to Drag a Shape Along an SVG Ellipse Path: A Step-by-Step Guide</title>
      <dc:creator>Miriam Zusin</dc:creator>
      <pubDate>Mon, 05 Jun 2023 16:04:49 +0000</pubDate>
      <link>https://dev.to/mzusin/how-to-drag-a-shape-along-an-svg-ellipse-path-a-step-by-step-guide-3b66</link>
      <guid>https://dev.to/mzusin/how-to-drag-a-shape-along-an-svg-ellipse-path-a-step-by-step-guide-3b66</guid>
      <description>&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG"&gt;SVG&lt;/a&gt; (Scalable Vector Graphics) is a powerful tool for creating interactive and dynamic graphics on the web. One interesting feature is the ability to animate and manipulate shapes along a predefined path. In this article, we will explore the step-by-step process of implementing this feature using &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;HTML Markup&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Drag and Drop&lt;/li&gt;
&lt;li&gt;Ellipse Movement&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  HTML Markup
&lt;/h2&gt;

&lt;p&gt;First, let's define an HTML file called &lt;code&gt;index.html&lt;/code&gt; that will serve as the container for our SVG element and any accompanying JavaScript and CSS files.&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; 
     &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; 
     &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Tutorial&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element"&gt;SVG element&lt;/a&gt; with a width of 500 pixels and a height of 300 pixels using the following code:&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;svg&lt;/span&gt; 
   &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"svg"&lt;/span&gt; 
   &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; 
   &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; 
   &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tag serves as the container for our upcoming animation along the SVG ellipse path.&lt;/p&gt;

&lt;p&gt;Now let's create &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse"&gt;an ellipse element&lt;/a&gt; that will be used as the motion path. The ellipse is defined with a center point at coordinates (250, 150), which is half the height and width of the SVG container.&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;svg&lt;/span&gt; 
   &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"svg"&lt;/span&gt; 
   &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; 
   &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; 
   &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ellipse&lt;/span&gt;
     &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"250"&lt;/span&gt;
     &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt;
     &lt;span class="na"&gt;rx=&lt;/span&gt;&lt;span class="s"&gt;"245"&lt;/span&gt; 
     &lt;span class="na"&gt;ry=&lt;/span&gt;&lt;span class="s"&gt;"145"&lt;/span&gt;
     &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
     &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#3d8ea7"&lt;/span&gt;
     &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ellipse&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stroke of an ellipse determines the outline or boundary of the shape. In our case, the ellipse has a stroke defined by the attributes &lt;code&gt;stroke="#3d8ea7"&lt;/code&gt; and &lt;code&gt;stroke-width="10"&lt;/code&gt;. This means the stroke color is set to a shade of green, and the stroke width is set to 10 units.&lt;/p&gt;

&lt;p&gt;When a stroke is applied to an ellipse, it typically follows the boundary of the shape. In this case, with a stroke width of &lt;code&gt;10 units&lt;/code&gt;, the stroke will extend &lt;code&gt;5 units&lt;/code&gt; inside the ellipse and &lt;code&gt;5 units&lt;/code&gt; outside the ellipse. &lt;/p&gt;

&lt;p&gt;This results in half of the stroke being rendered inside the ellipse, while the other half is rendered outside. Therefore, the horizontal and vertical radius should be 5 units less &lt;code&gt;(245, 145)&lt;/code&gt;, otherwise, the ellipse will go outside the SVG container.&lt;/p&gt;

&lt;p&gt;Now let's add the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle"&gt;circle shape&lt;/a&gt; that will be dragged by mouse along the ellipse path:&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;svg&lt;/span&gt; 
   &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"svg"&lt;/span&gt; 
   &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; 
   &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; 
   &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ellipse&lt;/span&gt;
     &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"250"&lt;/span&gt;
     &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt;
     &lt;span class="na"&gt;rx=&lt;/span&gt;&lt;span class="s"&gt;"245"&lt;/span&gt; 
     &lt;span class="na"&gt;ry=&lt;/span&gt;&lt;span class="s"&gt;"145"&lt;/span&gt;
     &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
     &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#3d8ea7"&lt;/span&gt;
     &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ellipse&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; 
     &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt;
     &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"495"&lt;/span&gt; 
     &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt; 
     &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt; 
     &lt;span class="na"&gt;cursor=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt; 
     &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#efefef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/circle&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This circle element is positioned at coordinates &lt;code&gt;(495, 150)&lt;/code&gt; with a radius &lt;code&gt;(r)&lt;/code&gt; of 30 units. It has a cursor style set to "pointer," indicating that it should change to a pointer cursor when hovered over. &lt;/p&gt;

&lt;p&gt;The x position is 495 because we're subtracting half of the &lt;code&gt;stroke-width&lt;/code&gt; (5) from the container's width (500) so that the circle is in the middle of the path.&lt;/p&gt;

&lt;p&gt;But after we look at the result, it turns out that the circle is outside the SVG container. To fix this, we can change the markup like this:&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;svg&lt;/span&gt; 
   &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"svg"&lt;/span&gt; 
   &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; 
   &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; 
   &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ellipse&lt;/span&gt;    
     &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"250"&lt;/span&gt;
     &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt;
     &lt;span class="na"&gt;rx=&lt;/span&gt;&lt;span class="s"&gt;"220"&lt;/span&gt; 
     &lt;span class="na"&gt;ry=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt;
     &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
     &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#3d8ea7"&lt;/span&gt;
     &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ellipse&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; 
     &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt;
     &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"470"&lt;/span&gt; 
     &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt; 
     &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt; 
     &lt;span class="na"&gt;cursor=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt; 
     &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#efefef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/circle&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here in the ellipse, the horizontal radius &lt;code&gt;220 = (500/2 - 30)&lt;/code&gt; is equal to half the width of the SVG container minus the width of the pointer circle. The same with the vertical radius &lt;code&gt;120 = (300/2 - 30)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The horizontal position of the pointer circle is equal to the &lt;br&gt;
 SVG width minus the width of the circle &lt;code&gt;470 = 500 - 30&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  TypeScript
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we will be using &lt;a href="https://www.typescriptlang.org/"&gt;TypeScript&lt;/a&gt;. TypeScript is a programming language that is a superset of JavaScript that adds a layer of static typing, allowing developers to define types for variables, function parameters, and return values. This helps catch errors during development and provides better tooling support for code completion and refactoring. &lt;/p&gt;

&lt;p&gt;I will use TypeScript with &lt;a href="https://esbuild.github.io/"&gt;esbuild bundler&lt;/a&gt;, which is a fast and highly efficient builder for JavaScript and TypeScript.&lt;/p&gt;

&lt;p&gt;Make sure you have &lt;a href="https://nodejs.org/en"&gt;node.js&lt;/a&gt; installed and open a terminal in your project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
npm install esbuild typescript --save-dev
tsc --init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command &lt;code&gt;npm init -y&lt;/code&gt; is used to initialize a new npm &lt;br&gt;
 project with default settings. When you run this command in your project's root directory, it creates a package.json file with basic information about your project.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;npm install esbuild typescript --save-dev&lt;/code&gt; is used to install the "esbuild" and "typescript" packages as devDependencies in your npm project.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;tsc --init&lt;/code&gt; is used to initialize a TypeScript project by generating a &lt;a href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html"&gt;tsconfig.json&lt;/a&gt; file in the current directory. This file contains various configuration options for the TypeScript compiler. By customizing the tsconfig.json file, you can configure TypeScript compilation settings, define the project's file structure, enable specific features, and more.&lt;/p&gt;

&lt;p&gt;Let's create an &lt;code&gt;index.ts&lt;/code&gt; file with the following content:&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&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 we can add the &lt;strong&gt;start&lt;/strong&gt; command to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tutorial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./node_modules/.bin/esbuild index.ts --bundle --watch --outfile=index.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"devDependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esbuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^0.17.19"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5.1.3"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command &lt;code&gt;./node_modules/.bin/esbuild index.ts --bundle --watch --outfile=index.js&lt;/code&gt; uses the locally installed esbuild package to bundle the &lt;code&gt;index.ts&lt;/code&gt; file and generate an &lt;code&gt;index.js&lt;/code&gt; output file. Here's a breakdown of the command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;./node_modules/.bin/esbuild&lt;/code&gt;: This specifies the path to the esbuild executable script located in the node_modules/.bin directory of your project. By running this script, you invoke the esbuild bundler.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;index.ts&lt;/code&gt;: This is the entry file for the bundling process. It specifies the TypeScript file that will be processed and bundled.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--bundle&lt;/code&gt;: This flag tells esbuild to perform the bundling process, which combines multiple files into a single output file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--watch&lt;/code&gt;: This flag instructs esbuild to watch for changes in the source files and automatically trigger a new build whenever a change is detected. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--outfile=index.js&lt;/code&gt;: This flag specifies the output file name and path for the bundled JavaScript file. In this case, the output file will be named &lt;code&gt;index.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can run the &lt;code&gt;npm start&lt;/code&gt; command in the terminal to generate the &lt;strong&gt;index.js&lt;/strong&gt; file. Esbuild will watch for changes in source files and automatically recompile the code. To exit watch mode, simply press &lt;code&gt;Ctrl C&lt;/code&gt; in the terminal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drag and Drop
&lt;/h2&gt;

&lt;p&gt;To implement the drag and drop functionality inside SVG, we can start by selecting the svg and circle elements with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById"&gt;getElementById&lt;/a&gt;:&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="cm"&gt;/**
 * This is where we place all the initialization logic.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$svg&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svg&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;$pointer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pointer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$svg&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$pointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The HTML file should have a javascript reference now:&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="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; 
      &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; 
      &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Tutorial&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; 
      &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"svg"&lt;/span&gt;
      &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; 
      &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"500"&lt;/span&gt; 
      &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;ellipse&lt;/span&gt;
                &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"250"&lt;/span&gt;
                &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt;
                &lt;span class="na"&gt;rx=&lt;/span&gt;&lt;span class="s"&gt;"220"&lt;/span&gt;
                &lt;span class="na"&gt;ry=&lt;/span&gt;&lt;span class="s"&gt;"120"&lt;/span&gt;
                &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
                &lt;span class="na"&gt;stroke=&lt;/span&gt;&lt;span class="s"&gt;"#3d8ea7"&lt;/span&gt;
                &lt;span class="na"&gt;stroke-width=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/ellipse&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt;
                &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt;
                &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;"470"&lt;/span&gt;
                &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;"150"&lt;/span&gt;
                &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;"30"&lt;/span&gt;
                &lt;span class="na"&gt;cursor=&lt;/span&gt;&lt;span class="s"&gt;"pointer"&lt;/span&gt;
                &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"#efefef"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/circle&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;

   &lt;span class="c"&gt;&amp;lt;!-- Reference to the compiled JavaScript file --&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"index.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's implement the basic drag and drop flow. The code below attaches event listeners to the $pointer element to handle mouse and touch events.&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="cm"&gt;/**
 * This is where we place all the initialization logic.
 */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$svg&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;svg&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;$pointer&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pointer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$svg&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;$pointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Here will be all the logic related to pointer movement.
     */&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Add event listeners as soon as 
     * the user presses the mouse button.
     */&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMouseDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&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;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="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;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="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;mouseup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMouseUp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="cm"&gt;/**
     * Remove event listeners as soon as 
     * the user releases the mouse button.
     */&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onMouseUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouseup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Attach event listeners to the $pointer element&lt;/span&gt;
    &lt;span class="c1"&gt;// to handle mouse and touch events.&lt;/span&gt;
    &lt;span class="nx"&gt;$pointer&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;mousedown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMouseDown&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$pointer&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;mouseup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMouseUp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$pointer&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;touchmove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;$pointer&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;touchstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;init&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 add event listeners for the mouse and touch events on the $pointer element. When the user presses or releases the mouse button on the element, the relevant function will be called to handle the event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ellipse Movement
&lt;/h2&gt;

&lt;p&gt;First we need to find out the mouse coordinates. The way it is determined will be different for mouse events and touch events. One way to do this is to use the &lt;code&gt;evt.type&lt;/code&gt;property, which represents the type of event that occurred:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mouseX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mouseY&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;isMouse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMouse&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="c1"&gt;// Mouse events &lt;/span&gt;
        &lt;span class="nx"&gt;mouseX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;mouseY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Touch events&lt;/span&gt;
        &lt;span class="nx"&gt;mouseX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;touches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;mouseY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;touches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mouseX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mouseY&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 also define some constants, such as the radii of the ellipse and its center. In actual production code, we can find these values dynamically, but in this demo, we define them as constants to keep the code simple.&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="c1"&gt;// The ellipse path radii constants.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RADIUS_X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;220&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;RADIUS_Y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The absolute top left coordinates of the SVG.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ABS_SVG_LEFT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ABS_SVG_TOP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SVG_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SVG_HEIGHT&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$svg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// The center of the SVG.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SVG_CENTER_LEFT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SVG_WIDTH&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SVG_CENTER_TOP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SVG_HEIGHT&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These lines calculate the center coordinates of the SVG element and store them in variables &lt;code&gt;SVG_CENTER_LEFT&lt;/code&gt; and &lt;code&gt;SVG_CENTER_TOP&lt;/code&gt;. The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect"&gt;getBoundingClientRect()&lt;/a&gt; method is called on the $svg element to obtain its bounding rectangle, which includes properties like &lt;code&gt;left&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;, and &lt;code&gt;height&lt;/code&gt;. Using destructuring assignment, the values of left and top properties are extracted and assigned to &lt;code&gt;ABS_SVG_LEFT&lt;/code&gt; and &lt;code&gt;ABS_SVG_TOP&lt;/code&gt; variables respectively.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onValueChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mouseX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mouseY&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;isMouse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mouse&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isMouse&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;mouseX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;mouseY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;clientY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;mouseX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;touches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;clientX&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;mouseY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;TouchEvent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;touches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;clientY&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 relative mouse position.&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;relativeMouseX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mouseX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ABS_SVG_LEFT&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;SVG_CENTER_LEFT&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;relativeMouseY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mouseY&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ABS_SVG_TOP&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;SVG_CENTER_TOP&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;By subtracting the coordinates of the SVG center from the mouse coordinates, the resulting values &lt;code&gt;relativeMouseX&lt;/code&gt; and &lt;code&gt;relativeMouseY&lt;/code&gt; represent the mouse's position relative to the center of the SVG element.&lt;/p&gt;

&lt;p&gt;Now we need to calculate the angle inside the ellipse that represents the current mouse position. We can use the &lt;code&gt;Math.atan2()&lt;/code&gt; function that returns the angle in radians between the positive x-axis and the point represented by the mouse.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;angle&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;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;relativeMouseY&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;RADIUS_Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
  &lt;span class="nx"&gt;relativeMouseX&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;RADIUS_X&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;relativeMouseX / RADIUS_X&lt;/code&gt;: This expression calculates the relative horizontal distance from the SVG center along the x-axis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;relativeMouseY / RADIUS_Y&lt;/code&gt;: This expression calculates the relative vertical distance from the SVG center along the y-axis.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have the angle, we can calculate the new coordinate of the pointer's center along the ellipse path. To do this, we can use the &lt;a href="https://www.mathopenref.com/coordparamellipse.html"&gt;parametric equation of an ellipse&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x(angle) = radius1 * cos(angle)
y(angle) = radius2 * sin(angle)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the final part of the &lt;code&gt;onValueChange()&lt;/code&gt; function would be:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newX&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SVG_CENTER_LEFT&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;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;RADIUS_X&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;newY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SVG_CENTER_TOP&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;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;RADIUS_Y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Update the pointer's center coordinates.&lt;/span&gt;
&lt;span class="nx"&gt;$pointer&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;cx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newX&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;$pointer&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;cy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&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 provided code, two variables &lt;code&gt;newX&lt;/code&gt; and &lt;code&gt;newY&lt;/code&gt; are calculated based on the angle and the radii of the SVG ellipse. These variables represent the new center coordinates for the &lt;code&gt;$pointer&lt;/code&gt; element. Then, the &lt;code&gt;cx&lt;/code&gt; and &lt;code&gt;cy&lt;/code&gt; attributes of the $pointer element are updated to move it to the new coordinates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The final result can be found in this &lt;a href="https://codepen.io/1rosehip/pen/oNaKRyN"&gt;codepen&lt;/a&gt; and also on &lt;a href="https://github.com/mzusin/articles/tree/main/how-to-drag-a-shape-along-an-svg-ellipse-path"&gt;GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This code can easily be adapted to a circular path instead of an ellipse by making one radius instead of two. Please check &lt;a href="https://codepen.io/1rosehip/pen/poQzKyP"&gt;this codepen&lt;/a&gt; as an example.&lt;/p&gt;

&lt;p&gt;I hope this article was interesting and helpful in your programming journey. Happy coding! 🙃&lt;/p&gt;

&lt;p&gt;Also please take a look at &lt;a href="https://github.com/mzusin/toolcool-range-slider"&gt;Tool Cool Range Slider&lt;/a&gt; project. It is a responsive range slider library written in typescript and using web component technologies. It has a rich set of settings, including any number of pointers (knobs), vertical and horizontal slider, touch, mousewheel and keyboard support, local and session storage, range dragging, and RTL support. &lt;/p&gt;

</description>
      <category>svg</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
