【问题标题】:how can I use parcel.js to run p5.js code?如何使用 parcel.js 运行 p5.js 代码?
【发布时间】:2020-10-28 09:28:48
【问题描述】:

我最近一直在使用 parcel.js 和 react 应用程序,它对用户非常友好。

我正在学习 Coding Train 教程,并且由于某种原因没有运行代码。

https://github.com/CodingTrain/website/tree/master/CodingChallenges/CC_001_StarField/P5

当我使用实时服务器运行它时,没有错误并且一切运行正常。

当我尝试使用 parcel.js 运行它时,没有错误,只是没有运行,没有任何渲染。

知道为什么会发生这种情况吗?

谢谢

【问题讨论】:

    标签: p5.js parceljs


    【解决方案1】:

    我认为这里的问题是 Parcel.js 默认情况下不会将 src 脚本中定义的变量放入全局范围,而 p5.js 默认情况下依赖于这些全局变量(setupdraw 在特定)。您可以通过在sketch.js 中创建speedsetupdraw 以及在Star.js 中创建Star 的属性window(或者,等效地,global)来解决问题。请参阅下面的示例,该示例在使用 parcel index.html 构建时有效。

    (此方法的好处是无需前缀即可保留对熟悉的(全局)p5.js 命令的访问权限,但如果您使用其他库,可能会导致全局变量被覆盖。)

     
    //sketch.js   
    let stars = [];
    
    window.speed = undefined;
    
    window.setup = function setup() {
      createCanvas(600, 600);
      for (let i = 0; i < 800; i++) {
        stars[i] = new Star();
      }
    }
    
    window.draw = function draw() {
      speed = map(mouseX, 0, width, 0, 50);
      background(0);
      translate(width / 2, height / 2);
      for (let i = 0; i < stars.length; i++) {
        stars[i].update();
        stars[i].show();
      }
    }
    
    //Star.js
    window.Star = function Star() {
      this.x = random(-width, width);
      this.y = random(-height, height);
      this.z = random(width);
      this.pz = this.z;
    
      this.update = function() {
        this.z = this.z - speed;
        if (this.z < 1) {
          this.z = width;
          this.x = random(-width, width);
          this.y = random(-height, height);
          this.pz = this.z;
        }
      };
    
      this.show = function() {
        fill(255);
        noStroke();
    
        var sx = map(this.x / this.z, 0, 1, 0, width);
        var sy = map(this.y / this.z, 0, 1, 0, height);
    
        var r = map(this.z, 0, width, 16, 0);
        ellipse(sx, sy, r, r);
    
        var px = map(this.x / this.pz, 0, 1, 0, width);
        var py = map(this.y / this.pz, 0, 1, 0, height);
    
        this.pz = this.z;
    
        stroke(255);
        line(px, py, sx, sy);
      };
    }
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>StarField_p5.js</title>
        <style>
          body {
            padding: 0;
            margin: 0;
          }
          canvas {
            vertical-align: top;
          }
        </style>
        <script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/addons/p5.sound.min.js"></script>
    
        <script src="./Star.js"></script>
        <script src="./sketch.js"></script>
      </head>
      <body>
        <main></main>
      </body>
    </html>

    或者,您可以使用 P5.js 的 instance mode 来设置没有全局变量(另请参阅线程 here - 其代码示例现在已删除其 P5.js 依赖项,但您可以查看提交历史)。这有一个缺点,即熟悉的 P5.js / 处理函数必须以对象引用为前缀,至少类似于 s.createCanvas (这些方法通常似乎依赖于以面向对象的样式正确绑定)。但是,如果涉及其他库,这可能是更安全的方法,尤其是 p5.js 定义了许多具有通用名称的全局变量,例如 randommapheight,如果它不用于实例模式。

    类似这样的:

     
    // index.js
    // I've combined sketch.js and Star.js here to make
    // it easier to share variable speed
    
    const myp5 = new p5((s) => {
      
      const stars = [];
    
      let speed =1;
    
      s.setup = function setup() {
        s.createCanvas(600, 600);
        for (let i = 0; i < 800; i++) {
          stars[i] = new Star();
        }
      };
    
      s.draw = function draw() {
        speed = s.map(s.mouseX, 0, s.width, 0, 50);
        s.background(0);
        s.translate(s.width / 2, s.height / 2);
        for (let i = 0; i < stars.length; i++) {
          stars[i].update();
          stars[i].show();
        }
      };
    
     function Star() {
       this.x = s.random(-s.width, s.width);
       this.y = s.random(-s.height, s.height);
       this.z = s.random(s.width);
       this.pz = this.z;
    
       this.update = function () {
         this.z = this.z - speed;
         if (this.z < 1) {
           this.z = s.width;
           this.x = s.random(-s.width, s.width);
           this.y = s.random(-s.height, s.height);
           this.pz = this.z;
         }
       };
    
       this.show = function () {
         s.fill(255);
         s.noStroke();
    
         var sx = s.map(this.x / this.z, 0, 1, 0, s.width);
         var sy = s.map(this.y / this.z, 0, 1, 0, s.height);
    
         var r = s.map(this.z, 0, s.width, 16, 0);
         s.ellipse(sx, sy, r, r);
    
         var px = s.map(this.x / this.pz, 0, 1, 0, s.width);
         var py = s.map(this.y / this.pz, 0, 1, 0, s.height);
    
         this.pz = this.z;
    
         s.stroke(255);
         s.line(px, py, sx, sy);
       };
     }
    },'sketch1');
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>StarField_p5.js</title>
        <style>
          body {
            padding: 0;
            margin: 0;
          }
          canvas {
            vertical-align: top;
          }
        </style>
        <script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/addons/p5.sound.min.js"></script>
        <script src="./index.js"></script>
      </head>
      <body>
        <div id="sketch1"></div>
      </body>
    </html>

    【讨论】:

    • 太棒了,再次感谢!我今天更多地了解了这种替代方法,您的跟进支持了我一直在学习的内容。
    • 严格来说,我认为您可以摆脱对前缀的需要,例如 const [background,translate] = ['background','translate'].map(x=&gt;s[x].bind(s)); .... 或许内省 s 及其原型以区分功能并节省两次键入所有名称.如果您要复制和粘贴大量 p5.js 代码,可能值得这样做。或者也许有人知道更好的方法?
    • 哦,这是一个有趣的想法。但是不,我不打算复制和粘贴太多 p5,计划是越来越多地编写它:)
    猜你喜欢
    • 2017-06-05
    • 2020-06-26
    • 2017-05-02
    • 2023-01-19
    • 2021-09-12
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2020-02-23
    相关资源
    最近更新 更多