ジークアクスのキラキラ空間

canvas-gquuuuuux-kirakira

view source

JavaScript

document.title = 'ジークアクスのキラキラ空間';
//canvas-gquuuuuux-kirakira


let { canvas, ctx, cx, cy, w, h, min, demo } = readyCanvas();



function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);

// グラデーションを描画
function drawBackground() {
  const gradient = ctx.createRadialGradient(
    canvas.width / 2,
    canvas.height / 2,
    0,
    canvas.width / 2,
    canvas.height / 2,
    Math.max(canvas.width, canvas.height)
  );
  gradient.addColorStop(0, 'rgb(255,255,155)'); // 白
  gradient.addColorStop(0.05, 'rgb(240,240,7)'); // 明るい黄色
  gradient.addColorStop(0.1, 'rgb(173,205,215)'); // 明るい緑
  gradient.addColorStop(0.2, 'rgb(44,177,177)'); // 明るい緑
  gradient.addColorStop(0.8, 'rgb(7,69,84)'); // エメラルドグリーン
  gradient.addColorStop(1, 'rgb(9,50,60)'); // エメラルドグリーン

  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
}

function cr() {
  return Math.random() * 10;
}
function randomRGB(r, g, b) {
  const rr = Math.floor(r + cr());
  const gg = Math.floor(g + cr());
  const bb = Math.floor(b + cr());
  return `rgb(${rr}, ${gg}, ${bb})`;
}

// 楕円オブジェクトのクラス
class Circle {
  constructor() {
    this.reset();
  }

  reset() {
    this.t = 0;
    this.x = canvas.width / 2;
    this.y = canvas.height / 2;
    this.angle = Math.random() * 2 * Math.PI;
    this.radius = 0;
    this.small = Math.random() < 1 / 3;

    if (this.small) {
      this.r = Math.random();
      this.radius = this.r * min / 6;
      this.speed = 0.2 + Math.random(); // 少し速めでもOK
      this.width = min / 60;
      this.height = this.width; // 真円
      this.opacity = 0.8;
      this.color = randomRGB(240, 130, 130); // ピンク固定
      this.invalid = false;
      return;
    }

    this.speed = 0.2 + Math.random()*4;
    this.width = min/80 + Math.random() * min/80;
    this.height = min/160 + Math.random() * min/160;
    this.opacity = 0.2 + Math.random() * 0.5;
    const cr = () => Math.random() * 20;
    const colors = [
      'rgba(0,0,0,0)',
      randomRGB(240, 240, 200),
      randomRGB(240, 130, 130),
      randomRGB(20, 230, 210),
      randomRGB(10, 130, 130),
      randomRGB(4, 30, 50),
      'rgba(0,0,0,0)',
    ];
    //this.r = Math.sqrt(Math.random());
    this.r = Math.random();
    const colorIndex = Math.floor(this.r * colors.length);
    this.color = colors[colorIndex];

    // rが大きいほどゆっくり
    this.radius = this.r * min/2;
    this.speed = 0.5 + (0.5 - this.r+0.5) * 2;

    // rが大きいほどサイズが大きく
    this.width = (this.r+0.5) * min / 20 + min / 40 * this.radius/240;

    // rが大きいほど真円に近く(高さ≒幅)
    const roundness = (this.r+0.4) * 0.6; // r=1ならほぼ丸
    this.height = this.width * roundness * this.radius/240;

    // rが大きいほど不透明に
    //this.opacity = 0.3 + this.r * 0.7;

    // 無効なインスタンスとしてマーク
    if (colorIndex === 0 || colorIndex === colors.length) {
      this.invalid = true;
      return;
    } else {
      this.invalid = false;
    }
  }

  update() {
    if (this.invalid) {
      this.reset();
    };
    if (this.small && this.t >= 30) {
      this.reset();
      return;
    }
    this.t++;
    this.radius += this.speed * (1/(this.r*0.5));
    this.x = canvas.width / 2 + Math.cos(this.angle) * this.radius;
    this.y = canvas.height / 2 + Math.sin(this.angle) * this.radius;

    this.width += 1;
    // 範囲外に出たらリセット
    if (
      this.x < -50 || this.x > canvas.width + 50 ||
      this.y < -50 || this.y > canvas.height + 50
    ) {
      this.reset();
    }
  }

  draw(ctx) {
    if (this.invalid) return;
    if(this.t < 2){return;}
    ctx.save();
    ctx.translate(this.x, this.y);
    ctx.rotate(this.angle);
    ctx.globalAlpha = this.opacity;
    ctx.beginPath();
    ctx.ellipse(0, 0, this.width, this.height, 0, 0, Math.PI * 2);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.restore();
  }
}



const circles = Array.from({ length: 320 }, () => new Circle());

function animate() {
  drawBackground();
  circles.sort((a, b) => b.r - a.r);
  for (const c of circles) {
    c.update();
    c.draw(ctx);
  }
  requestAnimationFrame(animate);
}

animate();

CSS

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/game/canvas-gquuuuuux-kirakira/

ABOUT

hi0a.com 「ひまあそび」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

仕様変更、API廃止等、実験途中で動かないページもあります。