链式反射特效
代码语言:html
所属分类:动画
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> chain reaction</title> <style> body { font-family: Arial, Helvetica, "Liberation Sans", FreeSans, sans-serif; background-color: #000; margin: 0; padding: 0; border-width: 0; } </style> </head> <body translate="no"> <script> window.addEventListener("load", function () { const gridStep = 40; // grid step (distance between atoms - center to center) const radiusToStepRatio = 0.3; // radius to step ratio, didn't guess ? < 0.5 const activity = 3; // maximum number of atoms destroyed by one particle const atomRadius = gridStep * radiusToStepRatio; let canv, ctx; // canvas and drawing context for atoms let canvP, ctxP; // canvas and drawing context for particles let maxx, maxy; // canvas size let orgx, orgy; // position of the center of top left atom let nbx, nby; // nb of atoms horiz. / vert. let crystal; // matrix of atoms let explosions; // table of disintegrations to come / in progress let endsOfExplosion; // list of elements to be removed from explosions let requestID; // to cancel animation in progress let lRay; // maximum length for particle path let nbEff = 0; // shortcuts for Math functions const mrandom = Math.random; const mfloor = Math.floor; const mround = Math.round; const mceil = Math.ceil; const mtrunc = Math.trunc; const mabs = Math.abs; const mmin = Math.min; const mmax = Math.max; const mPI = Math.PI; const mPIS2 = Math.PI / 2; const m2PI = Math.PI * 2; const msin = Math.sin; const mcos = Math.cos; const matan2 = Math.atan2; const mhypot = Math.hypot; const msqrt = Math.sqrt; //----------------------------------------------------------------------------- // miscellaneous functions //----------------------------------------------------------------------------- function alea(min, max) { /* random float min..max or 0..min if max is undefined min and max are supposed to be numbers, max (if provided) > min */ if (typeof max == 'undefined') return min * mrandom(); return min + (max - min) * mrandom(); } // alea // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function intAlea(min, max) { /* with 2 parameters : returns random integer min..max - 1 else returns random integer 0..min - 1 min and max are supposed to be integers, max (if provided) > min */ if (typeof max == 'undefined') { max = min; min = 0; } return mfloor(min + (max - min) * mrandom()); } // intAlea // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function distance(p0, p1) { /* distance between two points */ return mhypot(p0[0] - p1[0], p0[1] - p1[1]); } // function distance //------------------------------------------------------------------------ /* class Atom */ function Atom(kx, ky) { this.kx = kx; this.ky = ky; this.x = orgx + kx * gridStep; this.y = orgy + ky * gridStep; this.state = 0; // normal state - till now this.emitted = false; } // Atom // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Atom.prototype.explode = function () { if (this.state != 0) return false; // inform caller explosion already in progress this.state = 1; // new state for atom explosions.push(this); // put atom into animation queue return true; // inform caller this is a new explosion }; // Atom.prototype.explode // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Atom.prototype.draw = function (radius, color, clearBefore) { // use color = undefined && clearBefore = true to completely erase atom if (clearBefore) { ctx.clearRect(this.x - gridStep / 2, this.y - gridStep / 2, gridStep, gridStep); } if (color) { ctx.beginPath(); ctx.fillStyle = color; ctx.arc(this.x, this.y, radius, 0, m2PI); ctx.fill(); } }; // Atom.prototype.draw // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Atom.prototype.drawParticlePath = function (color, thickness, length) { ctxP.beginPath(); ctxP.strokeStyle = color; ctxP.lineWidth = thickness; ctxP.moveTo(this.x, this.y); ctxP.lineTo(this.x + length * this.c, this.y + length * this.s); ctxP.stroke(); }; // Atom.prototype.drawParticlePath // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Atom.prototype.animate = function (time, idx) { /* idx = index of this atom in table 'explosions' May (and will) change between two calls for same Atom. Used to declare end of animation by pushing it onto 'endsOfExplosion'. */ let elapsed, left; switch (this.state) { case 1: // beginning of explosion this.tRef = time; // reference time : start of disintegration this.hue = alea(360); this.color = `hsl(${this.hue}, 100%, 50%)`; this.th = alea(m2PI); // random direction of explosion this.c = mcos(this.th); // cosine and sine of direction this.s = msin(this.th); this.currRadius = 1.5 * atomRadius; if (this.currRadius > gridStep / 2 - 1) this.currRadius = gridStep / 2 - 1; this.duration = alea(800, 1000); this.emitTime = this.tRef + 0.6 * this.duration; this.pathThickness = 3; this.pathLength = lRay; this.pathDuration = alea(300, 500); if (this.emitTime + this.pathDuration < this.tRef + this.duration) { /* be sure this.pathDuration is long enough to last longer than this.duration */ this.pathDuration = this.tRef + this.duration - this.emitTime + 1; // + 1 is ridiculous, but I said longer… } this.pathLum = 80; // % Lightness for path color this.draw(this.currRadius, this.color, true); ++this.state; return; case 2: // atom oscillation - particle path illumination elapsed = time - this.emitTime; // time to emit particle ? if (elapsed > 0) { left = (this.pathDuration - elapsed) / this.pathDuration; this.drawParticlePath(`hsl(${this.hue}, 100% ,${20 + (this.pathLum - 20) * left}%)`, this.pathThickness * left, this.pathLength); if (!this.emitted) { // emission of particle // compute hit atoms this.computeHit(); this.emitted = true; } } // if particle emission in progress elapsed = time - this.tRef; if (elapsed >= this.duration) { this.draw(0, undefined, true); ++this.state; // next step in animation nbEff++; return; } // draw atom in current state left = (this.duration - elapsed) / this.duration; thi.........完整代码请登录后点击上方下载按钮下载查看
网友评论0