1

Ok so I have a list nav that navigates to a certain slide with carousel slide, the smoke.js loads up when the site is visited and starts automatically which is what I want, but when they click on any of the nav buttons other than the "Home" button, I need it to end the smoke animation, and if they click the home button to go back to the home slide, I need it to restart the smoke machine. How can I do that?

The codepen for smoke.js here codepen:

var smokemachine = function(context, color) {
  color = color || [24, 46.8, 48.2]
  var polyfillAnimFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  var lastframe;
  var currentparticles = []
  var pendingparticles = []

  var buffer = document.createElement('canvas'),
    bctx = buffer.getContext('2d')

  buffer.width = 20
  buffer.height = 20

  var opacities = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 5, 7, 4, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 17, 27, 41, 52, 56, 34, 23, 15, 11, 4, 9, 5, 1, 0, 0, 0, 0, 0, 0, 1, 45, 63, 57, 45, 78, 66, 52, 41, 34, 37, 23, 20, 0, 1, 0, 0, 0, 0, 1, 43, 62, 66, 64, 67, 115, 112, 114, 56, 58, 47, 33, 18, 12, 10, 0, 0, 0, 0, 39, 50, 63, 76, 87, 107, 105, 112, 128, 104, 69, 64, 29, 18, 21, 15, 0, 0, 0, 7, 42, 52, 85, 91, 103, 126, 153, 128, 124, 82, 57, 52, 52, 24, 1, 0, 0, 0, 2, 17, 41, 67, 84, 100, 122, 136, 159, 127, 78, 69, 60, 50, 47, 25, 7, 1, 0, 0, 0, 34, 33, 66, 82, 113, 138, 149, 168, 175, 82, 142, 133, 70, 62, 41, 25, 6, 0, 0, 0, 18, 39, 55, 113, 111, 137, 141, 139, 141, 128, 102, 130, 90, 96, 65, 37, 0, 0, 0, 2, 15, 27, 71, 104, 129, 129, 158, 140, 154, 146, 150, 131, 92, 100, 67, 26, 3, 0, 0, 0, 0, 46, 73, 104, 124, 145, 135, 122, 107, 120, 122, 101, 98, 96, 35, 38, 7, 2, 0, 0, 0, 50, 58, 91, 124, 127, 139, 118, 121, 177, 156, 88, 90, 88, 28, 43, 3, 0, 0, 0, 0, 30, 62, 68, 91, 83, 117, 89, 139, 139, 99, 105, 77, 32, 1, 1, 0, 0, 0, 0, 0, 16, 21, 8, 45, 101, 125, 118, 87, 110, 86, 64, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 28, 79, 79, 117, 122, 88, 84, 54, 46, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 6, 55, 61, 68, 71, 30, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 23, 25, 20, 12, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 12, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0]

  var data = bctx.createImageData(20, 20)
  var d = data.data

  for (var i = 0; i < d.length; i += 4) {
    d[i] = color[0]
    d[i + 1] = color[1]
    d[i + 2] = color[2]
    d[i + 3] = opacities[i / 4]
  }

  bctx.putImageData(data, 0, 0)

  var imagewidth = 20 * 5
  var imageheight = 20 * 5

  function particle(x, y, l) {
    this.x = x
    this.y = y
    this.age = 0
    this.vx = (Math.random() * 8 - 4) / 100
    this.startvy = -(Math.random() * 30 + 10) / 100
    this.vy = this.startvy
    this.scale = Math.random() * .5
    this.lifetime = Math.random() * l + l / 2
    this.finalscale = 5 + this.scale + Math.random()

    this.update = function(deltatime) {
      this.x += this.vx * deltatime
      this.y += this.vy * deltatime
      var frac = Math.pow((this.age) / this.lifetime, .5)
      this.vy = (1 - frac) * this.startvy
      this.age += deltatime
      this.scale = frac * this.finalscale
    }

    this.draw = function() {
      context.globalAlpha = (1 - Math.abs(1 - 2 * (this.age) / this.lifetime)) / 8
      var off = this.scale * imagewidth / 2
      var xmin = this.x - off
      var xmax = xmin + this.scale * imageheight
      var ymin = this.y - off
      var ymax = ymin + this.scale * imageheight
      context.drawImage(buffer, xmin, ymin, xmax - xmin, ymax - ymin)
    }
  }


  function addparticles(x, y, n, lifetime) {
    lifetime = lifetime || 4000
    n = n || 10
    if (n < 1) return Math.random() <= n && pendingparticles.push(new particle(x, y, lifetime));
    for (var i = 0; i < n; i++) {
      pendingparticles.push(new particle(x, y, lifetime))
    };
  }

  function updateanddrawparticles(deltatime) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    deltatime = deltatime || 16
    var newparticles = []
    currentparticles = currentparticles.concat(pendingparticles)
    pendingparticles = []

    currentparticles.forEach(function(p) {
      p.update(deltatime)
      if (p.age < p.lifetime) {
        p.draw()
        newparticles.push(p)
      }
    })
    currentparticles = newparticles
  }

  function frame(time) {
    if (running) {
      var deltat = time - lastframe
      lastframe = time;

      updateanddrawparticles(deltat)

      polyfillAnimFrame(frame)
    }
  }

  var running = false

  function start() {
    running = true
    polyfillAnimFrame(function(time) {
      lastframe = time
      polyfillAnimFrame(frame)
    })
  }

  function stop() {
    running = false
  }

  return {
    start: start,
    stop: stop,
    step: updateanddrawparticles,
    addsmoke: addparticles
  }

}



var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
canvas.width = innerWidth
canvas.height = innerHeight

var party = smokemachine(ctx, [54, 16.8, 18.2])
party.start() // start animating

onmousemove = function(e) {
  var x = e.clientX
  var y = e.clientY
  var n = .5
  var t = Math.floor(Math.random() * 200) + 3800
  party.addsmoke(x, y, n, t)
}

setInterval(function() {
  party.addsmoke(innerWidth / 2, innerHeight, 1)
}, 100)
html,
body {
  position: absolute;
  margin: 0;
  width: 100%;
}

#hi {
  position: absolute;
  top: 40%;
  width: 100%;
  text-align: center;
}

#hi a {
  color: #fff;
  font-size: 80px;
  text-decoration: none;
  font-family: Lobster;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />

<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
  <div class="container">
    <ul>
      <li>
        <a href="#" class="current">
          <span data-text="Home" data-target="#carouselExampleIndicators" data-slide-to="0">Home</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="About" data-target="#carouselExampleIndicators" data- slide-to="1">About</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Chronic Menu" data-target="#carouselExampleIndicators" data-slide-to="2">Chronic Menu</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Strains" data-target="#carouselExampleIndicators" data- slide-to="3">Strains</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Gallery" data-target="#carouselExampleIndicators" data- slide-to="4">Gallery</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Reviews" data-target="#carouselExampleIndicators" data- slide-to="5">Reviews</span>
        </a>
      </li>
    </ul>
  </div>
</nav>

<canvas id="canvas" width="1777" height="898"></canvas>
Alvaro Montoro
  • 28,081
  • 7
  • 57
  • 86
Tony Lopez
  • 81
  • 7
  • You've given this question the javascript, jquery, and css tags, but I see none of these in the code you posted. – Bucket Dec 10 '18 at 21:09
  • apologies, I've added the code pen link to the description that has the java and css, also removed the jquery tag – Tony Lopez Dec 10 '18 at 21:18
  • @TonyLopez read how to create a [mcve]. It will make it easier for other users to see the problem and understand what you want to do. – Alvaro Montoro Dec 10 '18 at 22:17

1 Answers1

1

If you check the documentation of the smoke.js plugin on GitHub, you will see that there are two methods: start() (that starts the smoke) and stop() (that stops it). So what you want to do is call party.stop() when the navigation is clicked and it was not the home one, and party.start() if it was the home option.

Something like this (my code is at the top):

Notice: the .stop() method will stop the smoke but it want delete the existing smoke, it's more like a pause. It is unclear if you also want to remove the existing smoke, but if you need to do it, you can follow the instructions on this question to clean the canvas.

var navbaroptions = document.querySelectorAll("nav a");
for (var x = 0; x < navbaroptions.length; x++) {
  navbaroptions[x].addEventListener("click", function() {
    const canvas = document.querySelector("#canvas");
    if (this.id === "option-home") {
      party.start();
      canvas.removeAttribute("hidden");
    } else {
      party.stop();
      // hide the canvas
      canvas.setAttribute("hidden", true);
      const context = canvas.getContext('2d');
      context.clearRect(0, 0, canvas.width, canvas.height);
    }
  });
}

var smokemachine = function(context, color) {
  color = color || [24, 46.8, 48.2]
  var polyfillAnimFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  var lastframe;
  var currentparticles = []
  var pendingparticles = []

  var buffer = document.createElement('canvas'),
    bctx = buffer.getContext('2d')

  buffer.width = 20
  buffer.height = 20

  var opacities = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 5, 7, 4, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 17, 27, 41, 52, 56, 34, 23, 15, 11, 4, 9, 5, 1, 0, 0, 0, 0, 0, 0, 1, 45, 63, 57, 45, 78, 66, 52, 41, 34, 37, 23, 20, 0, 1, 0, 0, 0, 0, 1, 43, 62, 66, 64, 67, 115, 112, 114, 56, 58, 47, 33, 18, 12, 10, 0, 0, 0, 0, 39, 50, 63, 76, 87, 107, 105, 112, 128, 104, 69, 64, 29, 18, 21, 15, 0, 0, 0, 7, 42, 52, 85, 91, 103, 126, 153, 128, 124, 82, 57, 52, 52, 24, 1, 0, 0, 0, 2, 17, 41, 67, 84, 100, 122, 136, 159, 127, 78, 69, 60, 50, 47, 25, 7, 1, 0, 0, 0, 34, 33, 66, 82, 113, 138, 149, 168, 175, 82, 142, 133, 70, 62, 41, 25, 6, 0, 0, 0, 18, 39, 55, 113, 111, 137, 141, 139, 141, 128, 102, 130, 90, 96, 65, 37, 0, 0, 0, 2, 15, 27, 71, 104, 129, 129, 158, 140, 154, 146, 150, 131, 92, 100, 67, 26, 3, 0, 0, 0, 0, 46, 73, 104, 124, 145, 135, 122, 107, 120, 122, 101, 98, 96, 35, 38, 7, 2, 0, 0, 0, 50, 58, 91, 124, 127, 139, 118, 121, 177, 156, 88, 90, 88, 28, 43, 3, 0, 0, 0, 0, 30, 62, 68, 91, 83, 117, 89, 139, 139, 99, 105, 77, 32, 1, 1, 0, 0, 0, 0, 0, 16, 21, 8, 45, 101, 125, 118, 87, 110, 86, 64, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 28, 79, 79, 117, 122, 88, 84, 54, 46, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 6, 55, 61, 68, 71, 30, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 23, 25, 20, 12, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 12, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0]

  var data = bctx.createImageData(20, 20)
  var d = data.data

  for (var i = 0; i < d.length; i += 4) {
    d[i] = color[0]
    d[i + 1] = color[1]
    d[i + 2] = color[2]
    d[i + 3] = opacities[i / 4]
  }

  bctx.putImageData(data, 0, 0)

  var imagewidth = 20 * 5
  var imageheight = 20 * 5

  function particle(x, y, l) {
    this.x = x
    this.y = y
    this.age = 0
    this.vx = (Math.random() * 8 - 4) / 100
    this.startvy = -(Math.random() * 30 + 10) / 100
    this.vy = this.startvy
    this.scale = Math.random() * .5
    this.lifetime = Math.random() * l + l / 2
    this.finalscale = 5 + this.scale + Math.random()

    this.update = function(deltatime) {
      this.x += this.vx * deltatime
      this.y += this.vy * deltatime
      var frac = Math.pow((this.age) / this.lifetime, .5)
      this.vy = (1 - frac) * this.startvy
      this.age += deltatime
      this.scale = frac * this.finalscale
    }

    this.draw = function() {
      context.globalAlpha = (1 - Math.abs(1 - 2 * (this.age) / this.lifetime)) / 8
      var off = this.scale * imagewidth / 2
      var xmin = this.x - off
      var xmax = xmin + this.scale * imageheight
      var ymin = this.y - off
      var ymax = ymin + this.scale * imageheight
      context.drawImage(buffer, xmin, ymin, xmax - xmin, ymax - ymin)
    }
  }


  function addparticles(x, y, n, lifetime) {
    lifetime = lifetime || 4000
    n = n || 10
    if (n < 1) return Math.random() <= n && pendingparticles.push(new particle(x, y, lifetime));
    for (var i = 0; i < n; i++) {
      pendingparticles.push(new particle(x, y, lifetime))
    };
  }

  function updateanddrawparticles(deltatime) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    deltatime = deltatime || 16
    var newparticles = []
    currentparticles = currentparticles.concat(pendingparticles)
    pendingparticles = []

    currentparticles.forEach(function(p) {
      p.update(deltatime)
      if (p.age < p.lifetime) {
        p.draw()
        newparticles.push(p)
      }
    })
    currentparticles = newparticles
  }

  function frame(time) {
    if (running) {
      var deltat = time - lastframe
      lastframe = time;

      updateanddrawparticles(deltat)

      polyfillAnimFrame(frame)
    }
  }

  var running = false

  function start() {
    running = true
    polyfillAnimFrame(function(time) {
      lastframe = time
      polyfillAnimFrame(frame)
    })
  }

  function stop() {
    running = false
  }

  return {
    start: start,
    stop: stop,
    step: updateanddrawparticles,
    addsmoke: addparticles
  }

}


var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
canvas.width = innerWidth
canvas.height = innerHeight

var party = smokemachine(ctx, [54, 16.8, 18.2])
party.start() // start animating

onmousemove = function(e) {
  var x = e.clientX
  var y = e.clientY
  var n = .5
  var t = Math.floor(Math.random() * 200) + 3800
  party.addsmoke(x, y, n, t)
}

setInterval(function() {
  party.addsmoke(innerWidth / 2, innerHeight, 1)
}, 100)
html,
body {
  position: absolute;
  margin: 0;
  width: 100%;
}

#hi {
  position: absolute;
  top: 40%;
  width: 100%;
  text-align: center;
}

#hi a {
  color: #fff;
  font-size: 80px;
  text-decoration: none;
  font-family: Lobster;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />

<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
  <div class="container">
    <ul>
      <li>
        <a href="#" class="current" id="option-home">
          <span data-text="Home" data-target="#carouselExampleIndicators" data-slide-to="0">Home</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="About" data-target="#carouselExampleIndicators" data- slide-to="1">About</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Chronic Menu" data-target="#carouselExampleIndicators" data-slide-to="2">Chronic Menu</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Strains" data-target="#carouselExampleIndicators" data- slide-to="3">Strains</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Gallery" data-target="#carouselExampleIndicators" data- slide-to="4">Gallery</span>
        </a>
      </li>
      <li>
        <a href="#">
          <span data-text="Reviews" data-target="#carouselExampleIndicators" data- slide-to="5">Reviews</span>
        </a>
      </li>
    </ul>
  </div>
</nav>

<div style="margin-top:300px;position:absolute;"><a href="#">Link for testing</a></div>

<canvas id="canvas" width="1777" height="898" style="position:relative;"></canvas>
Alvaro Montoro
  • 28,081
  • 7
  • 57
  • 86
  • ah I see ok so yes it did stop the animation, but it stopped it in place, I didnt realize it would still be casting the smoke as visable, is there a way to make it so the canvas is closed when its stopped as well? then recast the canvas if Home is clicked? – Tony Lopez Dec 11 '18 at 05:37
  • @TonyLopez you can use `clearRect` as specified in the [linked answer](https://stackoverflow.com/questions/2142535/how-to-clear-the-canvas-for-redrawing). I edited the question to show it working. The only thing is that the smoke will continue from the state in which it was instead of starting from zero every time you go to the home. If that's what you want, you may need to remove the canvas and readd it to the dom. – Alvaro Montoro Dec 11 '18 at 05:53
  • Ok it works in the stopping way, but the canvas is still present and prevents me from clicking anything behind it – Tony Lopez Dec 11 '18 at 06:43
  • @TonyLopez There are many ways to remove the `canvas` so it is not visible/behind the main content: you could set up the `z-index` to -1, or set the `display` to `none`, or set the attribute `hidden`. I edited the solution with this last option (and added a link that is not clickable when the canvas is on the page, but it is when it is hidden). – Alvaro Montoro Dec 11 '18 at 06:56
  • Fantastic, I appreciate your help very much – Tony Lopez Dec 11 '18 at 09:10
  • @AlvaroMotoro Hey there, so I noticed that when I nav to a different slide it does stop and hide the smoke, but when the home slide is clicked after some time the smoke machine seems to be overloaded? As in it animates a whole lot of smoke all at once causing the browser to slow down and lag for a few seconds until the cloud life dies then it goes back to the normal way it animates on page load – Tony Lopez Dec 12 '18 at 21:00