Skip to content

Creating Animated Fade Away gifs from Image

This Mediajam showcases how to transform an image to gif as a fadeout using cloudinary API’s in combination with typescript Nextjs

The final project can be viewed on Codesandbox.

You can find the full source code on my Github repository.

First, we initialize an empty next js project.

Using the commands below. The command will prompt you to name your project.


npx create-next-app@latest --typescript

# or

yarn create next-app --typescript

Code language: CSS (css)

Once initialization is complete you can confirm that the initial setup is complete by running.


yarn dev

# OR

npm run dev

Code language: PHP (php)

After running the above command visit localhost port 3000

  1. html2canvas

  2. cloudinary

  3. gifshot

  4. styled-components


yarn add html2canvas

yarn add gifshot

yarn add cloudinary

yarn add styled-components

Additional setup for gifshot

Add the following line of code in the ./pages/api/decs.d.ts file

To enable the import and export of the module within the project


declare  module  "gifshot";

Code language: JavaScript (javascript)
  • [X] Setup demonstration image in the public folder.

  • [X] link the image to an image tag in the App class renderer

  • [X] Retrieve the html image tag and convert the element to the canvas using the html2canvas library

  • [X] Generate 6 other canvases (Due to storage constraints) while fading out the pixels in each canvas.

  • [X] Take the generated list of canvases to convert them into data urls array

  • [X] Combine the images to gif using gifshot library

  • [X] Upload the generated video/gif to cloudinary for storage.

  • [X] Display the generated fadeout/disintegration gif


<Main>

<div className="inner">

{loading  ?  (

<div>Processing ... </div>

)  :  (

<Image

id="world"

src={gif_image  ?  gif_image  :  `/goat.jpg`}

alt=""

/>

)}

<br />

{url  ?  <div>{url}</div>  :  ""}

{!loading  &&  <button onClick={this.snap.bind(this)}>Snap</button>}

</div>

</Main>

Code language: HTML, XML (xml)

// convert img tag to canvas

const  canvas  =  await  html2canvas(img  as  HTMLElement);

const  ctx  =  canvas.getContext("2d");

if  (!ctx)  return;

// Getting image data from the canvas for pixel manipulation

const  image_data  =  ctx.getImageData(0,  0,  canvas.width,  canvas.height);

if  (!image_data)  return;

const  pixel_arr  =  image_data.data;

Code language: JavaScript (javascript)

const  image_data_array  =  this.createBlankImageArray(image_data);

//put pixel info to imageDataArray (Weighted Distributed)

for  (let  i  =  0;  i  <  pixel_arr.length;  i++)  {

const  p  =  Math.floor((i  /  pixel_arr.length)  *  CANVAS_COUNT);

  

const  dist  =  Math.round(Math.random()  *  (CANVAS_COUNT  -  1));

  

const  a  =  image_data_array[dist];

a[i]  =  pixel_arr[i];

a[i  +  1]  =  pixel_arr[i  +  1];

a[i  +  2]  =  pixel_arr[i  +  2];

a[i  +  3]  =  pixel_arr[i  +  3];

}

Code language: JavaScript (javascript)

// fadeout image list generation and mapping

const  images  =  new  Array(CANVAS_COUNT)

.fill(0)

.map((_,  i)  =>

this.createCanvasFromImageData(

image_data_array[i],

canvas.width,

canvas.height

).toDataURL()

);

Code language: JavaScript (javascript)

gifshot.createGIF(

{

images,

gifWidth:  canvas.width,

gifHeight:  canvas.height,

numFrames:  CANVAS_COUNT

},

(obj:  any)  =>  {

if  (obj.error)  {

console.log(obj.error);

return;

}

console.log(obj.image);

this.uploadVideoCloudinary(obj.image);

this.setState({ gif_image:  obj.image, loading:  false  });

}

);

Code language: JavaScript (javascript)

This article will use cloudinary for media upload and storage. Use this link to access the cloudinary website and sign up or log in to receive your environment variables(Cloud name, API Key, and API Secret). The mentioned variables will be found in your dashboard which should look like the below:

Cloudinary Dashboard.

Create a file named .env at the root of your project. The file is where we store our environment variables. Paste the following code into the file


CLOUDINARY_NAME = ""

  

CLOUDINARY_API_KEY = ""

  

CLOUDINARY_API_SECRET= ""

Ensure to fill in the blanks with your respective environment variables then restart the project server for the project to update its env.

Head to the ./pages/api directory and create a file named upload.tsx. In the file, we will access the cloudinary API to upload our files and receive the cloudinary file URL.

Start by including the necessary imports


import type { NextApiRequest, NextApiResponse } from 'next'

var cloudinary = require('cloudinary').v2

Integrate your environment variables with the API backend like below:


cloudinary.config({

cloud_name:  process.env.CLOUDINARY_NAME,

api_key:  process.env.CLOUDINARY_API_KEY,

api_secret:  process.env.CLOUDINARY_API_SECRET,

});

Code language: CSS (css)

Since we are using typescript, we will include a type system to represent the type of value that will be used in our backend. In our case, the value will be a string.


type Data = {

name: string

}

We can then introduce a handler function that receives a post request and processes response feedback for our front end.


// https://rv7py.sse.codesandbox.io/

export  default  async  function  handler(

req:  NextApiRequest,

res:  NextApiResponse<Data>

)  {

if  (req.method  ===  "POST")  {

let  fileStr:  string  =  req.body.data;

let  uploadResponse:  any;

  

try  {

uploadResponse  =  await  cloudinary.uploader.upload_large(fileStr,  {

resource_type:  "auto",

chunk_size:  6000000,

timeout:  60000

});

console.log(uploadResponse);

}  catch  (err)  {

console.log(err);

}

res.status(200).json({ name:  ""  +  uploadResponse.secure_url  });

}

}

Code language: JavaScript (javascript)

The code above receives the request body and uploads it to cloudinary. It then captures the sent file’s cloudinary URL and sends it back to the front end as a response.

That’s it! we’ve completed our project backend.

Back to top

Featured Post