PK Creative Spring Festival, I am participating in the “Spring Festival Creative Submission Contest”, please see: Spring Festival Creative Submission Contest”

preface

In order to make the atmosphere of the New Year stronger, fireworks and BGM are indispensable. In this article, we will use p5.js to realize a fireworks bloom according to music to add color to the New Year

Results the preview

What is the p5. Js

P5. js is a JavaScript creative programming library focused on making programming easier to use and more accessible to artists, designers, educators, beginners, and anyone else! P5.js is free and open source because we believe that everyone should be able to freely use software and the tools for learning software. P5.js uses the metaphor of drawing and has a complete drawing function. In addition, you are not limited to your drawing canvas. You can treat your entire browser page as your drawing, which includes HTML5 objects such as text, input fields, video, camera, and audio.

In short, p5.js can use Canvas for many cool browser effects and drawing in the browser.

implementation

We’ll start by referring to p5’s CDN, and then to its extension package p5.Sound, because we want to take advantage of the audio capabilities

<script src="https://cdn.bootcdn.net/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
Copy the code

Next we implement the fireworks part first, and then we combine the music with the fireworks

Create a canvas

P5 is written differently from the general situation. The setup function can be initialized directly in JS, while the draw function is used to draw the canvas:

function setup() {
  createCanvas(window.innerWidth, window.innerHeight)
}
function draw() {
  background(0.0.20)}Copy the code

If you want to define setup functions in Vue, you need to declare them in a different way:

const s = (sketch) = > {
  sketch.setup = () = > {
    createCanvas(window.innerWidth, window.innerHeight)
  }
  sketch.draw = () = > {
    background(0.0.20)}}Copy the code

In this article we write code directly in HTML, so we use the first approach.

Create the fireworks

Here our simulated firework consists of a central point and random points surrounding it. Specific code actions and meanings are noted in comments

// Currently receive a blast radius parameter.
function Fireworks(radius) {
  var num = 64 // How many points does a firework have

  // Random center position, width and height are the width and height of the canvas.
  var cp = new p5.Vector(
    random(0, width),
    random(height / 2, height / 5),
    random(-100.100))// Define the speed and acceleration of firework launch. The current height is written dead, and will be dynamically modified according to audio related data later.
  var velocity = new p5.Vector(0, -15.0)
  var accel = new p5.Vector(0.0.4.0)

  var img

  var fp = []

  var cosTheta
  var sinTheta
  var phi
  var colorChange = random(0.5)

  // Initializes the firework point
  for (var i = 0; i < num; i++) {
    cosTheta = random(0.1) * 2 - 1
    sinTheta = sqrt(1 - cosTheta * cosTheta)
    phi = random(0.1) * 2 * PI
    fp[i] = new p5.Vector(
      radius * sinTheta * cos(phi),
      radius * sinTheta * sin(phi),
      radius * cosTheta
    ) // Calculate the position of each point in a firework
    fp[i] = p5.Vector.mult(fp[i], 1.01)}// Randomly color the fireworks
  var side = 64
  var center = side / 2.0

  img = createImage(side, side)
  img.loadPixels()
  const r = random(0.5.0.8)
  const g = random(0.5.0.8)
  const b = random(0.5.0.8)
  for (var y = 0; y < side; y++) {
    for (var x = 0; x < side; x++) {
      var distance = (sq(center - x) + sq(center - y)) / 10.0
      var r = int((255 * r) / distance)
      var g = int((255 * g) / distance)
      var b = int((255 * b) / distance)
      // img.pixels[x + y * side] = color(r, g, b);
      img.set(y, x, color(r, g, b))
    }
  }

  img.updatePixels()

  this.display = function () {
    for (var i = 0; i < num; i++) {
      push()
      translate(cp.x, cp.y, cp.z)
      translate(fp[i].x, fp[i].y, fp[i].z)
      blendMode(ADD) // Each dot (source mask effect)
      image(img, 0.0)
      pop()

      fp[i] = p5.Vector.mult(fp[i], 1.015) // Update the dot diffusion position}}// Simulate the acceleration of gravity
  this.update = function () {
    radius = dist(
      0.0.0,
      fp[0].x,
      fp[0].y,
      fp[0].z
    )
    centerPosition.add(velocity)
    velocity.add(accel)
  }

  // Determine if destruction is required
  this.needRemove = function () {
    if (centerPosition.y - radius > height) {
      return true
    } else {
      return false}}}Copy the code

Now that the basic fireworks class is defined, we can bind a keyboard event to the canvas and modify the logic in the draw function to see what happens.

function keyPressed() {
  // Add a firework to the keyboard event
  fireworks.push(new Fireworks(20)) //80 is the initial radius of the fireworks
}

function draw() {
  background(0.0.20)
  for (var i = 0; i < fireworks.length; i++) {
    fireworks[i].display()
    fireworks[i].update()
    if (fireworks[i].needRemove()) {
      fireworks.splice(i, 1)}}}Copy the code

The relevant API

The apis and classes used above are listed here for easy viewing

API describe
createCanvas Create a canvas
background Set the background color
p5.Vector Create a new P5 vector with magnitude and direction
random Returns a random floating point number between the ranges given as arguments
sqrt Gets the square root of any input number
createImage Create a picture
translate Specifies the number of objects to place in the display window. The x parameter is used to specify left/right panning and the Y parameter is used to specify up/down panning
blendMode Blend two pixels according to the given blend mode
dist The measurement calculates the distance between two points in 2D or 3D

Get audio parameters

First we need to add an Audio tag to hold our music

<audio src="./1.mp3" autoplay controls>Your browser does not support the audio tag.</audio>
Copy the code

Then modify our setup function to get access to our audio resources

var fireworks = []
var highMap = [2.5.10.15]
const ORI_NUM = 32
function setup() {
  //processing initializes Settings
  createCanvas(window.innerWidth, window.innerHeight)
  frameRate(60) // Number of renders per second
  imageMode(CENTER)
  audioContext_ = getAudioContext()
  // Get sound dom
  let el = document.querySelector('audio')
  // Create a Web Audio API source node based on the sound DOM and connect the main output
  const source = audioContext_.createMediaElementSource(el)
  source.connect(p5.soundOut)
  //0.8 is the degree of variation. The smaller the pattern, the more shaky it is
  fft = new p5.FFT(0.8, ORI_NUM)
  fft.setInput(source)
}
Copy the code

Here we capture the frequency spectrum of the audio resources that will be used in the future to control the size and height of our fireworks. Of course, p5.sound can also capture the volume of the audio and so on for even cooler visualizations.

Next we adapt the Draw drawing function to parse the spectrum of local audio and use it to do things

function draw() {
  // Execute the loop to achieve the rendering effect

  audioContext_.resume()
  background(0.0.20)
  let spectrum = fft.analyze()

  spectrum.forEach((item, j) = > {
    if(item ! = =0 && j % 2) {
      let a = highMap[0]
      if (item >= 64 && item < 128) {
        a = highMap[1]}else if (item >= 128 && item < 192) {
        a = highMap[2]}else {
        a = highMap[3]}const fire = new Fireworks(item, a)
      fireworks.push(fire)
      if (fireworks.length > 64) {
        fireworks.shift()
      }
    }
  })

  for (var i = 0; i < fireworks.length; i++) {
    fireworks[i].display()
    fireworks[i].update()
    if (fireworks[i].needRemove()) {
      fireworks.splice(i, 1)}}}Copy the code

Note that audioContext_.resume() must be added because Google Chrome does not automatically play audio by default.

Spectrum is an array of spectrum values obtained through analysis. ORI_NUM is the number of spectrum, and at least 32 are required. We could set off more fireworks in theory, but since my computer performance is not good, so I just take 16 fireworks.

We can see in the code, Fireworks class we passed two parameters: spectrum value and we define the height value, now you can modify the Fireworks class, to achieve according to the audio to control the Fireworks explosion radius and launch height.

function Fireworks(radius, h) {
  var num = 64 // How many points are there in a firework

  var cp = new p5.Vector(
    random(0, width),
    random(height / 2, height / 5),
    random(-100.100))// The central position of the fireworks
  var velocity = new p5.Vector(0, -h, 0)
  var accel = new p5.Vector(0.0.4.0)

  ……
}
Copy the code

For a more realistic effect, we optimized the random color of the firework to make it brighter

if (colorChange >= 3.5) {
  img = makeColor(0.9, random(0.2.0.5), random(0.2.0.5))}else if (colorChange > 3.2) {
  img = makeColor(random(0.2.0.5), 0.9, random(0.2.0.5))}else if (colorChange > 2) {
  img = makeColor(random(0.2.0.5), random(0.2.0.5), 0.9)}else {
  img = makeColor(random(0.5.0.8), random(0.5.0.8), random(0.5.0.8))}function makeColor(rr, gg, bb) {
  var side = 64
  var center = side / 2.0

  var img = createImage(side, side)
  img.loadPixels()
  for (var y = 0; y < side; y++) {
    for (var x = 0; x < side; x++) {
      var distance = (sq(center - x) + sq(center - y)) / 10.0
      var r = int((255 * rr) / distance)
      var g = int((255 * gg) / distance)
      var b = int((255 * bb) / distance)
      // img.pixels[x + y * side] = color(r, g, b);
      img.set(y, x, color(r, g, b))
    }
  }

  img.updatePixels()
  return img
}
Copy the code

The effect is as colorful as the beginning of the article.

The last

That’s where the musical fireworks come in, and p5.js is a library THAT I stumbled upon and found a way to make all kinds of powerful animations. Thought I was the first to use the p5, js to achieve the effect, and as I write this demo out the second day of the first day of the event, attended by a fireworks feast 🎇 of Beijing, I wish you a happy New Year 🎉, implementation approach is different, I think Beijing elder brother also more beautiful and true ~, heartache ha ha ha ha can’t do it the first do a… … The NTH is also good.