如何让 p5.js 实例模式只为 <div> 渲染?

How to make p5.js Instance Mode render only for a <div>?

我使用实例模式创建了一个简单的草图:

var start = 0
var trueSize
const ring = (sketch) => {
    sketch.setup = () => {
        trueSize = sketch.windowWidth > sketch.windowHeight ? sketch.windowHeight : sketch.windowWidth
        sketch.createCanvas(sketch.windowWidth, sketch.windowHeight)
        sketch.angleMode(sketch.DEGREES)
        sketch.noiseDetail(2, 1)
    }

    sketch.draw = () => {
        sketch.background(30)
        sketch.noStroke()
        sketch.translate(sketch.width / 2, sketch.height / 2)
        var space = 0.1
        for (var i = 0; i < 360; i += space) {
            var xoff = sketch.map(sketch.cos(i), -1, 1, 0, 3)
            var yoff = sketch.map(sketch.sin(i), -1, 1, 0, 3)
            var n = sketch.noise(xoff + start, yoff + start)
            var h = sketch.map(n, 0, 1, -90, 90)

            var r = sketch.map(sketch.sin(i), -1, 1, 100, 200)
            var g = sketch.map(h, -150, 150, 0, 150)
            var b = sketch.map(n, 0, 1, 150, 255)

            sketch.rotate(space)
            sketch.fill(r, g, b)
            sketch.rect(trueSize * 0.3, 0, h, 1)
        }
        start += 0.01
    }
}

let myp5 = new p5(ring, 'ring')
//let myp5 = new p5(ring, document.getElementById('ring')); //This does not work either.

在我的 index.html 中,我有:

<!DOCTYPE html>
<html lang="en">
    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
        <link rel="stylesheet" type="text/css" href="style.css" />
        <meta charset="utf-8" />
        <script src="sketch.js"></script>
    </head>
    <body>

       <div id="ring" ></div> <!-- This is not respected. When commented out, the p5 image still appears. -->
    </body>
</html>

我遇到的问题是草图并未在 div 中真正渲染。当我注释掉 div 或将 width/height 设置为 div 时,不管 div.

仍然绘制草图

找不到 div 时的回退是设计使然,尽管如果 div 存在,p5 确实会使用它。让我们 look at the source:

// ... inside p5 constructor ... line 233 in src/core/main.js 5d4fd14 
    this._start = () => {
      // Find node if id given
      if (this._userNode) {
        if (typeof this._userNode === 'string') {
          this._userNode = document.getElementById(this._userNode);
        }
      }

      const context = this._isGlobal ? window : this;
      if (context.preload) {
        // Setup loading screen
        // Set loading screen into dom if not present
        // Otherwise displays and removes user provided loading screen
        let loadingScreen = document.getElementById(this._loadingScreenId);
        if (!loadingScreen) {
          loadingScreen = document.createElement('div');
          loadingScreen.innerHTML = 'Loading...';
          loadingScreen.style.position = 'absolute';
          loadingScreen.id = this._loadingScreenId;
          const node = this._userNode || document.body;
          node.appendChild(loadingScreen);
        }
// ...

如果你传递一个字符串,p5 使用 this._userNode = document.getElementById(this._userNode); 来尝试通过该 id 找到元素。如果你传递一个节点,它永远不会运行,但无论哪种方式,我们最终都会得到代码

const node = this._userNode || document.body;
node.appendChild(loadingScreen);

如果 this._userNode 最终是错误的(即你从未传递任何东西或在文档中找不到 id),p5 返回到 document.body

您可以在整个代码库中看到此回退:

PS C:\Users\greg\Desktop\p5.js-main\src> grep -RC 1 userNode .
./core/main.js-    this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1;
./core/main.js:    this._userNode = node;
./core/main.js-    this._curElement = null;
--
./core/main.js-      // Find node if id given
./core/main.js:      if (this._userNode) {
./core/main.js:        if (typeof this._userNode === 'string') {
./core/main.js:          this._userNode = document.getElementById(this._userNode);
./core/main.js-        }
--
./core/main.js-          loadingScreen.id = this._loadingScreenId;
./core/main.js:          const node = this._userNode || document.body;
./core/main.js-          node.appendChild(loadingScreen);
--
./core/p5.Graphics.js-  this.canvas = document.createElement('canvas');
./core/p5.Graphics.js:  const node = pInst._userNode || document.body;
./core/p5.Graphics.js-  node.appendChild(this.canvas);
--
./core/rendering.js-
./core/rendering.js:  if (this._userNode) {
./core/rendering.js-    // user input node case
./core/rendering.js:    this._userNode.appendChild(c);
./core/rendering.js-  } else {
--
./dom/dom.js-function addElement(elt, pInst, media) {
./dom/dom.js:  const node = pInst._userNode ? pInst._userNode : document.body;
./dom/dom.js-  node.appendChild(elt);
--
./webgl/p5.RendererGL.js-    pg.canvas = document.createElement('canvas');
./webgl/p5.RendererGL.js:    const node = pg._pInst._userNode || document.body;
./webgl/p5.RendererGL.js-    node.appendChild(pg.canvas);
--
./webgl/p5.RendererGL.js-    c.id = defaultId;
./webgl/p5.RendererGL.js:    if (this._pInst._userNode) {
./webgl/p5.RendererGL.js:      this._pInst._userNode.appendChild(c);
./webgl/p5.RendererGL.js-    } else {

如果您的目标是除非特定元素存在,否则不渲染草图,请检查您的客户端代码,不要调用 p5 构造函数。