"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>
Anstatt mit einem Skalar (1d) Wert für die Geschwindigkeit in Kombination mit einer Richtung Überschrift verwendet werden, ist es viel einfacher, wenn Sie einen 2D-Vektor beibehalten . Wenn das erledigt ist, ist es egal, was der Winkel zum Ursprung ist - das spart ein bisschen Trigonometrie. Das heißt - warum versuchen Sie, 180 ° hinzuzufügen, um die Richtung umzukehren? Punktursprung = Vektor vom Ursprung zum Punkt. während Ursprungspunkt = Vektor von Punkt zu Ursprung. Die Verwendung von 2D-Vektoren macht grundlegende Teilchensysteme trivial. – enhzflep
bitte auch den Code für 'Particle' und Beispieldaten für' le' und 'loc' angeben. – trincot
Hey, danke! Der Rest des Codes wurde hinzugefügt. Könnten Sie versuchen, das, was Sie gerade gesagt haben, etwas anders zu formulieren, um es mir leichter zu machen, es zu verstehen? –