"use strict";
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
// useful for HtmlCollection, NodeList, String types (array-like objects without the forEach method)
function forEach(array, callback, scope){for (var i=0,n=array.length; i<n; i++)callback.call(scope, array[i], i, array);} // passes back stuff we need
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function vec2_t(x,y)
{
\t this.x=x;
\t this.y=y;
\t this.equals = function(vec2){this.x = vec2.x; this.y = vec2.y;}
\t this.addVec = function(vec2){this.x += vec2.x; this.y += vec2.y;}
\t this.scalarMult = function(scalar){this.x *= scalar; this.y *= scalar;}
\t this.vecLen = function(){return Math.sqrt(this.x*this.x + this.y*this.y);}
\t this.normalize = function(){ let k = 1.0/this.vecLen(); this.scalarMult(k); }
\t this.vecSub = function(vec2){this.x-=vec2.x;this.y-=vec2.y;}
\t this.toString = function(){return"<"+this.x+","+this.y+">"}
\t return this;
}
function part_t(vec2pos, vec2vel, domElem)
{
\t this.pos = vec2pos;
\t this.vel = vec2vel;
\t this.domElem = domElem;
\t return this;
}
var particleArray, timerId;
let explosionOrigin = new vec2_t(156,110);
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
\t particleArray = createPartSys('textInput', 'tgtContainer');
\t byId('stepBtn').addEventListener('click', onStepBtnClick);
\t byId('resetBtn').addEventListener('click', onResetBtnClick);
\t byId('animateBtn').addEventListener('click', onAnimateBtnClick);
\t
\t byId('pauseBtn').addEventListener('click', onPauseBtnClick);
\t
\t byId('tgtContainer').addEventListener('click', onClick);
}
function onStepBtnClick(evt)
{
\t updatePartSys(particleArray);
}
function onAnimateBtnClick(evt)
{
\t timerId = setInterval(function(){updatePartSys(particleArray);}, 100);
\t this.setAttribute('disabled', 'true');
\t byId('pauseBtn').removeAttribute('disabled');
}
function onPauseBtnClick(evt)
{
\t clearInterval(timerId);
\t this.setAttribute('disabled', 'true');
\t byId('animateBtn').removeAttribute('disabled');
}
function onResetBtnClick(evt)
{
\t var bombImg = byId('bomb');
\t byId('tgtContainer').innerHTML = '';
\t byId('tgtContainer').appendChild(bombImg);
\t
\t particleArray = createPartSys('textInput', 'tgtContainer');
\t
\t byId('animateBtn').removeAttribute('disabled');
\t clearInterval(timerId);
}
function createPartSys(srcElemId, tgtElemId)
{
\t let \t elem = byId(srcElemId);
\t var str = elem.value, len=str.length;
\t let result = [];
\t let parent = elem;
\t let curX = elem.offsetLeft - parent.offsetLeft;
\t let curY = elem.offsetTop - parent.offsetTop;
\t let bombImg = byId('bomb');
\t bombImg.style = 'position: absolute';
\t bombImg.style.left = (explosionOrigin.x - (bombImg.clientWidth/2))+'px';
\t bombImg.style.top = (explosionOrigin.y - (bombImg.clientHeight/2))+'px';
\t byId(tgtElemId).appendChild(bombImg);
\t \t
\t curY = 50;
\t curX = 50;
\t forEach(str,
\t \t \t function(letter)
\t \t \t {
\t \t \t \t var span = newEl('span');
\t \t \t \t span.className = 'particle';
\t \t \t \t if (letter == ' ') letter = ' '
\t \t \t \t let h1 = newEl('h1');
\t \t \t \t h1.innerHTML = letter;
\t \t \t \t span.appendChild(h1);
\t \t \t \t span.style.left = curX + 'px';
\t \t \t \t span.style.top = curY + 'px';
\t \t \t \t byId(tgtElemId).appendChild(span);
\t \t \t \t
\t \t \t \t var pos = new vec2_t(curX,curY);
\t \t \t \t
\t \t \t \t curX += span.offsetWidth;
\t \t \t \t var vel = new vec2_t(0,0);
\t \t \t \t
\t \t \t \t let letterOrigin = getCenter(span);
\t \t \t \t
\t \t \t \t vel.equals(letterOrigin);
\t \t \t \t vel.vecSub(explosionOrigin);
\t \t \t \t vel.normalize();
\t \t \t // \t vel.scalarMult((Math.random()*1) + 4);
\t \t \t \t vel.scalarMult(10);
\t \t \t \t
\t \t \t \t var newPart = new part_t(pos,vel,span);
\t \t \t \t result.push(newPart);
\t \t \t }
\t \t);
\t return result;
}
function updatePartSys(partSys)
{
\t forEach(
\t \t \t partSys,
\t \t \t function(part, index, array)
\t \t \t {
\t \t \t \t part.pos.addVec(part.vel); \t \t \t \t \t \t // position += velocity
\t \t \t \t var gravity = new vec2_t(0,0.98/3); \t \t \t \t // arbitrary value chosen
\t \t \t \t part.vel.scalarMult(0.95); \t \t \t \t \t \t // velocity *= 0.95 \t - needs to be quite high. it simulates wind resistance
\t \t \t \t part.vel.addVec(gravity); \t \t \t \t \t \t // velocity += gravity
\t \t \t \t part.domElem.style.left = part.pos.x + "px";
\t \t \t \t part.domElem.style.top = part.pos.y + "px";
\t \t \t }
\t \t);
}
function onClick(evt)
{
\t let elemRect = byId('tgtContainer').getBoundingClientRect();
\t let posX = evt.clientX - elemRect.left, posY = evt.clientY-elemRect.top;
\t explosionOrigin.x = posX;
\t explosionOrigin.y = posY;
\t onResetBtnClick();
}
function getCenter(elem)
{
\t let x = elem.offsetLeft + (elem.offsetWidth/2);
\t let y = elem.offsetTop + (elem.offsetHeight/2);
\t let result = new vec2_t(x,y);
\t return result;
}
#tgtContainer
{
\t position: relative;
\t height: 256px;
\t width: 512px;
\t border: solid 1px black;
\t overflow: hidden;
\t background-color: white;
}
.particle
{
\t display: inline-block;
\t position: absolute;
}
.panel
{
\t display: inline-block;
\t border: solid 1px #113;
\t border-radius: 8px;
\t margin: 8px;
\t padding: 8px;
\t background-image: url(https://www.gravatar.com/avatar/97c2d181ef6bbb9eee0c4033561c3891?s=48&d=identicon&r=PG);
\t background-size: 100% 100%;
}
#textContainer
{
\t display: block;
}
#textContainer textarea
{
\t width: 100%;
\t padding: 0;
\t margin: 1px 0px;
}
<div class='panel'>
\t \t <div id='textContainer'><textarea id='textInput'>click to set bomb position</textarea></div>
\t \t <hr>
\t \t <button id='resetBtn'>Reset</button><button id='stepBtn'>Single Step</button> | <button id='animateBtn'>Animate</button><button id='pauseBtn' disabled>Pause</button>
\t \t <hr>
\t \t <div id='tgtContainer'>
\t \t </div>
\t </div>
\t <svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" id='bomb'>
\t \t <g transform="translate(0,-1020.3622)">
\t \t \t <path d="m23.23,15.84a10.55,10.55,0,1,1,-21.11,0,10.55,10.55,0,1,1,21.11,0z" transform="matrix(1.1875635,0,0,1.1875635,0.68612298,1020.367)" fill="#26201e"/>
\t \t \t <path d="m23.23,15.84a10.55,10.55,0,1,1,-21.11,0,10.55,10.55,0,1,1,21.11,0z" transform="matrix(0.86603158,0,0,0.86603158,2.4299747,1024.1874)" fill="#333"/>
\t \t \t <path d="m-13.04,19.32a1.964,1.964,0,1,1,-3.929,0,1.964,1.964,0,1,1,3.929,0z" transform="matrix(1.924285,1.1058108,-1.1908732,2.0723069,62.314757,1012.6494)" fill="#CCC"/>
\t \t \t <path d="m15.69,1026c0.02518-5.037,7.647-7.396,8.907-2.969,0.7936,2.761,1.349,5.666,4.877,6.786" stroke="#888" stroke-width="1.5px" fill="none"/>
\t \t \t <rect height="2.399" width="4.798" y="1026" x="13.31" stroke-width="0" fill="#26201e"/>
\t \t \t <path fill="#F00" transform="translate(2.0203051,1022.13)" d="M29.8,10.53,27.1,9.62,24.82,11.32,24.86,8.477,22.54,6.833,25.25,5.989,26.1,3.271,27.74,5.595,30.59,5.558,28.89,7.839z"/>
\t \t </g>
\t </svg>
ではなくスカラー(1D)方向の見出しとの組み合わせでの速度の値を使用してを使用する必要がありますが、2Dベクトルを維持するならば、それははるかに簡単です。もし完了すれば、あなたは角度が原点に戻っているかどうか気にしないので、少しの三角法を保存します。それは言った - なぜ方向を逆に180°を追加しようとしているのですか? Point-Origin =原点から点へのベクトル。原点=点から原点へのベクトルです。 2Dベクトルを使用すると、基本的なパーティクルシステムが簡単になります。 – enhzflep
'粒子 'のコードと' le'と 'loc'のサンプルデータも提供してください。 – trincot
ねえ、ありがとう!残りのコードを追加しました。私が理解しやすくするためにちょっと言ったことを言い換えることができますか? –