如何避免多个 p5.js 草图同时变为 运行

how to avoid multiple p5.js sketches to run all at once

我有一个网页,里面有一些草图,都是用 P5.JS

写的

每个草图都使用自己的名称 space,因此它 运行 独立于其他草图。

我注意到,对于每个草图,性能水平都低于我在单独的网页中 运行 获得的性能水平。

我的问题:如何防止所有草图同时 运行?例如,是否可以仅在鼠标悬停在其 canvas 上时激活草图?它可能会节省资源。

感谢您的帮助。

您可以调用 noLoop()loop() 来停止和重新启动草图。当鼠标离开草图或草图滚出屏幕时,没有任何内置的 p5.js 事件可以帮助您触发 noLoop(),但是您可以通过几种方法来实现关于使用底层浏览器功能:

  1. 内置 mouseentermouseleave 事件
  2. 在每次调用 draw()
  3. 时根据草图 canvas getBoundingClientRect() 检查 winMouseXwinMouseY

function makeSketch(...colorArgs) {
  return (p) => {
    let bgColor;
    let black;
    let c;
    p.setup = () => {
      c = p.createCanvas(p.windowWidth, p.windowHeight / 3);
      bgColor = p.color(...colorArgs);
      black = p.color(0);
      
      c.elt.addEventListener('mouseenter', () => {
        p.loop();
      });
      c.elt.addEventListener('mouseleave', () => {
        p.noLoop();
      });
      
      let bounds = c.elt.getBoundingClientRect();
      
      // Just in case the mouse is already over the canvas when it is created.
      // This is also how you would use getBoundingClientRect from the draw()
      // and mouseMoved() functions instead of the mouseenter/mouseleave events.
      if (p.winMouseX < bounds.left ||
        p.winMouseX > bounds.right ||
        p.minMouseY < bounds.top ||
        p.winMouseY > bounds.bottom) {
        
        p.noLoop();
      }
    };
    
    p.draw = () => {
      p.background(p.lerpColor(
        bgColor,
        black,
        p.abs((p.frameCount % 240 - 120) / 120)
      ));
      
      
      let bounds = c.elt.getBoundingClientRect();
      p.fill('white');
      p.noStroke();
      p.text(`${p.winMouseX}, ${p.winMouseY} :: ${bounds.left}, ${bounds.top}, ${bounds.right}, ${bounds.bottom}`, 10, 10); 
    }
  };
}

let sketch1 = new p5(makeSketch('red'));
let sketch2 = new p5(makeSketch(0, 255, 0));
let sketch3 = new p5(makeSketch('blue'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

您可能还会发现暂停屏幕外的草图就足够了:

function makeSketch(...colorArgs) {
  return (p) => {
    let bgColor;
    let black;
    let c;
    let isLooping;
    p.setup = () => {
      c = p.createCanvas(p.windowWidth, p.windowHeight);
      bgColor = p.color(...colorArgs);
      black = p.color(0);
      
      let bounds = c.elt.getBoundingClientRect();
      
      isLooping = true;
      if (bounds.bottom < 0 ||
          bounds.top > p.windowHeight) {
        
        p.noLoop();
        isLooping = false;
      }
      
      // Might need to check this on resize as well.
      document.addEventListener('scroll', () => {
        let bounds = c.elt.getBoundingClientRect();
        // Note this only checks verticle scrolling, but you could check horizontal as well
        if (bounds.bottom > 0 &&
            bounds.top <= p.windowHeight) {

          if (!isLooping) {
            isLooping = true;
            console.log(`sketch ${colorArgs.join(',')}: loop`);
            p.loop();
          }
        } else if (isLooping) {
          isLooping = false;
          console.log(`sketch ${colorArgs.join(',')}: noLoop`);
          p.noLoop();
        }
      });
    };
    
    p.draw = () => {
      p.background(p.lerpColor(
        bgColor,
        black,
        p.abs((p.frameCount % 240 - 120) / 120)
      ));
      
      p.fill('white');
      p.noStroke();
      p.text(`${p.frameCount}`, 10, 10);
    }
  };
}

let sketch1 = new p5(makeSketch('red'));
let sketch2 = new p5(makeSketch(0, 255, 0));
let sketch3 = new p5(makeSketch('blue'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>