const contents = [
{
html: `
<div class="content-style">
<h2 class="neon-text">MidoriPhotArt</h2>
<p class="fade-in-text">ようこそ、私のデジタルアートギャラリーへ。</p>
<img src="images/texture1.jpg" width="250" class="image-style glow-image">
<p class="paragraph-style slide-in-text">ここでは、日本の伝統工芸「組子」をモチーフにしたデジタルアートを展示しています。</p>
<p class="paragraph-style zoom-in-text">組子の幾何学模様の美しさと、デジタル技術を融合させた作品をお楽しみください。</p>
<button class="button-style pulse-button" onclick="alert('ギャラリーへようこそ!')">ギャラリーに入る</button>
<script>
console.log('このスクリプトは実行されます!');
// ここにJavaScriptコードを追加できます。
// 例:document.getElementById('myElement').addEventListener('click', function() { alert('要素がクリックされました!'); });
</script>
</div>
<style>
.content-style {
color: white;
font-size: 18px;
text-align: center;
perspective: 1000px; /* 3D効果のための視点を設定 */
}
.neon-text {
animation: neon 2s infinite alternate;
text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #ff00de, 0 0 70px #ff00de, 0 0 80px #ff00de, 0 0 100px #ff00de, 0 0 150px #ff00de;
}
.fade-in-text {
animation: fadeIn 3s ease-out;
}
.image-style {
margin-top: 10px;
transition: transform 0.5s ease; /* トランジション効果を追加 */
}
.image-style:hover {
transform: scale(1.1) rotate(5deg); /* ホバー時に拡大と回転 */
}
.glow-image {
animation: glow 2s infinite alternate;
}
.paragraph-style {
margin-top: 10px;
transform-style: preserve-3d; /* 子要素に3D変換を適用 */
}
.slide-in-text {
animation: slideIn 3s ease-out;
transform: translateZ(50px); /* Z軸方向に移動 */
}
.zoom-in-text {
animation: zoomIn 3s ease-out;
transform: translateZ(50px); /* Z軸方向に移動 */
}
.button-style {
margin-top: 10px;
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
transition: transform 0.3s ease; /* トランジション効果を追加 */
}
.button-style:hover {
transform: scale(1.1); /* ホバー時に拡大 */
}
.pulse-button {
animation: pulse 2s infinite;
}
@keyframes neon {
to {
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #00ff00, 0 0 35px #00ff00, 0 0 40px #00ff00, 0 0 50px #00ff00, 0 0 75px #00ff00;
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes glow {
to {
box-shadow: 0 0 20px #fff, 0 0 30px #0000ff, 0 0 40px #0000ff, 0 0 50px #0000ff, 0 0 60px #0000ff, 0 0 70px #0000ff, 0 0 80px #0000ff;
}
}
@keyframes slideIn {
from { transform: translateX(-100%) rotateY(-30deg); opacity: 0; }
to { transform: translateX(0) rotateY(0); opacity: 1; }
}
@keyframes zoomIn {
from { transform: scale(0.5); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
@keyframes pulse {
to {
box-shadow: 0 0 0 10px rgba(255, 255, 255, 0);
}
}
</style>
`,
x: 0, y: 0, z: -500, width: 300, height: 400,
options: { rotationY: 0 }
},
{
// CSSの表現を変更し、表、グラフ、SVG図をコードで生成
html: `
<div class="content-style">
<h2 class="data-title">日本の伝統工芸データ</h2>
<div id="clock" class="clock-style"></div>
<table class="data-table">
<thead>
<tr>
<th>工芸名</th>
<th>特徴</th>
<th>歴史</th>
</tr>
</thead>
<tbody>
<tr>
<td>組子細工</td>
<td>釘を使わずに木を組み付ける</td>
<td>飛鳥時代から</td>
</tr>
<tr>
<td>陶磁器</td>
<td>土を焼いて作る器</td>
<td>縄文時代から</td>
</tr>
<tr>
<td>漆器</td>
<td>漆を塗って作る器</td>
<td>縄文時代から</td>
</tr>
</tbody>
</table>
<div class="chart-container">
<svg class="bar-chart" width="400" height="300"></svg>
</div>
<div class="svg-container">
<svg width="300" height="200">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
<rect width="150" height="100" x="100" y="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
</div>
<button class="data-button" onclick="alert('データ詳細!')">詳細データ</button>
</div>
<style>
.content-style {
color: white;
font-size: 18px;
text-align: center;
background: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
}
.data-title {
margin-bottom: 20px;
font-size: 24px;
}
.clock-style {
font-size: 20px;
margin-bottom: 20px;
}
.data-table {
width: 100%;
margin-bottom: 20px;
border-collapse: collapse;
}
.data-table th, .data-table td {
border: 1px solid white;
padding: 10px;
}
.chart-container {
width: 100%;
height: 300px;
margin-bottom: 20px;
}
.bar-chart {
width: 100%;
height: 100%;
}
.svg-container {
width: 100%;
margin-bottom: 20px;
}
.data-button {
background-color: #008CBA;
color: white;
padding: 15px 30px;
border: none;
cursor: pointer;
border-radius: 5px;
}
</style>
<script>
// D3.js ライブラリの読み込み
<script src="https://d3js.org/d3.v7.min.js"></script>
// 時計の更新関数
function updateClock() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
const timeString = \`\${hours}:\${minutes}:\${seconds}\`;
// document.getElementById('clock') の代わりに object.element.querySelector('#clock') を使用
object.element.querySelector('#clock').innerText = timeString;
}
// 時計の初期化
updateClock();
setInterval(updateClock, 1000);
// グラフデータの例
const chartData = [
{ label: '組子細工', value: 30 },
{ label: '陶磁器', value: 50 },
{ label: '漆器', value: 20 }
];
// 棒グラフの生成
const svg = d3.select(".bar-chart");
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = +svg.attr("width") - margin.left - margin.right;
const height = +svg.attr("height") - margin.top - margin.bottom;
const g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
const x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1)
.domain(chartData.map(d => d.label));
const y = d3.scaleLinear()
.rangeRound([height, 0])
.domain([0, d3.max(chartData, d => d.value)]);
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.call(d3.axisLeft(y))
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("text-anchor", "end")
.text("Value");
g.selectAll(".bar")
.data(chartData)
.enter().append("rect")
.attr("class", "bar")
.attr("x", d => x(d.label))
.attr("y", d => y(d.value))
.attr("width", x.bandwidth())
.attr("height", d => height - y(d.value))
.attr("fill", "steelblue");
</script>
`,
x: 0, y: 0, z: -200, width: 100, height: 100,
options: { rotationY: 0 }
}
];
Three.jsのCSS3DRendererを使用すると、HTML要素を3D空間内に配置できます。 まず、CSS3DRendererを初期化し、サイズを設定します。 このレンダラーは、通常のWebGLRendererと併用して、3Dシーン内にHTML要素をレンダリングします。
// CSS3D レンダラーの設定
css3dRenderer = new CSS3DRenderer();
css3dRenderer.setSize(window.innerWidth, window.innerHeight);
css3dRenderer.domElement.style.position = 'absolute';
css3dRenderer.domElement.style.top = 0;
css3dRenderer.domElement.style.pointerEvents = 'none';
document.getElementById('threeContainer').appendChild(css3dRenderer.domElement);
用意したHTMLコンテンツを、CSS3DObjectに変換します。 これにより、HTML要素がThree.jsのシーン内で3Dオブジェクトとして扱えるようになります。 各コンテンツに対して、位置(x, y, z)、サイズ(width, height)、回転(rotationY)などのオプションを設定できます。
// HTMLコンテンツを3Dオブジェクトに変換する関数
function create3DObject(html, x, y, z, width, height, options) {
// div要素を作成し、HTMLコンテンツを格納
const div = document.createElement('div');
div.innerHTML = html;
div.style.width = \`\${width}px\`;
div.style.height = \`\${height}px\`;
div.style.opacity = 0.8; // 透明度を設定
div.style.background = 'rgba(0, 0, 0, 0.5)'; // 背景色を設定
div.style.border = '1px solid white'; // 枠線を設定
div.style.overflow = 'hidden'; // コンテンツがはみ出さないように設定
// CSS3DObjectを作成
const object = new CSS3DObject(div);
object.position.set(x, y, z);
object.rotation.y = options.rotationY;
// シーンに追加
scene.add(object);
}
作成した3Dオブジェクトは、Three.jsのアニメーションループ内で更新できます。 例えば、オブジェクトを回転させたり、マウスの動きに反応させたりすることができます。 また、HTML要素内のJavaScriptコードも実行されるため、通常のWebページと同様にインタラクティブな要素を追加することも可能です。
以下は、HTML要素を3D空間に配置する完全なソースコードです。
import * as THREE from 'three';
// Controls
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { DragControls } from 'three/addons/controls/DragControls.js';
// Loaders
import { TextureLoader } from 'three';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
import { EXRLoader } from 'three/addons/loaders/EXRLoader.js';
// CSS3DRenderer
import { CSS3DRenderer, CSS3DObject } from 'three/addons/renderers/CSS3DRenderer.js';
// Utils
import { GUI } from 'dat.gui';
import Stats from 'three/addons/libs/stats.module.js';
import { PMREMGenerator } from 'three';
let scene, camera, renderer, controls, stats, css3dRenderer;
// パーティクルエフェクトを生成する関数
// パーティクルエフェクトを生成する関数
// パーティクルエフェクトを生成し、アニメーションさせる関数
// パーティクルエフェクトを生成し、アニメーションさせる関数
function createParticleEffect() {
const particlesGeometry = new THREE.BufferGeometry();
const particlesCnt = 30000; // パーティクルの数を増やす
const posArray = new Float32Array(particlesCnt * 3);
const colors = new Float32Array(particlesCnt * 3);
const sizes = new Float32Array(particlesCnt);
for (let i = 0; i < particlesCnt; i++) {
// 位置を宇宙空間のように広範囲にランダムに設定
posArray[i * 3] = (Math.random() - 0.5) * 8000;
posArray[i * 3 + 1] = (Math.random() - 0.5) * 8000;
posArray[i * 3 + 2] = (Math.random() - 0.5) * 8000;
// 色を青白く、星のような色合いに設定
const color = new THREE.Color();
if (Math.random() > 0.8) {
// 明るい星
color.setHSL(0.6, 0.8, 0.9);
} else {
// 暗い星
...
// HTMLコンテンツを3D空間に追加する関数
function addHTMLContentTo3DSpace() {
// サンプルコンテンツの配列
const contents = [
{
html: `
<div class="content-style">
<h2 class="neon-text">MidoriPhotArt</h2>
<p class="fade-in-text">ようこそ、私のデジタルアートギャラリーへ。</p>
<img src="images/texture1.jpg" width="250" class="image-style glow-image">
<p class="paragraph-style slide-in-text">ここでは、日本の伝統工芸「組子」をモチーフにしたデジタルアートを展示しています。</p>
<p class="paragraph-style zoom-in-text">組子の幾何学模様の美しさと、デジタル技術を融合させた作品をお楽しみください。</p>
<button class="button-style pulse-button" onclick="alert('ギャラリーへようこそ!')">ギャラリーに入る</button>
<script>
console.log('このスクリプトは実行されます!');
// ここにJavaScriptコードを追加できます。
// 例:document.getElementById('myElement').addEventListener('click', function() { alert('要素がクリックされました!'); });
</script>
</div>
<style>
.content-style {
color: white;
font-size: 18px;
text-align: center;
perspective: 1000px; /* 3D効果のための視点を設定 */
}
.neon-text {
animation: neon 2s infinite alternate;
text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #ff00de, 0 0 70px #ff00de, 0 0 80px #ff00de, 0 0 100px #ff00de, 0 0 150px #ff00de;
}
.fade-in-text {
animation: fadeIn 3s ease-out;
}
.image-style {
margin-top: 10px;
transition: transform 0.5s ease; /* トランジション効果を追加 */
}
.image-style:hover {
transform: scale(1.1) rotate(5deg); /* ホバー時に拡大と回転 */
}
.glow-image {
animation: glow 2s infinite alternate;
}
.paragraph-style {
margin-top: 10px;
transform-style: preserve-3d; /* 子要素に3D変換を適用 */
}
.slide-in-text {
animation: slideIn 3s ease-out;
transform: translateZ(50px); /* Z軸方向に移動 */
}
.zoom-in-text {
animation: zoomIn 3s ease-out;
transform: translateZ(50px); /* Z軸方向に移動 */
}
.button-style {
margin-top: 10px;
background-color: #4CAF50;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
transition: transform 0.3s ease; /* トランジション効果を追加 */
}
.button-style:hover {
transform: scale(1.1); /* ホバー時に拡大 */
}
.pulse-button {
animation: pulse 2s infinite;
}
@keyframes neon {
to {
text-shadow: 0 0 5px #fff, 0 0 10px #fff, 0 0 15px #fff, 0 0 20px #00ff00, 0 0 35px #00ff00, 0 0 40px #00ff00, 0 0 50px #00ff00, 0 0 75px #00ff00;
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes glow {
to {
box-shadow: 0 0 20px #fff, 0 0 30px #0000ff, 0 0 40px #0000ff, 0 0 50px #0000ff, 0 0 60px #0000ff, 0 0 70px #0000ff, 0 0 80px #0000ff;
}
}
@keyframes slideIn {
from { transform: translateX(-100%) rotateY(-30deg); opacity: 0; }
to { transform: translateX(0) rotateY(0); opacity: 1; }
}
@keyframes zoomIn {
from { transform: scale(0.5); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}
@keyframes pulse {
to {
box-shadow: 0 0 0 10px rgba(255, 255, 255, 0);
}
}
</style>
`,
x: 0, y: 0, z: -500, width: 300, height: 400,
options: { rotationY: 0 }
},
{
// CSSの表現を変更し、表、グラフ、SVG図をコードで生成
html: `
<div class="content-style">
<h2 class="data-title">日本の伝統工芸データ</h2>
<div id="clock" class="clock-style"></div>
<table class="data-table">
<thead>
<tr>
<th>工芸名</th>
<th>特徴</th>
<th>歴史</th>
</tr>
</thead>
<tbody>
<tr>
<td>組子細工</td>
<td>釘を使わずに木を組み付ける</td>
<td>飛鳥時代から</td>
</tr>
<tr>
<td>陶磁器</td>
<td>土を焼いて作る器</td>
<td>縄文時代から</td>
</tr>
<tr>
<td>漆器</td>
<td>漆を塗って作る器</td>
<td>縄文時代から</td>
</tr>
</tbody>
</table>
<div class="chart-container">
<svg class="bar-chart" width="400" height="300"></svg>
</div>
<div class="svg-container">
<svg width="300" height="200">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
<rect width="150" height="100" x="100" y="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
</div>
<button class="data-button" onclick="alert('データ詳細!')">詳細データ</button>
</div>
<style>
.content-style {
color: white;
font-size: 18px;
text-align: center;
background: rgba(0, 0, 0, 0.5);
padding: 20px;
border-radius: 10px;
}
.data-title {
margin-bottom: 20px;
font-size: 24px;
}
.clock-style {
font-size: 20px;
margin-bottom: 20px;
}
.data-table {
width: 100%;
margin-bottom: 20px;
border-collapse: collapse;
}
.data-table th, .data-table td {
border: 1px solid white;
padding: 10px;
}
.chart-container {
width: 100%;
height: 300px;
margin-bottom: 20px;
}
.bar-chart {
width: 100%;
height: 100%;
}
.svg-container {
width: 100%;
margin-bottom: 20px;
}
.data-button {
background-color: #008CBA;
color: white;
padding: 15px 30px;
border: none;
cursor: pointer;
border-radius: 5px;
}
</style>
<script>
// D3.js ライブラリの読み込み
<script src="https://d3js.org/d3.v7.min.js"></script>
// 時計の更新関数
function updateClock() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const seconds = now.getSeconds().toString().padStart(2, '0');
const timeString = \`\${hours}:\${minutes}:\${seconds}\`;
// document.getElementById('clock') の代わりに object.element.querySelector('#clock') を使用
object.element.querySelector('#clock').innerText = timeString;
}
// 時計の初期化
updateClock();
setInterval(updateClock, 1000);
// グラフデータの例
const chartData = [
{ label: '組子細工', value: 30 },
{ label: '陶磁器', value: 50 },
{ label: '漆器', value: 20 }
];
// 棒グラフの生成
const fireParams = {
speed: 1.5, // 炎の動きの速度
intensity: 0.3, // 炎の明るさ
scale: 2.5, // 炎の全体的なサイズ
density: 1.2, // 炎の密度
turbulence: 1.4, // 炎のゆらぎの強さ
flameHeight: 1.3, // 炎の高さ
colorIntensity: 1.5, // 炎の色の鮮やかさ
volumetricLayers: 48, // 炎の3D表現のためのレイヤー数
coneAngle: 25 // 炎の広がり角度
};
// GUIコントロールの初期化
const gui = new dat.GUI();
gui.domElement.style.opacity = "0.8";
// パラメータの追加
gui.add(fireParams, 'speed', 0, 3).name('炎の速度');
gui.add(fireParams, 'intensity', 0, 1).name('明るさ');
gui.add(fireParams, 'scale', 0.5, 5).name('サイズ');
gui.add(fireParams, 'density', 0.5, 2).name('密度');
gui.add(fireParams, 'turbulence', 0, 3).name('ゆらぎ');
// フラグメントシェーダー
uniform float time;
uniform float intensity;
uniform float turbulence;
varying vec2 vUv;
void main() {
// ノイズ関数による揺らぎの生成
float noise = snoise(vec3(vUv * 4.0, time));
// グラデーションの計算
vec3 color = mix(
vec3(1.0, 0.5, 0.0), // オレンジ
vec3(1.0, 0.8, 0.0), // 黄色
noise * turbulence
);
// 透明度の計算
float alpha = (1.0 - vUv.y) * intensity;
gl_FragColor = vec4(color, alpha);
}
各フレームごとに炎エフェクトを更新し、リアルタイムでダイナミックな動きを実現します。 主な更新内容は以下の通りです:
// 炎エフェクトの更新処理
const updateFire = () => {
// 円錐の半径を計算(角度に基づく)
const radius = Math.sin(fireParams.coneAngle * Math.PI / 180) * 0.5;
// 各レイヤーの更新処理
layers.forEach((layer, index) => {
// 時間経過による動的な変化
layer.material.uniforms.time.value += 0.016; // 約60FPSに相当
// エフェクトパラメータの更新
layer.material.uniforms.speed.value = fireParams.speed; // 炎の速度
layer.material.uniforms.intensity.value = fireParams.intensity; // 炎の強度
// ... その他のパラメータ更新
// 円周上にレイヤーを均等配置
const angle = (index / (fireParams.volumetricLayers - 1)) * Math.PI * 2;
layer.position.x = Math.cos(angle) * radius; // X座標
layer.position.z = Math.sin(angle) * radius; // Z座標
layer.rotation.y = angle; // レイヤーの向き
});
// 全体的なスケールの適用
fireGroup.scale.set(fireParams.scale, fireParams.scale, fireParams.scale);
};
// 炎のマテリアルのパラメータ
const fireParams = {
speed: 1.5, // より自然な動きのスピード
intensity: 0.3, // より明るい炎の強度
scale: 2.5, // より大きなサイズ
density: 1.2, // より密度の高い炎
turbulence: 1.4, // より自然な乱流
flameHeight: 1.3, // より高い炎
colorIntensity: 1.5, // より鮮やかな色
volumetricLayers: 48, // より滑らかな見た目のレイヤー数
coneAngle: 25 // より自然な広がり角度
};
// GUIコントロールの設定
const gui = new GUI({ autoPlace: false });
const fireFolder = gui.addFolder('炎のパラメータ');
fireFolder.add(fireParams, 'speed', 0.1, 3.0).name('速度');
fireFolder.add(fireParams, 'intensity', 0.1, 3.0).name('強度');
// ... その他のGUIパラメータ設定 ...
// GUIコンテナの作成と配置
const guiContainer = document.createElement('div');
guiContainer.style.position = 'absolute';
guiContainer.style.right = '10px';
guiContainer.style.top = '50%';
// ... スタイル設定 ...
// ドラッグ機能の実装
let isDragging = false;
let currentX, currentY, initialX, initialY;
dragHandle.addEventListener('mousedown', (e) => {
isDragging = true;
initialX = e.clientX - guiContainer.offsetLeft;
initialY = e.clientY - guiContainer.offsetTop;
e.preventDefault();
});
// 3D炎エフェクトの作成
const fireGroup = new THREE.Group();
const layers = [];
for(let i = 0; i < fireParams.volumetricLayers; i++) {
const segments = 64;
const planeGeometry = new THREE.PlaneGeometry(1, 4, segments, 128);
// 台形状の変形処理
const positions = planeGeometry.attributes.position.array;
for(let j = 0; j < positions.length; j += 3) {
const y = positions[j + 1];
const widthScale = 1.0 + (y / 4.0) * 0.5;
positions[j] *= widthScale;
}
planeGeometry.attributes.position.needsUpdate = true;
// バーテックスシェーダー
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vUv = uv;
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// フラグメントシェーダー
uniform float time;
uniform float speed;
uniform float intensity;
// ... その他のユニフォーム変数 ...
void main() {
vec2 uv = vUv;
float n = 0.0;
float amplitude = 1.0;
float frequency = 1.0;
// ノイズ生成処理
for(int i = 0; i < 4; i++) {
vec2 noisePos = uv * noiseScale * frequency * density +
vec2(sin(time * speed * 0.1 + layerOffset * 6.28) * turbulence,
-time * speed * (0.5 + float(i) * 0.1));
n += noise(noisePos) * amplitude;
amplitude *= 0.5;
frequency *= 2.0;
}
// 炎の形状と色の計算
float flame = smoothstep(0.1, 0.5, uv.y) *
(1.0 - pow(uv.y, flameHeight)) * 2.0;
flame *= n * intensity;
const updateFire = () => {
const radius = Math.sin(fireParams.coneAngle * Math.PI / 180) * 0.5;
layers.forEach((layer, index) => {
// 時間更新
layer.material.uniforms.time.value += 0.016;
// パラメータ更新
layer.material.uniforms.speed.value = fireParams.speed;
layer.material.uniforms.intensity.value = fireParams.intensity;
// ... その他のパラメータ更新 ...
// 位置更新
const angle = (index / (fireParams.volumetricLayers - 1)) * Math.PI * 2;
layer.position.x = Math.cos(angle) * radius;
layer.position.z = Math.sin(angle) * radius;
layer.rotation.y = angle;
});
fireGroup.scale.set(fireParams.scale, fireParams.scale, fireParams.scale);
};