久しぶりにARっぽいものを作りたくなりまして…
ARっていろいろ難しいことをやってる感じですが 背景がカメラ映像だと十分ARっぽいし その手前にエフェクトを表示するレイヤーを置いて そのまた手前に3Dオブジェクトを置いたら何だか楽しそう じゃないですか?
こういう仕組みは思いつくのですが 実際これをどうコードで書いたらいいのか分からず…困った時のGemini先生
何度か質問を繰り返して Gemini先生が考えてくれたHTMLとJavaScriptがこちら
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v6.1.1/dist/aframe-extras.min.js"></script> <script src="https://unpkg.com/aframe-particle-system-component@1.0.x/dist/aframe-particle-system-component.min.js"></script> <style> /* すべての要素を画面全体に固定 */ #camera-view, #effect-container, #aframe-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; } /* 1. 一番奥:カメラ映像 */ #camera-view { object-fit: cover; z-index: 1; } /* 2. 真ん中:エフェクト */ #effect-container { position: fixed; left: 0; width: 100%; height: 80%; /* 高さを画面の80%に */ top: auto; /* topの固定を解除 */ bottom: 0; /* 画面の一番下に配置 */ background-color: transparent; z-index: 2; pointer-events: none; /* エフェクト越しにA-Frameをクリックできるようにする */ } canvas { display: block; width: 100%; height: 100%; } /* 3. 一番手前:A-Frameの3Dオブジェクト */ #aframe-container { z-index: 3; } </style> </head> <body> <video id="camera-view" autoplay playsinline muted></video> <div id="effect-container"></div> <div id="aframe-container"> <a-scene embedded xr-mode-ui="enabled: false" renderer="alpha: true;"> <a-assets> <a-asset-item id="unity-chan" src="unity-chanのURL" ></a-asset-item> </a-assets> <a-entity animation-mixer gltf-model="#unity-chan" position="0 0 -3" scale="1.5 1.5 1.5" ></a-entity> </a-scene> </div> <script defer type="module"> // 1. エフェクトの起動 import { Fireworks } from "https://cdn.skypack.dev/fireworks-js"; const container = document.getElementById("effect-container"); const fireworks = new Fireworks(container, { // 背景を透明にするための設定(花火ライブラリ側の背景をクリアにする) background: "transparent", }); fireworks.start(); // 2. スマホの背面カメラを起動してvideoタグに流す const video = document.getElementById("camera-view"); if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { // 背面カメラ(environment)を指定 navigator.mediaDevices .getUserMedia({ video: { facingMode: "environment" }, audio: false, }) .then((stream) => { video.srcObject = stream; }) .catch((error) => { console.error("カメラの起動に敗しました:", error); }); } </script> </body> </html>
スマホでWebページを開くと

エフェクトはFireworksという既存のものを使いました
この部分(scriptの1.エフェクトの起動の箇所)を以下のように変更すると
const container = document.getElementById("effect-container"); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); container.appendChild(canvas); // 画面サイズにCanvasを合わせる function resizeCanvas() { canvas.width = container.clientWidth; canvas.height = container.clientHeight; } resizeCanvas(); window.addEventListener("resize", resizeCanvas); const particles = []; // パーティクルクラスの定義 class Particle { constructor(x, y) { this.x = x; this.y = y; // 上方向(画面下部から上)への初速 this.radius = Math.random() * 10 + 5; this.vx = (Math.random() - 0.5) * 2; this.vy = -Math.random() * 4 - 2; this.alpha = 1; this.color = `hsl(${Math.random() * 360}, 100%, 60%)`; // ランダムな色 } update() { this.x += this.vx; this.y += this.vy; this.vy += 0.05; // 擬似的な重力 this.alpha -= 0.01; // 徐々に透明にする } draw() { ctx.save(); ctx.globalAlpha = this.alpha; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = this.color; ctx.fill(); ctx.restore(); } } // アニメーションループ function animate() { // 軌跡を残さず透明にクリア ctx.clearRect(0, 0, canvas.width, canvas.height); // 一定確率で画面下部から新しいパーティクルを生成 if (Math.random() < 0.3) { // 画面の横幅ランダム、高さは一番下(Canvasの最下部) particles.push( new Particle(Math.random() * canvas.width, canvas.height) ); } // パーティクルの更新と描画 for (let i = particles.length - 1; i >= 0; i--) { const p = particles[i]; p.update(); p.draw(); // 透明になったら配列から削除 if (p.alpha <= 0) { particles.splice(i, 1); } } requestAnimationFrame(animate); } // アニメーション開始 animate();

球が噴き上がるようなエフェクトになります
ちなみに このスクリプトもGemini先生が考えてくれました
エフェクト部分や3Dオブジェクト部分を変更するだけでARっぽい画像がいろいろできますね
応用できそう(嬉)
それにしてもGemini先生優秀です 頼りになります