# 【100sites #009】Flame, cool little animations with P5js

- Canonical: https://easonchang.com/posts/100sites-009-flame
- Date: 2016-03-23T07:05:00.000Z
- Language: en
- Translation: AI-assisted, from the zh-TW original

> One-sentence summary: A flame-like interactive effect made with P5.js

[Play the live demo](http://kamigami55.github.io/100sites/009_Flame/)

[View the source code on Github](https://github.com/eason-dev/100sites/tree/gh-pages/009_Flame)

![Screenshot 2016-03-23 4.08.53 AM.png](https://i.imgur.com/rqkEbP4.jpg)

I first learned about [P5.js](http://p5js.org) from [Chiun Hau You](https://www.behance.net/chiunhauyou)'s talk at this year's SITCON conference. Recently his P5.js visual identity project, [Hello World - Programmable Visual Identity](https://www.behance.net/gallery/34490551/Hello-World-Programmable-Visual-Identity), made it into [CodePen](http://codepen.io)'s Picked Pens and got a great response. That made me want to explore more of what P5.js can do, so today I made this little flame interaction as practice.

There aren't many details to explain today. Just move your mouse and enjoy the little flames!

Left-click to switch styles — there are 4 in total.

Here's another style:
![Screenshot 2016-03-23 4.09.52 AM.png](https://i.imgur.com/2hriTFz.jpg)

Source code:

```html index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset-"UTF-8">
    <title>Flame</title>
    <link rel="stylesheet" type="text/css" href="style.css" />
    <script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.23/p5.js"></script>
    <script src="flame.js"></script>
  </head>

  <body></body>
</html>
```

```css style.css
* {
  margin: 0;
  padding: 0;
}

body {
  overflow: hidden;
}
```

```javascript flame.js
var rows = 0, // how many shapes there are vertically
  cols = 0, // how many shapes there are horizontally
  diameter = [], // diameter of every single shape
  displayMode = 0, // four display mode: 0: red rect, 1: red ellipse, 2: blue rect, 3: blue ellipse
  MARGIN = 30, // distance between two shapes
  MAX_SIZE = 100, // max shape size when mouse approach
  SENSE_RANGE = 200; // what distance shapes will react

function setup() {
  createCanvas(windowWidth, windowHeight);
  strokeWeight(0);
  ellipseMode(CENTER);
  rectMode(CENTER);
  frameRate(30);

  rows = windowHeight / MARGIN;
  cols = windowWidth / MARGIN;

  // initialize diameter 2-dimensional array
  for (var y = 0; y < rows; ++y) {
    diameter.push([]);
    for (var x = 0; x < cols; ++x) {
      diameter[y].push(0);
    }
  }
}

function draw() {
  background(20);
  for (var y = 0; y < rows; y += 1) {
    for (var x = 0; x < cols; x += 1) {
      var thisDiameter = diameter[y][x];

      // decrease diameter by time until diameter is 0
      if (thisDiameter < 2) {
        diameter[y][x] = 0;
      } else {
        // thisDiameter >= 2
        diameter[y][x] -= 2;
        thisDiameter = diameter[y][x];

        // And we can now display it
        // Determine which color should we use
        if (displayMode <= 1) {
          // 0, 1
          fill(255, thisDiameter * 2.5, 0); // red color mode
        } else {
          // 2, 3
          fill(0, thisDiameter * 2.5, 255 - thisDiameter * 1.5); // blue color mode
        }
        // Determine which shape should we use
        if (displayMode == 0 || displayMode == 2) {
          // 0, 2
          rect(x * MARGIN, y * MARGIN, thisDiameter, thisDiameter); // rect mode
        } else {
          // 1, 3
          ellipse(x * MARGIN, y * MARGIN, thisDiameter, thisDiameter); // ellipse mode
        }
      } // .if-else
    } // .for
  } // .for
}

// when mouse moved, adjust diameters of every shapes
function mouseMoved() {
  for (var y = 0; y < rows; y += 1) {
    for (var x = 0; x < cols; x += 1) {
      // calculus the distance between this shape and user mouse
      var dist = Math.sqrt(
        (x * MARGIN - mouseX) * (x * MARGIN - mouseX) +
          (y * MARGIN - mouseY) * (y * MARGIN - mouseY)
      );
      if (dist <= SENSE_RANGE) {
        // calculus the diameter based on the distance
        var theDiameter = ((SENSE_RANGE - dist) * MAX_SIZE) / SENSE_RANGE;
        // if current diameter is smaller than the calc diameter
        if (diameter[y][x] < theDiameter) {
          diameter[y][x] = theDiameter; // increase the current diameter to it should be
        }
      }
    }
  }
}

// switch display mode
function mousePressed() {
  ++displayMode;
  if (displayMode > 3) {
    displayMode = 0;
  }
}
```
