はじめに
createPatternという機能がある。
いわゆるループ画像を作るための機能である。いろんな模様を作るのに使える。今回はこれで工字繋ぎを作ろう。
コード全文
main.js
// rectの衝突判定とかいう事故りやすいやり方をやめたいので。
const WIW = window.innerWidth;
const WIH = window.innerHeight;
const DPR = window.devicePixelRatio;
function sketch(){
// DPRを使う場合、ここで指定するのと...
const cvs = document.querySelector('#myCanvas');
cvs.width = WIW*DPR;
cvs.height = WIH*DPR;
cvs.style.width = `${WIW}px`;
cvs.style.height = `${WIH}px`;
const ctx = cvs.getContext('2d');
const u = 12;
const ptn = new OffscreenCanvas(10*u, 12*u);
const ptnCtx = ptn.getContext('2d');
const path = new Path2D();
path.moveTo(0,0);
const pathData = [9,0,9,3,8,3,8,1,5,1,5,10,8,10,8,8,9,8,9,11,0,11,0,8,1,8,1,10,4,10,4,1,1,1,1,3,0,3];
for(let i=0; i<pathData.length; i+=2){
path.lineTo(pathData[i]*u, pathData[i+1]*u);
}
ptnCtx.fillStyle = `rgb(16, 32, 64)`;
ptnCtx.fill(path);
const diffs = [-6,-6,6,-6,-6,6,6,6];
for(let i=0; i<diffs.length; i+=2){
const tf = ptnCtx.getTransform();
ptnCtx.translate(diffs[i]*u, diffs[i+1]*u);
ptnCtx.fill(path);
ptnCtx.setTransform(tf);
}
const kouji_ptn = ctx.createPattern(ptn, 'repeat');
// これならOK!transformを絡めるにはパターン自体のトランスフォームが必要なのだ!
kouji_ptn.setTransform(new DOMMatrix([0.8, -0.4, 0.8, 0.4, 0, 0]));
ctx.fillStyle = `rgb(32, 64, 128)`;
// ここでTFをいじればOK. らくちん。
ctx.setTransform(DPR,0,0,DPR,0,0);
ctx.fillRect(0,0,WIW,WIH);
// ctx.setTransform(0.8, -0.4, 0.8, 0.4, 0, 0); // これだとうまくいかないのだ。切れてしまう。
// まあ当然だ。rectが全体を覆わなくなるから。パターンの方の変形をしてrect描画ではTFをしないようにしなきゃ。
ctx.fillStyle = kouji_ptn;
ctx.fillRect(0,0,WIW,WIH);
}
document.addEventListener("DOMContentLoaded", sketch);
index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>TITLE</title>
<script src="../fisce_beta.js"></script>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<main>
<canvas id="myCanvas"></canvas>
</main>
<script src="main.js"></script>
</body>
</html>
style.css
html {
font-size:62.5%;
}
* {
box-sizing: border-box;
}
body {
margin:0;
}
main{
display:flex;
justify-content:center;
align-items:center;
height:100dvh;
}
結果:
解説
まず、繰り返しのパターンをPath2Dで作る。ひとつひとつはこんな感じの小さいものである。
これはまず中央の「工」の字をPathで作り、それを4つコピーして配置している。この長方形状のパターンを繰り返させる。ただしそのままでは斜めにならないので、トランスフォームを適用する。
const kouji_ptn = ctx.createPattern(ptn, 'repeat');
// これならOK!transformを絡めるにはパターン自体のトランスフォームが必要なのだ!
kouji_ptn.setTransform(new DOMMatrix([0.8, -0.4, 0.8, 0.4, 0, 0]));
canvasPatternオブジェクトにはトランスフォームを設定できる。これとrepeatを組み合わせると、斜めであっても繰り返しのパターンを作ることができる。あとはこれをfillStyleに設定するだけ。
ctx.fillStyle = kouji_ptn;
ctx.fillRect(0,0,WIW,WIH);
なお、今回はdevicePixelRatioを考慮して描画している。スマホなどでは見栄えに影響する可能性があるので。とはいえ事前にスケーリングするだけなので難しくない。
ctx.setTransform(DPR,0,0,DPR,0,0);
以上です。
応用
おわりに
表現の幅が広がりそうですね。ここまでお読みいただいてありがとうございました。


