このページでは、p5.pave2risoのセットアップから最初の描画までを説明します。
p5.pave2risoを使うには、まずbaku89さんのPave.jsでパスを作る必要があります。
Pave.jsは、ベクターパスをデータとして扱えるようにするライブラリです。p5.jsのellipse()やrect()とは違ってパスをオブジェクトとして持ち、後から変形したり、他のパスと合成したりできます。
Pave.jsについての詳しい解説は、baku89さんによる記事をご覧ください: → Pave.js - baku89.com
p5.riso.jsは、p5.jsでリソグラフの製版用データを作るためのライブラリです。複数の「チャンネル」(インク)を重ねて印刷する仕組みを再現しています。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My 1st p5.pave2riso</title>
<!-- p5.js -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.9.0/lib/p5.js"></script>
<!-- p5.riso.js -->
<script src="https://cdn.jsdelivr.net/gh/antiboredom/p5.riso@master/lib/p5.riso.js"></script>
<!-- p5.pattern.js(パターン塗りを使う場合) -->
<script src="https://cdn.jsdelivr.net/gh/SYM380/p5.pattern@master/p5.pattern.min.js"></script>
</head>
<body>
<!-- ES Modulesとして読み込む -->
<script type="module" src="sketch.js"></script>
</body>
</html>
Pave.jsとlinearlyはES ModulesとしてCDNから直接インポートします。p5.pave2risoは依存性注入(DI)パターンで初期化します:
// sketch.js
// 1. ライブラリをESモジュールとしてインポート
import { Path } from 'https://cdn.jsdelivr.net/npm/@baku89/pave@0.7.1/+esm'
import { vec2 } from 'https://cdn.jsdelivr.net/npm/linearly@0.32.0/+esm'
import { createP5Pave2Riso } from './dist/p5.pave2riso.js'
// 2. 依存性注入でp2rファクトリを作成(グローバル変数不要!)
const { p2r } = createP5Pave2Riso({ Path, vec2 })
let channels = []
let render
window.setup = () => {
createCanvas(800, 600)
pixelDensity(1)
// 3. Risographチャンネルを作成
channels = [
new Riso('red'),
new Riso('blue'),
new Riso('yellow')
]
// 4. p2rファクトリにチャンネルとキャンバスサイズをバインド
render = p2r({
channels,
canvasSize: [width, height]
})
noLoop()
}
window.draw = () => {
background(255)
channels.forEach(ch => ch.clear())
// 5. パスを作成
const circlePath = Path.circle([width / 2, height / 2], 100)
// 6. render()で描画
render({
path: circlePath,
fill: {
type: 'solid',
channelVals: [100, 50, 0] // 赤100%, 青50%, 黄0%
},
mode: 'overprint'
})
// 7. チャンネルを合成して表示
drawRiso()
}
p5.pave2risoでは、createP5Pave2Riso()を使った依存性注入パターンを提供しています。グローバル変数(window.Pathなど)を汚染しないようにしています。
// PathとVec2を明示的に渡す
const { p2r } = createP5Pave2Riso({ Path, vec2 })
ここがp5.pave2risoの核心かもしれません。
リソグラフは「孔版印刷」の一種で、色ごとに別々の「版」を作って重ね刷りします。 そのため、使う色の数だけデータを分けて版を作る必要があります。
channelValsは、各チャンネル(版)にどれだけインクを乗せるかを0-100%で指定する配列です。
たとえば赤、青、黄の3色刷りにする場合、channelsにRED/BLUE/YELLOWのp5.risoオブジェクトを用意した上で下記のように混色を指定できます。
channelVals:[
100, // 赤100%
50, // 青50%
0 // 黄0%
]
p5.riso.jsを直接使う場合、同じ図形を各チャンネルに個別に描画する必要があります。
// チャンネルごとに図形を描画
channel1.fill(createInkDepth(100))
channel1.beginShape()
// ...頂点を列挙...
channel1.endShape(CLOSE)
channel2.fill(createInkDepth(50))
channel2.beginShape()
// ...同じ頂点を列挙...
channel2.endShape(CLOSE)
p5.pave2risoでは、1回の呼び出しで全チャンネルに展開されます。
render({
path: myPath,
fill: {
type: 'solid',
channelVals: [100, 50, 0]
},
mode: 'overprint'
})
図形が複雑になればなるほど、うれしい部分が大きくなるということになります。Pave.jsのパスをそのまま渡せばOKなので、パス操作と版展開がスルッとつながります。
p2r()ファクトリを使わず、pave2Riso()関数を直接呼ぶこともできます:
import { pave2Riso } from './dist/p5.pave2riso.js'
// 毎回すべてのオプションを指定
pave2Riso({
path: circlePath,
fill: {
type: 'solid',
channelVals: [100, 50, 0]
},
mode: 'overprint',
canvasSize: [width, height],
channels: [channel1, channel2, channel3]
})