サマリ🎨
p5.jsで作成したスケッチを額縁にかざる方法をシェアいたします。
結論からいいますと、今回の成果物PictureFrame Classを使うとできるよという話です。
成果物
※ 本記事の下のほうにもソースコードをおいておきました。(ライセンスはpublic domain)
これを使うと、このようにアート作品をそれっぽくバーチャル展示できますよ!
"神奈川沖浪裏 x p5.pattern"
— Tetsunori NAKAYAMA | 中山 哲法 (@tetunori_lego) November 21, 2021
This is the 1st piece from #Generative富嶽三十六景 .https://t.co/CJoM90IQXp#creativecoding #generativeart #p5js pic.twitter.com/JPhKVn3Q3A
きっかけ
ツカモトさん(@tkmts5)の作成された作品の中に、額装されているものがあり、とても美しかったので、自分でもトライしてみようと思ったのがきっかけです。下記ツイートが発端ですが、壁紙の表現とかもうつくしいですよねー。
#creativecoding #generativeart #javascript #illustration #3DCG #二点透視図法 pic.twitter.com/goP2Ncuexh
— ツカモト (@tkmts5) November 14, 2021
使い方
pictureFrame.jsを読み込んだ前提で、飾りたい画像(img(p5.image))を引数にPictureFrameをnewし、描画先のx/y座標を指定してdrawメソッドをcallしてください。現場からは以上です。
const pF = new PictureFrame(img);  
pF.draw(0, 0);
実際の使用例は神奈川沖浪裏 x p5.patternをご覧ください。
細かい使い方
コンストラクタ、メソッド共にOptionalな引数をつけているので、マージン・ベゼルの幅や色、額縁全体のサイズが気に入らない場合はいじることができます。詳しくは下記のコードとコメントをみてみてください。
コード
/*
  Class for Drawing picture frame mounting your image.
  Usage example.
 
    const pF = new PictureFrame(img);  
    pF.draw(0, 0);
  
  Reference: ツカモトsan(@tkmts5)'s tweet https://twitter.com/tkmts5/status/1459877788861620225
*/
class PictureFrame {
  // Syntax
  //   PictureFrame(img, [marginSize], [bezelSize], [bezelColor], [marginColor])
  // Parameters
  //   img: p5.Image: image to be mounted.
  //   marginSize: Number: size of margin. Optional and default value is 80;
  //   marginColor:  p5.Color|gray scale etc... : color of margin Optional and default value is '#f1ece6';
  //   bezelSize: Number: size of bezel. Optional and default value is 20;
  //   bezelColor:  p5.Color|gray scale etc... : color of bezel. Optional and default value is 50(=dark gray);
  constructor(img, marginSize = 80, marginColor = '#f1ece6', bezelSize = 20, bezelColor = 50) {
    this.img = img;
    // Parameters for frame
    this.marginSize = marginSize;
    this.marginColor = marginColor;
    this.bezelSize = bezelSize;
    this.bezelColor = bezelColor;
    // Whole picture frame width/heigth size
    this.width = this.img.width + 2 * this.marginSize;
    this.height = this.img.height + 2 * this.marginSize;
  }
  // Syntax
  //   draw(x, y, [w],[h])
  // Parameters
  //   x: Number: x-coordinate of the frame.
  //   y: Number: y-coordinate of the frame.
  //   w: Number: width of the frame. (Optional) Default value is image width + both margin.
  //   h: Number: height of the frame. (Optional) Default value is image height + both margin.
  draw(x, y, w = this.img.width + 2 * this.marginSize, h = this.img.height + 2 * this.marginSize) {
    push();
    {
      // Draw frame(by stroke!)
      stroke(this.bezelColor);
      strokeWeight(this.bezelSize);
      drawingContext.shadowBlur = 10;
      drawingContext.shadowColor = '#00000055';
      drawingContext.shadowOffsetX = 5;
      drawingContext.shadowOffsetY = 5;
      // Draw margin
      fill(this.marginColor);
      rect(x, y, w, h);
    }
    pop();
    // Mount image.
    const imageWidth = w - 2 * this.marginSize;
    const imageHeight = h - 2 * this.marginSize;
    image(this.img, x + this.marginSize, y + this.marginSize, imageWidth, imageHeight);
  }
}
Gist側も再掲