Ethan Hughes

Ethan Hughes

1597257720

SVG Morphing Animation In JavaScript – Shapeshifter.js

Shapeshifter.js

Shapeshifter.js takes low poly SVGs and transforms them into each other. The shapes don’t need to have the same number of polygons. The polygons don’t need to have equal number of points. And the polygons can have different colors and opacity.

Preview

SETTING UP THE DOM

1- First of all you’ll need the SVG markup for the shapes you want to transform between. I personally use illustrator to draw the vectors and export the SVG code, but there are a lot of options obviously. This is the markup for two of the SVGs in the example.

<svg id="retriever" viewBox="0 0 227.49 200.03">
  <polygon points="144.38 0 177.82 20 192.51 88.14 144.38 0" style="fill: #f79a4c"/>
  <polygon points="192.51 88.14 190.63 104.7 135.91 126.59 141.78 38.86 192.51 88.14" style="fill: #f37944"/>
  <polygon points="190.63 104.7 182.82 120.95 149.69 171.59 135.91 126.59 190.63 104.7" style="fill: #ef4f2b"/>
  <polygon points="144.38 0 113.75 5.15 141.78 38.86 156.51 22.23 144.38 0" style="fill: #f37944"/>
  <polygon points="83.12 0 49.67 20 34.98 88.14 83.12 0" style="fill: #db3627"/>
  <polygon points="34.98 88.14 36.86 104.7 70.3 82.04 83.12 0 34.98 88.14" style="fill: #ef4f2b"/>
  <polygon points="36.86 104.7 44.67 120.95 77.8 171.59 91.58 126.59 36.86 104.7" style="fill: #f37944"/>
  <polygon points="83.12 0 113.75 5.15 94.06 22.19 83.12 0" style="fill: #f79a4c"/>
  <polygon points="149.69 171.59 142.66 188.36 135.91 126.59 149.69 171.59" style="fill: #db3627"/>
  <polygon points="77.8 171.59 84.84 188.36 91.58 126.59 77.8 171.59" style="fill: #f79a4c"/>
  <polygon points="142.66 188.36 132.66 197.32 113.75 200.03 91.58 126.59 113.75 133.61 135.91 126.59 142.66 188.36" style="fill: #ef4f2b"/>
  <polygon points="113.75 200.03 94.84 197.32 84.84 188.36 91.58 126.59 113.75 200.03" style="fill: #f37944"/>
  <polygon points="70.3 82.04 91.58 126.59 36.86 104.7 70.3 82.04" style="fill: #f79a4c"/>
  <polygon points="94.06 22.19 141.78 38.86 113.75 5.15 94.06 22.19" style="fill: #f4b84d"/>
  <polygon points="94.06 22.19 70.3 82.04 83.12 0 94.06 22.19" style="fill: #f37944"/>
  <polygon points="141.78 38.86 156.51 22.23 192.51 88.14 141.78 38.86" style="fill: #ef4f2b"/>
  <polygon points="70.3 82.04 138.48 88.14 141.78 38.86 94.06 22.19 70.3 82.04" style="fill: #f79a4c"/>
  <polygon points="113.75 97.83 135.91 126.59 138.48 88.14 113.75 97.83" style="fill: #f79a4c"/>
  <polygon points="113.75 97.83 91.58 126.59 113.75 133.61 135.91 126.59 113.75 97.83" style="fill: #904645"/>
  <polygon points="70.3 82.04 138.48 88.14 113.75 97.83 91.58 126.59 70.3 82.04" style="fill: #f4b84d"/>
  <polygon points="155.94 6.92 172.34 19.13 183.39 3.41 165.21 3.41 155.94 6.92" style="fill: #904645"/>
  <polygon points="183.39 3.41 203.78 9.06 172.34 19.13 183.39 3.41" style="fill: #c97979"/>
  <polygon points="172.34 19.13 179.71 31.17 181.67 43.95 203.78 9.06 172.34 19.13" style="fill: #b26060"/>
  <polygon points="203.78 9.06 219.51 20.36 227.49 40.63 181.33 52.02 181.67 43.95 203.78 9.06" style="fill: #a55555"/>
  <polygon points="227.49 40.63 226.85 50.09 213.95 91.91 181.33 77.54 181.33 52.02 227.49 40.63" style="fill: #904645"/>
  <polygon points="181.33 77.54 188.06 96.89 213.21 103.15 213.95 91.91 181.33 77.54" style="fill: #512927"/>
  <polygon points="188.06 96.89 204.41 113.1 213.21 103.15 188.06 96.89" style="fill: #381b1a"/>
  <polygon points="204.41 113.1 216.9 121.58 213.21 111.26 213.21 103.15 204.41 113.1" style="fill: #904645"/>
  <polygon points="71.55 6.92 55.15 19.13 44.1 3.41 62.28 3.41 71.55 6.92" style="fill: #904645"/>
  <polygon points="44.1 3.41 23.71 9.06 55.15 19.13 44.1 3.41" style="fill: #c97979"/>
  <polygon points="55.15 19.13 47.78 31.17 45.82 43.95 23.71 9.06 55.15 19.13" style="fill: #b26060"/>
  <polygon points="23.71 9.06 7.98 20.36 0 40.63 46.16 52.02 45.82 43.95 23.71 9.06" style="fill: #a55555"/>
  <polygon points="0 40.63 0.65 50.09 13.54 91.91 46.16 77.54 46.16 52.02 0 40.63" style="fill: #904645"/>
  <polygon points="46.16 77.54 39.43 96.89 14.28 103.15 13.54 91.91 46.16 77.54" style="fill: #512927"/>
  <polygon points="39.43 96.89 23.08 113.1 14.28 103.15 39.43 96.89" style="fill: #381b1a"/>
  <polygon points="23.08 113.1 10.6 121.58 14.28 111.26 14.28 103.15 23.08 113.1" style="fill: #904645"/>
  <polygon points="141.82 65.69 146.06 73.65 155.03 74.33 160.78 70.01 154.18 67.39 141.82 65.69" style="fill: #fff"/>
  <polygon points="85.67 65.69 81.44 73.65 72.47 74.33 66.71 70.01 73.31 67.39 85.67 65.69" style="fill: #fff"/>
</svg>

<svg id="passerine" viewBox="0 0 279.94 199.6">
  <polygon points="69.98 30.7 101 73.11 82.76 35.19 102.25 26.45 69.98 30.7" style="fill: #891b29"/>
  <polygon points="102.25 26.45 151.01 6.94 129.01 24.45 82.76 35.19 102.25 26.45" style="fill: #891b29"/>
  <polygon points="129.01 24.45 150.01 31.14 123.75 41.27 82.76 35.19 129.01 24.45" style="fill: #99293f"/>
  <polygon points="124 41.27 145.14 53.65 125.5 58.27 82.76 35.19 124 41.27" style="fill: #bc2a42"/>
  <polygon points="125.5 58.27 138.95 70.59 121.07 70.59 82.76 35.19 125.5 58.27" style="fill: #d33d4f"/>
  <polygon points="82.76 35.19 121.07 70.59 137.82 90.77 101 73.11 82.76 35.19" style="fill: #f24653"/>
  <polygon points="151.01 6.94 207.58 2.02 247.26 6.94 225.25 41.27 129.01 24.45 151.01 6.94" style="fill: #f37944"/>
  <polygon points="129.01 24.45 150.01 31.14 124 41.27 145.14 53.65 125.5 58.27 175.9 80.38 225.25 41.27 129.01 24.45" style="fill: #f79a4c"/>
  <polygon points="137.82 90.77 178.73 95.72 175.9 80.38 125.5 58.27 138.95 70.59 121.07 70.59 137.82 90.77" style="fill: #f4bd4d"/>
  <polygon points="37.35 33.87 32.34 14.53 21.51 27.7 0 30.37 37.35 33.87" style="fill: #512927"/>
  <polygon points="0 30.37 28.68 36.87 41.02 50.21 54.35 53.71 58.52 42.04 37.35 33.87 0 30.37" style="fill: #904645"/>
  <polygon points="54.35 53.71 68.86 49.08 51.19 9.69 32.34 14.53 37.35 33.87 58.52 42.04 54.35 53.71" style="fill: #f79a4c"/>
  <polygon points="68.86 49.08 77.97 41.27 69.98 30.7 77.03 29.77 69.98 18.11 51.19 9.69 68.86 49.08" style="fill: #f37944"/>
  <polygon points="178.73 95.72 219.41 70.59 198.64 62.36 175.9 80.38 178.73 95.72" style="fill: #bc2a42"/>
  <polygon points="219.41 70.59 234.74 41.27 226.88 38.73 225.25 41.27 198.64 62.36 219.41 70.59" style="fill: #99293f"/>
  <polygon points="234.74 41.27 255.05 19.26 279.94 3.75 258.68 5.25 223.54 0 207.58 2.02 247.26 6.94 226.88 38.73 234.74 41.27" style="fill: #891b29"/>
  <polygon points="54.35 53.71 75.36 94.39 82.76 47.6 77.97 41.27 68.86 49.08 54.35 53.71" style="fill: #ee4648"/>
  <polygon points="75.36 94.39 113.95 129.99 111.35 78.07 101 73.11 82.76 47.6 75.36 94.39" style="fill: #cc3635"/>
  <polygon points="113.95 129.99 142.72 144.24 124.94 84.59 111.35 78.07 113.95 129.99" style="fill: #992e2e"/>
  <polygon points="142.72 144.24 203.58 143.41 179.82 107.39 168.53 94.49 137.82 90.77 124.94 84.59 142.72 144.24" style="fill: #7f2422"/>
  <polygon points="164.26 143.95 202.58 163.25 222.25 199.6 245.26 194.09 211.91 155.91 179.9 143.73 164.26 143.95" style="fill: #e2c534"/>
  <polygon points="203.58 143.41 219.41 150.52 259.1 179.25 243.82 192.45 211.91 155.91 179.9 143.73 203.58 143.41" style="fill: #ffd939"/>
  <polygon points="195.17 130.67 263.93 154.41 253.4 175.13 219.41 150.52 203.58 143.41 195.17 130.67" style="fill: #fffa3b"/>
  <polygon points="189.31 121.79 212.91 130.67 259.1 126.23 260.59 153.26 195.17 130.67 189.31 121.79" style="fill: #d0d82b"/>
</svg>

Few notes:

  • As of now, the SVGs need to consist of polygons. I’m planning to implement the ability for shapeshifter.js to take other SVGs that have paths, rects etc. But as of now, it only works with polygons.

  • Make sure to set the display on the SVGs to none. We’re not going to display them directly in the DOM. We’re just taking the SVG and polygon attributes and displaying them on a JavaScript canvas.

  • Notice how every polygon has a fill value. If it doesn’t shapeshifter.js will default to black.

  • If you’d like the polygons to have different opacity, add it as an inline css value just like fill. Otherwise, the polygons will have full opacity by default.

2- OK, next thing we need is a parent element for our canvas.

<div id="container"></div>

3- Our canvas size is gonna be relative to the container, so make sure to give the container width and height (and it can be responsive or static) In this case I’ll just make it fill the viewport.

#container {
    position: absolute;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
}

INSTALLATION

Just download the shapeshifter.js file and link it in your html.

<script src="shapeshifter.js"></script>

USAGE

OK, now we’re ready to jump in to all the fun JavaScript stuff. First we’ll add a reference for our svg shapes. Make sure to querySelectorAll the polygons. Not the SVG itself.

var retrieverPolygons = document.querySelector('#retriever').querySelectorAll('polygon');
var passerinePolygons = document.querySelector('#passerine').querySelectorAll('polygon');

We’ll add a reference to the container div also

var container = document.querySelector('#container');

Now let’s initialzie Shapeshifter.

var shapeshifter = new Shapeshifter(container, x, y, polygons, options);

container | domElement: The container element we created earlier.

x | number: Initial x value, I recommend setting it as 0 and changing the container’s position instead.

y | number: Initial y value, I also recommend setting it as 0 and changing the container’s position instead.

polygons | domElements: The initial SVG for Shapeshifter before any transformation happen. Pass the array of polygons from earlier (retrieverPolygons, passerinePolygons);

options | object: pass any options you wanna change. Here are all the options you can pass.

Here’s how we’ll initialize it in this example:

var options = {
  /*transformSpeed: {x:0.05, y:0.05}, //transformation speed 
  hideSpeed: {x:0.05, y:0.05}, //the speed extra polygons get hidden
  opacitySpeed: 0.05, //the speed of opacity changes
  colorSpeed: 0.05, //the speed of color changes*/
  defaultSpeed: 0.03, //any speed property not defined will resort to defaultSpeed. If defaultSpeed is not set, it defaults to 0.07
  scale: 0.3, //1 makes the initial SVG 100% of the container's width
  center: true, //center the shapes inside the container. Otherwise, they'll stick to the top left corner
  strokeOnly: false //only show the outlines
}

var shapeshifter = new Shapeshifter(container, 0, 0, retrieverPolygons, options);

OPTIONS OBJECT

These are the paramaters you can pass as options:

transformSpeed | {x: number; y: number}: Transformation speed. Default value is {x: 0.07, y: 0.07}

hideSpeed | {x: number; y: number}: The speed extra polygons get hidden. Default value is {x: 0.07, y: 0.07}

opacitySpeed | number: The speed polygons will change opacity. Default value is 0.07

colorSpeed | number: The speed polygons will change color. Default value is 0.07

defaultSpeed | number: The default speed all the other unset speed properties take. Default value is 0.07

scale | number: The size of the initial SVG. 1 == 100% of the container div width. The SVGs your transform to will just be sized relatively to the first. So make sure they’re all similar size when you export them.

center | boolean: Center the SVG inside the container. Otherwise they stay on the top left of the container.

strokeOnly | boolean: Only show the outlines.

RUNNING THE LOOP

Now before Shapeshifter.js animations work, we need to run its loop function every frame. So we’ll create a recursive loop function to update Shapeshifter.

function loop(){
  shapeshifter.loop();
  window.requestAnimationFrame(loop);
}
loop();

TRANSFORMATION

Now the part we’re doing all of this for. If you wanna transform the svg. Run this method.

shapeshifter.transform(newPolygons);

In this example newPolygons being passerinePolygons.

And here’s a quick example function to switch back and forth between passerinePolygons and retrieverPolygons on click. I’ll just use a boolean since we’re transforming between two SVGs only in this example, but we can can transform between any number of SVGs.

(function(){
    var animationState = true;

    window.addEventListener('click', function(){
      if(animationState){
        shapeshifter.transform(passerinePolygons);
      } else {
        shapeshifter.transform(retrieverPolygons);
      }
      animationState = !animationState;
    });
})();

Download Details:

Author: mhazaa

Demo: http://shapeshifterjs.com/

Source Code: https://github.com/mhazaa/shapeshifter.js

#javascript

What is GEEK

Buddha Community

SVG Morphing Animation In JavaScript – Shapeshifter.js

NBB: Ad-hoc CLJS Scripting on Node.js

Nbb

Not babashka. Node.js babashka!?

Ad-hoc CLJS scripting on Node.js.

Status

Experimental. Please report issues here.

Goals and features

Nbb's main goal is to make it easy to get started with ad hoc CLJS scripting on Node.js.

Additional goals and features are:

  • Fast startup without relying on a custom version of Node.js.
  • Small artifact (current size is around 1.2MB).
  • First class macros.
  • Support building small TUI apps using Reagent.
  • Complement babashka with libraries from the Node.js ecosystem.

Requirements

Nbb requires Node.js v12 or newer.

How does this tool work?

CLJS code is evaluated through SCI, the same interpreter that powers babashka. Because SCI works with advanced compilation, the bundle size, especially when combined with other dependencies, is smaller than what you get with self-hosted CLJS. That makes startup faster. The trade-off is that execution is less performant and that only a subset of CLJS is available (e.g. no deftype, yet).

Usage

Install nbb from NPM:

$ npm install nbb -g

Omit -g for a local install.

Try out an expression:

$ nbb -e '(+ 1 2 3)'
6

And then install some other NPM libraries to use in the script. E.g.:

$ npm install csv-parse shelljs zx

Create a script which uses the NPM libraries:

(ns script
  (:require ["csv-parse/lib/sync$default" :as csv-parse]
            ["fs" :as fs]
            ["path" :as path]
            ["shelljs$default" :as sh]
            ["term-size$default" :as term-size]
            ["zx$default" :as zx]
            ["zx$fs" :as zxfs]
            [nbb.core :refer [*file*]]))

(prn (path/resolve "."))

(prn (term-size))

(println (count (str (fs/readFileSync *file*))))

(prn (sh/ls "."))

(prn (csv-parse "foo,bar"))

(prn (zxfs/existsSync *file*))

(zx/$ #js ["ls"])

Call the script:

$ nbb script.cljs
"/private/tmp/test-script"
#js {:columns 216, :rows 47}
510
#js ["node_modules" "package-lock.json" "package.json" "script.cljs"]
#js [#js ["foo" "bar"]]
true
$ ls
node_modules
package-lock.json
package.json
script.cljs

Macros

Nbb has first class support for macros: you can define them right inside your .cljs file, like you are used to from JVM Clojure. Consider the plet macro to make working with promises more palatable:

(defmacro plet
  [bindings & body]
  (let [binding-pairs (reverse (partition 2 bindings))
        body (cons 'do body)]
    (reduce (fn [body [sym expr]]
              (let [expr (list '.resolve 'js/Promise expr)]
                (list '.then expr (list 'clojure.core/fn (vector sym)
                                        body))))
            body
            binding-pairs)))

Using this macro we can look async code more like sync code. Consider this puppeteer example:

(-> (.launch puppeteer)
      (.then (fn [browser]
               (-> (.newPage browser)
                   (.then (fn [page]
                            (-> (.goto page "https://clojure.org")
                                (.then #(.screenshot page #js{:path "screenshot.png"}))
                                (.catch #(js/console.log %))
                                (.then #(.close browser)))))))))

Using plet this becomes:

(plet [browser (.launch puppeteer)
       page (.newPage browser)
       _ (.goto page "https://clojure.org")
       _ (-> (.screenshot page #js{:path "screenshot.png"})
             (.catch #(js/console.log %)))]
      (.close browser))

See the puppeteer example for the full code.

Since v0.0.36, nbb includes promesa which is a library to deal with promises. The above plet macro is similar to promesa.core/let.

Startup time

$ time nbb -e '(+ 1 2 3)'
6
nbb -e '(+ 1 2 3)'   0.17s  user 0.02s system 109% cpu 0.168 total

The baseline startup time for a script is about 170ms seconds on my laptop. When invoked via npx this adds another 300ms or so, so for faster startup, either use a globally installed nbb or use $(npm bin)/nbb script.cljs to bypass npx.

Dependencies

NPM dependencies

Nbb does not depend on any NPM dependencies. All NPM libraries loaded by a script are resolved relative to that script. When using the Reagent module, React is resolved in the same way as any other NPM library.

Classpath

To load .cljs files from local paths or dependencies, you can use the --classpath argument. The current dir is added to the classpath automatically. So if there is a file foo/bar.cljs relative to your current dir, then you can load it via (:require [foo.bar :as fb]). Note that nbb uses the same naming conventions for namespaces and directories as other Clojure tools: foo-bar in the namespace name becomes foo_bar in the directory name.

To load dependencies from the Clojure ecosystem, you can use the Clojure CLI or babashka to download them and produce a classpath:

$ classpath="$(clojure -A:nbb -Spath -Sdeps '{:aliases {:nbb {:replace-deps {com.github.seancorfield/honeysql {:git/tag "v2.0.0-rc5" :git/sha "01c3a55"}}}}}')"

and then feed it to the --classpath argument:

$ nbb --classpath "$classpath" -e "(require '[honey.sql :as sql]) (sql/format {:select :foo :from :bar :where [:= :baz 2]})"
["SELECT foo FROM bar WHERE baz = ?" 2]

Currently nbb only reads from directories, not jar files, so you are encouraged to use git libs. Support for .jar files will be added later.

Current file

The name of the file that is currently being executed is available via nbb.core/*file* or on the metadata of vars:

(ns foo
  (:require [nbb.core :refer [*file*]]))

(prn *file*) ;; "/private/tmp/foo.cljs"

(defn f [])
(prn (:file (meta #'f))) ;; "/private/tmp/foo.cljs"

Reagent

Nbb includes reagent.core which will be lazily loaded when required. You can use this together with ink to create a TUI application:

$ npm install ink

ink-demo.cljs:

(ns ink-demo
  (:require ["ink" :refer [render Text]]
            [reagent.core :as r]))

(defonce state (r/atom 0))

(doseq [n (range 1 11)]
  (js/setTimeout #(swap! state inc) (* n 500)))

(defn hello []
  [:> Text {:color "green"} "Hello, world! " @state])

(render (r/as-element [hello]))

Promesa

Working with callbacks and promises can become tedious. Since nbb v0.0.36 the promesa.core namespace is included with the let and do! macros. An example:

(ns prom
  (:require [promesa.core :as p]))

(defn sleep [ms]
  (js/Promise.
   (fn [resolve _]
     (js/setTimeout resolve ms))))

(defn do-stuff
  []
  (p/do!
   (println "Doing stuff which takes a while")
   (sleep 1000)
   1))

(p/let [a (do-stuff)
        b (inc a)
        c (do-stuff)
        d (+ b c)]
  (prn d))
$ nbb prom.cljs
Doing stuff which takes a while
Doing stuff which takes a while
3

Also see API docs.

Js-interop

Since nbb v0.0.75 applied-science/js-interop is available:

(ns example
  (:require [applied-science.js-interop :as j]))

(def o (j/lit {:a 1 :b 2 :c {:d 1}}))

(prn (j/select-keys o [:a :b])) ;; #js {:a 1, :b 2}
(prn (j/get-in o [:c :d])) ;; 1

Most of this library is supported in nbb, except the following:

  • destructuring using :syms
  • property access using .-x notation. In nbb, you must use keywords.

See the example of what is currently supported.

Examples

See the examples directory for small examples.

Also check out these projects built with nbb:

API

See API documentation.

Migrating to shadow-cljs

See this gist on how to convert an nbb script or project to shadow-cljs.

Build

Prequisites:

  • babashka >= 0.4.0
  • Clojure CLI >= 1.10.3.933
  • Node.js 16.5.0 (lower version may work, but this is the one I used to build)

To build:

  • Clone and cd into this repo
  • bb release

Run bb tasks for more project-related tasks.

Download Details:
Author: borkdude
Download Link: Download The Source Code
Official Website: https://github.com/borkdude/nbb 
License: EPL-1.0

#node #javascript

Hayden Slater

1582081434

Anime.js Tutorial - JavaScript Animation Engine in 10 Minutes

Step by step tutorial on how to use create animation with anime.js. Walkthrough of key features like text/DOM animation, keyframes, stagger, timeline, grid, axis and more.
Anime.js: https://animejs.com/

#Anime.js #js #javascript

GSAP (Green Sock Animation Platform) Web SVG Animation | JavaScript Animation Library

Today we are going to look at how to design and create a fully working website animation using the GSAP (Green Sock Animation Platform). SVG animation is actually not so complicated and can be a lot of fun. With the help of GSAP we can do powerful web animations with ease.

Article + Files:
https://raddy.co.uk/blog/adobe-xd-website-design-to-gsap-3-0-tutorial/

Part 1 - Designing the website layout: https://www.youtube.com/watch?v=ZmGfH6CJNYY

Subscribe to my newsletter: www.raddy.co.uk/newsletter

SOCIAL: @RaddyTheBrand
Instagram: www.instagram.com/RaddyTheBrand
Twitter: www.twitter.com/RaddyTheBrand
Website: www.raddy.co.uk
Blog: www.raddy.co.uk/blog
GitHub: https://github.com/RaddyTheBrand

#svg animation #javascript #library #gsap #green sock animation platform #tutorial

Ajay Kapoor

1626321063

JS Development Company India | JavaScript Development Services

PixelCrayons: Our JavaScript web development service offers you a feature-packed & dynamic web application that effectively caters to your business challenges and provide you the best RoI. Our JavaScript web development company works on all major frameworks & libraries like Angular, React, Nodejs, Vue.js, to name a few.

With 15+ years of domain expertise, we have successfully delivered 13800+ projects and have successfully garnered 6800+ happy customers with 97%+ client retention rate.

Looking for professional JavaScript web app development services? We provide custom JavaScript development services applying latest version frameworks and libraries to propel businesses to the next level. Our well-defined and manageable JS development processes are balanced between cost, time and quality along with clear communication.

Our JavaScript development companies offers you strict NDA, 100% money back guarantee and agile/DevOps approach.

#javascript development company #javascript development services #javascript web development #javascript development #javascript web development services #javascript web development company

Grokking Call(), Apply() and Bind() Methods in JavaScript

These functions are very important for every JavaScript Developer and are used in almost every JavaScript Library or Framework. Check out the code snippet below.

Taken from the very popular library Lodash

/**
	* Creates a function that invokes `func` with arguments reversed.
	*
	* @since 4.0.0
	* @category Function
	* @param {Function} func The function to flip arguments for.
	* @returns {Function} Returns the new flipped function.
	* @see reverse
	* @example
	*
	* const flipped = flip((...args) => args)
	*
	* flipped('a', 'b', 'c', 'd')
	* // => ['d', 'c', 'b', 'a']
	*/
	function flip(func) {
	  if (typeof func !== 'function') {
	    throw new TypeError('Expected a function')
	  }
	  return function(...args) {
	    return func.apply(this, args.reverse())
	  }
	}

	export default flip

Look at the statement on line 21, return func.apply(this, args.reverse())

In this article, we will have a look at the call()apply() and bind() methods of JavaScript. Basically these 3 methods are used to control the invocation of the function. The call() and apply() were introduced in ECMAScript 3 while bind() was added as a part of ECMAScript 5.

Let us start with an example to understand these.

Suppose you are a student of X university and your professor has asked you to create a math library, for an assignment, which calculates the area of a circle.

const calcArea = {
	  pi: 3.14,
	  area: function(r) {
	    return this.pi * r * r;
	  }
	}

calcArea.area(4); // prints 50.24


You test this and verify its result, it is working fine and you upload the library to portal way before the deadline ends. Then you ask your classmates to test and verify as well, you come to know that that your result and their results mismatches the decimals precision. You check the assignment guidelines, Oh no! The professor asked you to use a constant **pi** with 5 decimals precision. But you used **3.14** and not **3.14159** as the value of pi. Now you cannot re-upload the library as the deadline date was already over. In this situation, **call()** function will save you.

#js #javascript-development #javascript #javascript-interview #javascript-tips