0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

createPatternで工字繋ぎを作る

0
Posted at

はじめに

 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;
}

結果:

wcdqcq2qv.png

解説

 まず、繰り返しのパターンをPath2Dで作る。ひとつひとつはこんな感じの小さいものである。

wrvwwb.png

これはまず中央の「工」の字を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);

以上です。

応用

fish_kouji_5938.png

おわりに

 表現の幅が広がりそうですね。ここまでお読みいただいてありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?