P5.JS - 使用对象及其属性和功能,用预加载的图像填充形状

P5.JS - Filling a shape with a preloaded image, using an object, its properties and its functions

我正在尝试创建一个对象并使其具有形状(椭圆)、图像和以某种方式用预加载图像填充形状的函数。

我已经找到了 ,但是如果我试图使它整洁并将其全部放入一个对象中,我将无法使用它。

要清楚,这就是它的样子:

let image;
let hypotheticalObject
function preload()
{
   image = loadImage('Assets/randomimage.jpeg');
}


function setup()
{
    hypotheticalObject = {
        objectImage: image,
        graphicsBuffer: createGraphics(100, 100),
        xPos: width / 2,
        yPos: height / 2,
        size: 50,
        colour: color(255, 255, 255),

        shape: function()
        {
            fill(this.colour),
            ellipse(this.xPos, this.yPos, this.size);
        },
        
        mask: function()
        {
            this.graphicsBuffer.shape();
        },

        render: function()
        {
            something something
        }
        
}

function draw()
{
    hypotheticalObject.render();
}

这就是我能做到的程度,因为我不知道如何继续。

您的代码有几个问题,即:

shape: function() {
  // ...
},

mask: function() {
  this.graphicsBuffer.shape();
},

您在 hypotheticalObject 上声明了 shape(),但随后您尝试在 graphicsBuffer 上调用它?这不是 javascript 的工作方式。你可以这样做:

hypotheticalObject.graphicsBuffer.shape = function() {
  // When graphicsBuffer.shape() is called, the this keyword will be bound to graphicsBuffer
  // Unfortunately we need a to access members from hypotheticalObject as well, so that is inconvenient:
  this.fill(hypotheticalObject.colour),
  this.ellipse(hypotheticalObject.xPos, hypotheticalObject.yPos, hypotheticalObject.size);
}

但是我认为这也不是最惯用的方法。这是一个试图接近您的代码的工作解决方案:

let img;
let hypotheticalObject;

function preload() {
  img = loadImage('https://www.paulwheeler.us/files/windows-95-desktop-background.jpg');
}

function setup() {
  createCanvas(windowWidth, windowHeight);
  
  hypotheticalObject = {
    objectImage: img,
    // The graphics you're using for the mask need to be the size of the image
    graphicsBuffer: createGraphics(img.width, img.height),
    xPos: width / 2,
    yPos: height / 2,
    size: 50,
    
    init: function() {
      this.maskedImage = createImage(this.objectImage.width, this.objectImage.height);
    },

    updateShape: function() {
      this.graphicsBuffer.clear();
      // The fill color is irrelevant so long as it is opaque
      this.graphicsBuffer.fill(0);
      // These drawing instructions need to happen on the p5.Graphics object
      this.graphicsBuffer.ellipse(this.xPos, this.yPos, this.size);
    },

    render: function() {
      this.updateShape();
      // When you call mask on an image it changes the image so we need to make a copy
      this.maskedImage.copy(
        this.objectImage,
        0, 0, this.objectImage.width, this.objectImage.height,
        0, 0, this.objectImage.width, this.objectImage.height
      );
      this.maskedImage.mask(this.graphicsBuffer);
      // Always draw the image at 0, 0 since the masked portion is already offset
      image(this.maskedImage, 0, 0);
    }
  }

  hypotheticalObject.init();
}

let xv = 2;
let yv = 2;

function draw() {
  background(255);
  
  hypotheticalObject.xPos += xv;
  hypotheticalObject.yPos += yv;
  
  if (hypotheticalObject.xPos > width) {
    hypotheticalObject.xPos = width;
    xv *= -1;
  } else if (hypotheticalObject.xPos < 0) {
    hypotheticalObject.xPos = 0;
    xv *= -1;
  }
  if (hypotheticalObject.yPos > height) {
    hypotheticalObject.yPos = height;
    yv *= -1;
  } else if (hypotheticalObject.yPos < 0) {
    hypotheticalObject.yPos = 0;
    yv *= -1;
  }
  
  hypotheticalObject.render();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

更新:Gif 动画

如果你想让它与动画 gif 一起工作,你必须处理 p5.js 的一个特性:事实上它仅在使用 image() 函数渲染时更新 gif 图像或 texture() 函数。并且该渲染代码取决于具有计时信息的绘图上下文,因此不适用于屏幕外 p5.Graphics 缓冲区。这是一个例子:

let img;
let hypotheticalObject;

function preload() {
  img = loadImage('https://www.paulwheeler.us/files/Clouds.gif');
}

function setup() {
  createCanvas(img.width, img.height);

  hypotheticalObject = {
    objectImage: img,
    // The graphics you're using for the mask need to be the size of the image
    graphicsBuffer: createGraphics(img.width, img.height),
    xPos: width / 2,
    yPos: height / 2,
    size: 100,

    init: function() {
      this.maskedImage = createImage(this.objectImage.width, this.objectImage.height);
    },

    updateShape: function() {
      this.graphicsBuffer.clear();
      // The fill color is irrelevant so long as it is opaque
      this.graphicsBuffer.fill(0);
      // These drawing instructions need to happen on the p5.Graphics object
      this.graphicsBuffer.ellipse(this.xPos, this.yPos, this.size);
    },

    render: function() {
      this.updateShape();
      // When you call mask on an image it changes the image so we need to make a copy
      this.maskedImage.copy(
        this.objectImage,
        0, 0, this.objectImage.width, this.objectImage.height,
        0, 0, this.objectImage.width, this.objectImage.height
      );
      this.maskedImage.mask(this.graphicsBuffer);
      // Always draw the image at 0, 0 since the masked portion is already offset
      image(this.maskedImage, 0, 0);
    }
  }

  hypotheticalObject.init();
}

let xv = 2;
let yv = 2;

function draw() {
  // In order to get a gif to animate it needs to be passed to either the image() function or the texture() function. And unfortunately it must be the global one, not the version on an off-screen p5.Graphics
  // However we don't actually want to display this
  image(img, width, height);
  background(255);

  hypotheticalObject.xPos += xv;
  hypotheticalObject.yPos += yv;

  if (hypotheticalObject.xPos > width) {
    hypotheticalObject.xPos = width;
    xv *= -1;
  } else if (hypotheticalObject.xPos < 0) {
    hypotheticalObject.xPos = 0;
    xv *= -1;
  }
  if (hypotheticalObject.yPos > height) {
    hypotheticalObject.yPos = height;
    yv *= -1;
  } else if (hypotheticalObject.yPos < 0) {
    hypotheticalObject.yPos = 0;
    yv *= -1;
  }

  hypotheticalObject.render();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>