<canvas id="visible"></canvas>
 body {
      margin: 0px;
      padding: 0px;
    }
    html,
    body {
      height: 100%;
      font-family: "Segoe UI", Tahoma, Verdana, sans-serif;
      position: relative;
      background: #000918;
      min-height: 300px;
      min-width: 300px;
      font-weight: 200;
    }
    #visible {
      position: absolute;
      height: 100%;
      width: 100%;
    }
    #change {
      position: absolute;
      right: 10px;
      top: 10px;
      border: 2px solid rgba(255,255,255, 0.5);
      color: rgba(255,255,255, 0.5);
      background: transparent;
      cursor: pointer;
      padding: 6px 35px;
      border-radius: 4px;
      transition: all 0.4s;
    }
    #change:hover {
      background: rgba(255,255,255, 0.2);
      border: 2px solid rgba(255,255,255, 0.8);
      color: rgba(255,255,255, 0.8);
    }
    #hidden {
      display: none;
    }
const settings = {
  starsColor: {
    red: 240,
    green: 60,
    blue: 255
  },
  cloudsColor: {
    red: 20,
    green: 0,
    blue: 60
  },
  clusterSpreadinglet: 0.2, // [0, 1]
  sphereRadius: {
    min: 65,
    max: 90
  },
  cloudSize: {
    min: 140,
    max: 220
  },
  elementsSpreading: {
    min: 10,
    max: 50
  },
  startSpeed: {
    x: 0.4,
    y: 0.8
  }
};

const randomInt = (min, max) =>
  Math.round(min - 0.5 + Math.random() * (max - min + 1));

class CanvasBuffer {
  constructor(scaleParam, cutSize, amountStars, amountClouds) {
    this.scaleParam = scaleParam;
    this.cutSize = cutSize;
    this.fullSize = [cutSize[0] * 3, cutSize[1] * 3];
    this.amountStars = amountStars;
    this.amountClouds = amountClouds;
    this.crossNumb = 0;
    this.crossMap = [[0, 0]];
    this.camera = [cutSize[0], cutSize[1]];
    this.stars = this.createElementsArray();
    this.clouds = this.createElementsArray(false);
    const canvas = document.createElement("canvas");
    //document.getElementById('hidden').appendChild(canvas);
    canvas.width = this.fullSize[0];
    canvas.height = this.fullSize[1];
    this.canvas = canvas;
  }

  randomizeParams(isStars) {
    let other;
    const params = {
      clusterOX: randomInt(0, this.fullSize[0]),
      clusterOY: randomInt(0, this.fullSize[1])
    };
    if (isStars) {
      other = {
        color: `rgba(${randomInt(80, settings.starsColor.red)},${randomInt(
          20,
          settings.starsColor.green
        )},${randomInt(120, settings.starsColor.blue)},`,
        radius: randomInt(settings.sphereRadius.min, settings.sphereRadius.max)
      };
    } else {
      other = {
        color: `rgba(${randomInt(0, settings.cloudsColor.red)},${randomInt(
          0,
          settings.cloudsColor.green
        )},${randomInt(20, settings.cloudsColor.blue)},`,
        height:
          randomInt(settings.cloudSize.min, settings.cloudSize.max) *
          this.scaleParam,
        width:
          randomInt(settings.cloudSize.min, settings.cloudSize.max) *
          this.scaleParam,
        rotate: randomInt(0, 1)
      };
    }
    return {
      params,
      other
    };
  }
  createElementsArray(isStars = true) {
    let elementsArray = [];
    let extraElements = [];
    let newElement = {};
    let arrayLength = isStars ? this.amountStars : this.amountClouds;
    // first cluster
    let { params, other } = this.randomizeParams(isStars);

    for (let n = 0; n < arrayLength; n++) {
      if (Math.random() > settings.clusterSpreadinglet) {
        ({ params, other } = this.randomizeParams(isStars));
      }
      newElement = {
        x:
          randomInt(
            settings.elementsSpreading.min,
            settings.elementsSpreading.max
          ) + params.clusterOX,
        y:
          randomInt(
            settings.elementsSpreading.min,
            settings.elementsSpreading.max
          ) + params.clusterOY,
        ...other
      };
      elementsArray.push(newElement);
      //generate pattern
      if (newElement.x < newElement.radius || newElement.x < newElement.width) {
        extraElements.push({
          x: newElement.x + this.fullSize[0],
          y: newElement.y,
          ...other
        });
        if (
          newElement.y < newElement.radius ||
          newElement.y < newElement.height
        ) {
          extraElements.push({
            x: newElement.x + this.fullSize[0],
            y: newElement.y + this.fullSize[1],
            ...other
          });
          extraElements.push({
            x: newElement.x,
            y: newElement.y + this.fullSize[1],
            ...other
          });
        } else if (
          newElement.y + newElement.radius >= this.fullSize[1] ||
          newElement.y + newElement.height >= this.fullSize[1]
        ) {
          extraElements.push({
            x: newElement.x + this.fullSize[0],
            y: newElement.y - this.fullSize[1],
            ...other
          });
          extraElements.push({
            x: newElement.x,
            y: newElement.y - this.fullSize[1],
            ...other
          });
        }
      } else if (
        newElement.x + newElement.radius >= this.fullSize[0] ||
        newElement.x + newElement.width >= this.fullSize[0]
      ) {
        extraElements.push({
          x: newElement.x - this.fullSize[0],
          y: newElement.y,
          ...other
        });
        if (
          newElement.y < newElement.radius ||
          newElement.y < newElement.height
        ) {
          extraElements.push({
            x: newElement.x - this.fullSize[0],
            y: newElement.y + this.fullSize[1],
            ...other
          });
          extraElements.push({
            x: newElement.x,
            y: newElement.y + this.fullSize[1],
            ...other
          });
        } else if (
          newElement.y + newElement.radius >= this.fullSize[1] ||
          newElement.y + newElement.height >= this.fullSize[1]
        ) {
          extraElements.push({
            x: newElement.x - this.fullSize[0],
            y: newElement.y - this.fullSize[1],
            ...other
          });
          extraElements.push({
            x: newElement.x,
            y: newElement.y - this.fullSize[1],
            ...other
          });
        }
      } else if (
        newElement.y < newElement.radius ||
        newElement.y < newElement.height
      ) {
        extraElements.push({
          x: newElement.x,
          y: newElement.y + this.fullSize[1],
          ...other
        });
      } else if (
        newElement.y + newElement.radius >= this.fullSize[1] ||
        newElement.y + newElement.height >= this.fullSize[1]
      ) {
        extraElements.push({
          x: newElement.x,
          y: newElement.y - this.fullSize[1],
          ...other
        });
      }
    }
    elementsArray.push(...extraElements);

    return elementsArray;
  }
  clearMap(n) {
    if (this.crossNumb == 3) {
      if (
        this.camera[n] > this.crossMap[0][n] + 0.5 * this.cutSize[n] &&
        this.camera[n] < this.crossMap[0][n] + 1.5 * this.cutSize[n]
      ) {
        if (this.crossMap[1][n] == this.crossMap[0][n]) {
          this.crossMap.pop();
          this.crossMap.pop();
        } else {
          this.crossMap.pop();
          this.crossMap.splice(1, 1);
        }
        this.crossNumb -= 2;
      } else if (
        this.camera[n] > this.crossMap[3][n] + 0.5 * this.cutSize[n] &&
        this.camera[n] < this.crossMap[3][n] + 1.5 * this.cutSize[n]
      ) {
        if (this.crossMap[3][n] == this.crossMap[0][n] + this.cutSize[n] * 3) {
          this.camera[n] -= 3 * this.cutSize[n];
        } else {
          this.camera[n] += 3 * this.cutSize[n];
        }
        if (this.crossMap[1][n] == this.crossMap[0][n]) {
          this.crossMap.pop();
          this.crossMap.pop();
        } else {
          this.crossMap.pop();
          this.crossMap.splice(1, 1);
        }
        this.crossNumb -= 2;
      }
    } else if (this.crossNumb == 1) {
      if (
        this.camera[n] > this.crossMap[0][n] + 0.5 * this.cutSize[n] &&
        this.camera[n] < this.crossMap[0][n] + 1.5 * this.cutSize[n] &&
        this.crossMap[1][n] != this.crossMap[0][n]
      ) {
        this.crossMap.pop();
        this.crossNumb--;
      } else if (
        this.camera[n] > this.crossMap[1][n] + 0.5 * this.cutSize[n] &&
        this.camera[n] < this.crossMap[1][n] + 1.5 * this.cutSize[n] &&
        this.crossMap[1][n] != this.crossMap[0][n]
      ) {
        if (this.crossMap[1][n] == this.crossMap[0][n] + this.cutSize[n] * 3) {
          this.camera[n] -= 3 * this.cutSize[n];
        } else {
          this.camera[n] += 3 * this.cutSize[n];
        }
        this.crossMap.pop();
        this.crossNumb--;
      }
    }
  }
  drawStars() {
    const context = this.canvas.getContext("2d");
    let grad;
    let curentElem;
    context.globalCompositeOperation = "lighten";

    for (let i = 0; i < this.stars.length; i++) {
      curentElem = this.stars[i];
      context.save();
      context.beginPath();
      context.arc(
        curentElem.x,
        curentElem.y,
        curentElem.radius,
        0,
        2 * Math.PI,
        true
      );
      context.lineWidth = curentElem.width;
      grad = context.createRadialGradient(
        curentElem.x,
        curentElem.y,
        0,
        curentElem.x,
        curentElem.y,
        curentElem.radius + this.scaleParam * 2
      );
      grad.addColorStop(
        0,
        `${curentElem.color + (0.06 + 0.01 * this.scaleParam)})`
      );
      grad.addColorStop(1, `${curentElem.color + 0.0})`); //0.0
      context.fillStyle = grad;
      context.fill();
      context.closePath();

      //белая звезда + дымка
      context.beginPath();
      context.arc(
        curentElem.x,
        curentElem.y,
        curentElem.radius / 4,
        0,
        2 * Math.PI,
        true
      );
      grad = context.createRadialGradient(
        curentElem.x,
        curentElem.y,
        0,
        curentElem.x,
        curentElem.y,
        curentElem.radius / (38 - 5 * this.scaleParam)
      );
      grad.addColorStop(0, `rgba(245,240,250, ${curentElem.radius * 0.04})`);
      grad.addColorStop(
        this.scaleParam * 0.1,
        `rgba(245,240,250, ${curentElem.radius * 0.02})`
      );
      grad.addColorStop(1, `rgba(245,240,250, ${this.scaleParam * 0.001})`);
      context.fillStyle = grad;
      context.fill();
      context.closePath();
      context.restore();
    }
  }

  drawClouds() {
    const layerContext = this.canvas.getContext("2d");
    const cloudCanvas = cloudCanvases[0].canvas;
    const cloudWidth = cloudCanvases[0].width;
    const cloudHeight = cloudCanvases[0].height;
    const scaleCanvas = document.createElement("canvas");
    //document.getElementById('hidden').appendChild(scaleCanvas);
    scaleCanvas.width = cloudWidth * 2;
    scaleCanvas.height = cloudHeight * 2;
    let scaleContext = scaleCanvas.getContext("2d");

    let curentElem;
    for (let i = 0; i < this.clouds.length; i++) {
      curentElem = this.clouds[i];
      scaleContext.save();
      scaleContext.clearRect(0, 0, scaleCanvas.width, scaleCanvas.height);
      scaleContext.translate(cloudWidth, cloudHeight);
      scaleContext.rotate(180 * curentElem.rotate * Math.PI / 180);
      scaleContext.drawImage(cloudCanvas, -cloudWidth / 2, -cloudHeight / 2);
      scaleContext.restore();
      scaleContext.save();
      scaleContext.globalCompositeOperation = "source-in";
      scaleContext.fillStyle = `${curentElem.color} 1)`;
      scaleContext.fillRect(0, 0, cloudWidth * 2, cloudHeight * 2);
      scaleContext.restore();
      layerContext.drawImage(
        scaleCanvas,
        curentElem.x,
        curentElem.y,
        curentElem.height,
        curentElem.width
      );
    }
  }
}

function update(context) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i < layerArray.length; i++) {
    that = layerArray[i];

    that.camera[0] += speedX * that.scaleParam;
    that.camera[1] += speedY * that.scaleParam;
    if (speedX > 0) {
      that.clearMap(0);
      if (
        that.camera[0] >
        that.crossMap[that.crossNumb][0] + that.cutSize[0] * 1.5
      ) {
        if (that.crossNumb == 3) {
          if (
            that.crossMap[that.crossNumb][0] !=
              that.crossMap[0][0] + that.cutSize[0] * 3 &&
            that.crossMap[0][0] < that.camera[0]
          ) {
            if (that.crossMap[1][0] == that.crossMap[0][0]) {
              that.crossMap.splice(
                2,
                2,
                [
                  that.crossMap[0][0] + 3 * that.cutSize[0],
                  that.crossMap[0][1]
                ],
                [that.crossMap[0][0] + 3 * that.cutSize[0], that.crossMap[1][1]]
              );
            } else {
              that.crossMap.pop();
              that.crossMap.splice(1, 1, [
                that.crossMap[0][0] + 3 * that.cutSize[0],
                that.crossMap[0][1]
              ]);
              that.crossMap.push([
                that.crossMap[0][0] + 3 * that.cutSize[0],
                that.crossMap[2][1]
              ]);
            }
          }
        } else if (that.crossNumb == 1) {
          if (that.crossMap[that.crossNumb][0] == that.crossMap[0][0]) {
            that.crossMap.push([
              that.crossMap[that.crossNumb][0] + 3 * that.cutSize[0],
              that.crossMap[0][1]
            ]);
            that.crossMap.push([
              that.crossMap[that.crossNumb][0] + 3 * that.cutSize[0],
              that.crossMap[that.crossNumb][1]
            ]);
            that.crossNumb += 2;
          } else if (
            that.crossMap[that.crossNumb][0] !=
              that.crossMap[0][0] + that.cutSize[0] * 3 &&
            that.crossMap[0][0] < that.camera[0]
          ) {
            that.crossMap.pop();
            that.crossMap.push([
              that.crossMap[0][0] + 3 * that.cutSize[0],
              that.crossMap[0][1]
            ]);
          }
        } else {
          that.crossMap.push([
            that.crossMap[that.crossNumb][0] + 3 * that.cutSize[0],
            that.crossMap[that.crossNumb][1]
          ]);
          that.crossNumb++;
        }
      }
    } else if (speedX < 0) {
      that.clearMap(0);
      if (
        that.camera[0] <
        that.crossMap[that.crossNumb][0] + that.cutSize[0] * 0.5
      ) {
        if (that.crossNumb == 3) {
          if (
            that.crossMap[that.crossNumb][0] !=
              that.crossMap[0][0] - that.cutSize[0] * 3 &&
            that.crossMap[0][0] > that.camera[0]
          ) {
            if (that.crossMap[1][0] == that.crossMap[0][0]) {
              that.crossMap.splice(
                2,
                2,
                [
                  that.crossMap[0][0] - 3 * that.cutSize[0],
                  that.crossMap[0][1]
                ],
                [that.crossMap[0][0] - 3 * that.cutSize[0], that.crossMap[1][1]]
              );
            } else {
              that.crossMap.pop();
              that.crossMap.splice(1, 1, [
                that.crossMap[0][0] - 3 * that.cutSize[0],
                that.crossMap[0][1]
              ]);
              that.crossMap.push([
                that.crossMap[0][0] - 3 * that.cutSize[0],
                that.crossMap[2][1]
              ]);
            }
          }
        } else if (that.crossNumb == 1) {
          if (that.crossMap[that.crossNumb][0] == that.crossMap[0][0]) {
            that.crossMap.push([
              that.crossMap[that.crossNumb][0] - 3 * that.cutSize[0],
              that.crossMap[0][1]
            ]);
            that.crossMap.push([
              that.crossMap[that.crossNumb][0] - 3 * that.cutSize[0],
              that.crossMap[that.crossNumb][1]
            ]);
            that.crossNumb += 2;
          } else if (
            that.crossMap[that.crossNumb][0] !=
              that.crossMap[0][0] - that.cutSize[0] * 3 &&
            that.crossMap[0][0] > that.camera[0]
          ) {
            that.crossMap.pop();
            that.crossMap.push([
              that.crossMap[0][0] - 3 * that.cutSize[0],
              that.crossMap[0][1]
            ]);
          }
        } else {
          that.crossMap.push([
            that.crossMap[that.crossNumb][0] - 3 * that.cutSize[0],
            that.crossMap[that.crossNumb][1]
          ]);
          that.crossNumb++;
        }
      }
    }
    if (speedY > 0) {
      that.clearMap(1);
      if (
        that.camera[1] >
        that.crossMap[that.crossNumb][1] + that.cutSize[1] * 1.5
      ) {
        if (that.crossNumb == 1) {
          if (that.crossMap[that.crossNumb][1] == that.crossMap[0][1]) {
            that.crossMap.push([
              that.crossMap[0][0],
              that.crossMap[that.crossNumb][1] + 3 * that.cutSize[1]
            ]);
            that.crossMap.push([
              that.crossMap[that.crossNumb][0],
              that.crossMap[that.crossNumb][1] + 3 * that.cutSize[1]
            ]);
            that.crossNumb += 2;
          } else if (
            that.crossMap[that.crossNumb][1] !=
              that.crossMap[0][1] + that.cutSize[1] * 3 &&
            that.crossMap[0][1] < that.camera[1]
          ) {
            that.crossMap.pop();
            that.crossMap.push([
              that.crossMap[0][0],
              that.crossMap[0][1] + 3 * that.cutSize[1]
            ]);
          }
        } else if (that.crossNumb == 3) {
          if (
            that.crossMap[that.crossNumb][1] !=
              that.crossMap[0][1] + that.cutSize[1] * 3 &&
            that.crossMap[0][1] < that.camera[1]
          ) {
            if (that.crossMap[1][1] == that.crossMap[0][1]) {
              that.crossMap.splice(
                2,
                2,
                [
                  that.crossMap[0][0],
                  that.crossMap[0][1] + 3 * that.cutSize[1]
                ],
                [that.crossMap[1][0], that.crossMap[0][1] + 3 * that.cutSize[1]]
              );
            } else {
              that.crossMap.pop();
              that.crossMap.splice(1, 1, [
                that.crossMap[0][0],
                that.crossMap[0][1] + 3 * that.cutSize[1]
              ]);
              that.crossMap.push([
                that.crossMap[2][0],
                that.crossMap[0][1] + 3 * that.cutSize[1]
              ]);
            }
          }
        } else {
          that.crossMap.push([
            that.crossMap[that.crossNumb][0],
            that.crossMap[that.crossNumb][1] + 3 * that.cutSize[1]
          ]);
          that.crossNumb++;
        }
      }
    } else if (speedY < 0) {
      that.clearMap(1);
      if (
        that.camera[1] <
        that.crossMap[that.crossNumb][1] + that.cutSize[1] * 0.5
      ) {
        if (that.crossNumb == 1) {
          //проверить 0 и 1 элемент на х, если одинаковые то должны сделать 2 элемента
          if (that.crossMap[that.crossNumb][1] == that.crossMap[0][1]) {
            // по вертикали?
            that.crossMap.push([
              that.crossMap[0][0],
              that.crossMap[that.crossNumb][1] - 3 * that.cutSize[1]
            ]);
            that.crossMap.push([
              that.crossMap[that.crossNumb][0],
              that.crossMap[that.crossNumb][1] - 3 * that.cutSize[1]
            ]);
            that.crossNumb += 2;
          } else if (
            that.crossMap[0][1] > that.camera[1] &&
            that.crossMap[that.crossNumb][1] !=
              that.crossMap[0][1] - that.cutSize[1] * 3
          ) {
            //справа?
            that.crossMap.pop();
            that.crossMap.push([
              that.crossMap[0][0],
              that.crossMap[0][1] - 3 * that.cutSize[1]
            ]);
          }
        } else if (that.crossNumb == 3) {
          if (
            that.crossMap[that.crossNumb][1] !=
              that.crossMap[0][1] - that.cutSize[1] * 3 &&
            that.crossMap[0][1] > that.camera[1]
          ) {
            if (that.crossMap[1][1] == that.crossMap[0][1]) {
              // по вертикали?
              that.crossMap.splice(
                2,
                2,
                [
                  that.crossMap[0][0],
                  that.crossMap[0][1] - 3 * that.cutSize[1]
                ],
                [that.crossMap[1][0], that.crossMap[0][1] - 3 * that.cutSize[1]]
              );
            } else {
              that.crossMap.pop();
              that.crossMap.splice(1, 1, [
                that.crossMap[0][0],
                that.crossMap[0][1] - 3 * that.cutSize[1]
              ]);
              that.crossMap.push([
                that.crossMap[2][0],
                that.crossMap[0][1] - 3 * that.cutSize[1]
              ]);
            }
          }
        } else {
          that.crossMap.push([
            that.crossMap[that.crossNumb][0],
            that.crossMap[that.crossNumb][1] - 3 * that.cutSize[1]
          ]);
          that.crossNumb++;
        }
      }
    }
    for (let i = 0; i <= that.crossNumb; i++) {
      context.drawImage(
        that.canvas,
        that.crossMap[i][0] - that.camera[0],
        that.crossMap[i][1] - that.camera[1]
      );
    }
    context.restore();
  }

  animationTimeout = window.requestAnimationFrame(() => {
    update(context);
  });
}

let animationTimeout;
let debounceTimeout;

const debounceDelay = 600;

window.requestAnimationFrame =
  window.requestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.msRequestAnimationFrame ||
  function(t) {
    return setTimeout(t, 1000 / 60);
  };
window.cancelAnimationFrame =
  window.cancelAnimationFrame ||
  window.mozCancelAnimationFrame ||
  function(t) {
    clearTimeout(t);
  };

/*____________________________________________________ */

let windowParam;
let that;
let speedX, speedY;
let quantityStars, quantityClouds;

const canvas = document.getElementById("visible");
let context;

let layerArray = [];

let cloudCanvases = [];
let loadedImages = 0;
let bufferImages = [];

const clouds = ["https://www.dropbox.com/s/6wxtfm496ufcsuu/cloud.png?dl=1"];

const getParams = () => {
  if (animationTimeout) {
    window.cancelAnimationFrame(animationTimeout);
  }
  windowParam = [document.body.clientWidth, document.body.clientHeight];
  speedX = settings.startSpeed.x;
  speedY = settings.startSpeed.y;
  quantityStars = Math.floor(windowParam[0] * windowParam[1] / 200);
  quantityClouds = Math.floor(windowParam[0] * windowParam[1] / 10245);
  canvas.width = windowParam[0];
  canvas.height = windowParam[1];
  context = canvas.getContext("2d");
  layerArray = [];
};
/*wtf... need change it*/
const start = () => {
  if (loadedImages >= clouds.length) {
    layerArray.push(new CanvasBuffer(1, windowParam, quantityStars, 0));
    layerArray.push(
      new CanvasBuffer(
        2,
        windowParam,
        Math.floor(quantityStars / 6),
        quantityClouds
      )
    );
    layerArray.push(
      new CanvasBuffer(
        2.5,
        windowParam,
        Math.floor(quantityStars / 6),
        Math.floor(quantityClouds / 3)
      )
    );
    layerArray.push(
      new CanvasBuffer(3, windowParam, Math.floor(quantityStars / 8), 0)
    );

    for (let i = 0; i < layerArray.length; i++) {
      layerArray[i].drawClouds();
      layerArray[i].drawStars();
    }

    animationTimeout = window.requestAnimationFrame(() => {
      update(context);
    });
  }
};

(() => {
  let cloudCanvas, cloudContext;

  for (let i = 0; i < clouds.length; i++) {
    bufferImages[i] = new Image();
    bufferImages[i].src = clouds[i];
    bufferImages[i].onload = function() {
      cloudCanvas = document.createElement("canvas");
      cloudCanvas.id = `cloud_${i}`;
      cloudCanvas.width = bufferImages[i].naturalWidth;
      cloudCanvas.height = bufferImages[i].naturalHeight;
      //document.getElementById('hidden').appendChild(cloudCanvas);

      cloudContext = cloudCanvas.getContext("2d");
      cloudContext.drawImage(
        bufferImages[i],
        0,
        0,
        cloudCanvas.width,
        cloudCanvas.height
      );
      cloudCanvases.push({
        canvas: cloudCanvas,
        width: cloudCanvas.width,
        height: cloudCanvas.height
      });
      loadedImages++;
      getParams();
      start();
    };
  }
})();

canvas.addEventListener(
  "mousemove",
  e => {
    speedX = 2 * (2 * e.clientX / windowParam[0] - 1);
    speedY = 2 * (2 * e.clientY / windowParam[1] - 1);
  },
  false
);
window.addEventListener(
  "resize",
  () => {
    clearTimeout(debounceTimeout);

    debounceTimeout = setTimeout(() => {
      getParams();
      start();
    }, debounceDelay);
  },
  false
);
canvas.addEventListener(
  "mouseleave",
  () => {
    speedX = settings.startSpeed.x;
    speedY = settings.startSpeed.y;
  },
  false
);
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.