【リアイム】


タップ(クリック)で消す



よみこみ中…








閉じる
もくじ

リアイム

アウトプット&知識の共有

Canvasで綺麗なアニメーションを作る方法 まさに芸術!



最後の方に誰でも実行できるエリアがあるので、ぜひ試してみてください!

アニメーションを作ってみる

背景に綺麗なアニメーションを作りたい

そう思って、点と点の間に接続を作り、移動させるプログラムを書いてみた。とても面白かったので、プログラムを共有して、誰でも遊べるようなエリアを作りました。

Canvasの概要

JavaScriptCanvasに点や線、画像などを描画できます。

ゲームを作るときや、複雑なアニメーションを作成するときに最適ですね!

定義の方法はこんな感じ

<canvas id="canvas"></canvas>
<style>
#canvas {
  width: 300px; height: 300px;
  border: 1px solid black;
}
</style>
<script>
  const canvas = document.getElementById("canvas");
  const ctx = canvas.getContext("2d");

  // canvasの大きさ設定
  canvas.width = 600; canvas.height = 600;

  // 四角形の描画
  ctx.fillStyle = "yellow";
  // 点(100, 100)と点(400, 400)に四角形を描画
  ctx.fillRect(100, 100, 400, 400);
</script>


idとか、変数名はcanvasとctxがいいけど、今回は別のところでも使うので、変更してます。

実行結果




プログラム

<canvas id='canvas'></canvas>
<style>
  #canvas { 
    height: 500px;width: 100%;
    background: black;
  }
</style>
<script>
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');

  let Dots = {};
  class TopCanvas {
    constructor() {
      if(canvas.clientHeight > canvas.clientWidth) {
        // 横が2000pxになるように設定
        canvas.width = 2000; canvas.height = canvas.clientHeight * (2000/canvas.clientWidth);
      } else {
        // 縦が2000pxになるように設定
        canvas.height = 2000; canvas.width = canvas.clientWidth * (2000/canvas.clientHeight);
      }
      this.limit = 150;
      this.maxSpeed = 10;

      this.dots = {};
      // 初期生成
      for(var i=0;i<1000;++i) {
        this.GenerateDot();
      }
      // 接続の生成
      for(var id in this.dots) {
        let from = this.dots[id].position;
        for(var target in this.dots) {
          if(id != from) {
            let to = this.dots[target].position;

            let d = Math.sqrt(
              (from[0]-to[0])**2
              +
              (from[1]-to[1])**2
            );

            if(Math.random() <= 1-d/this.limit) {
              this.dots[id].connections.push(
                target
              );
            }
          }
        }
      }
      setInterval(() => {
        // 接続の表示
        ctx.lineWidth = 0.3;

        // 描画
        for(var id in this.dots) {
          ctx.beginPath();
          ctx.strokeStyle = this.dots[id].color;
          // 移動
          this.dots[id].position.forEach((p, i) => {
            this.dots[id].position[i] += this.dots[id].speed[i];
          });

          let from = this.dots[id].position;
          this.dots[id].connections.forEach(target => {
            let to = this.dots[target].position;
            ctx.moveTo(from[0], from[1]);
            ctx.lineTo(to[0], to[1]);
          });
          ctx.stroke();
        }
      }, 100);
    }
    GenerateDot() {
      let id = '0';
      while(
        Object.keys(this.dots).includes(id)
      ) {
        id = String(
          Math.round(Math.random() * 10**8)
        );
      }
      let rgb = [];
      for(var i=0;i<3;++i) {
        rgb.push(
          Math.round(
            Math.random() * 255
          )
        );
      }
      let color = 'rgb('+rgb[0]+','+rgb[1]+','+rgb[2]+')';

      this.dots[id] = {
        color: color,
        position: [Math.random() * canvas.width, Math.random() * canvas.height],
        speed: [(2*Math.random()-1) * this.maxSpeed, (2*Math.random()-1) * this.maxSpeed],
        connections: [] // 相手のid
      };
    }
  }
  let topCanvas;
</script>

<button onclick="canvas.scrollIntoView(true);topCanvas = new TopCanvas();">実行</button>

実行結果




処理が重くなるので、ゆっくり描画にしています…


記事を読んでいただきありがとうございます。
思ったより芸術的な作品ができあがったので驚きました笑
更新時間や線の太さを変更すると違った模様になるかもしれませんね。
これをずっと続けると3Dみたいになることも不思議です。2次元で点が動いているだけなのに…
ちなみに、更新のたびにcanvasをリセットすると綺麗な線だけのアニメーションができます!

【おすすめ記事】

riaimu.hateblo.jp
riaimu.hateblo.jp
riaimu.hateblo.jp





記事の内容に間違いがあった場合は、Twitterもしくはお問い合わせフォームからお伝えください。