js实现canvas电流闪电放电动画效果代码
代码语言:html
所属分类:动画
代码描述:js实现canvas电流闪电放电动画效果代码,可调节闪电角度、速度、颜色、厚度及模糊度。
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> body { font-family: sans-serif; padding: 0; margin: 0; background-color: #222; overflow: hidden; -webkit-user-select: none; -moz-user-select: none; -o-user-select: none; -ms-user-select: none; user-select: none; } canvas { position: absolute; top: 0; left: 0; } </style> </head> <body> <canvas id='c'></canvas> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/simplex-noise.min.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/dat.gui-min.js"></script> <script> /** * requestAnimationFrame */ window.requestAnimationFrame = function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); }; }(); /** * Vector */ function Vector(x, y) { this.x = x || 0; this.y = y || 0; } Vector.add = function (a, b) { return new Vector(a.x + b.x, a.y + b.y); }; Vector.sub = function (a, b) { return new Vector(a.x - b.x, a.y - b.y); }; Vector.prototype = { set: function (x, y) { if (typeof x === 'object') { y = x.y; x = x.x; } this.x = x || 0; this.y = y || 0; return this; }, add: function (v) { this.x += v.x; this.y += v.y; return this; }, sub: function (v) { this.x -= v.x; this.y -= v.y; return this; }, scale: function (s) { this.x *= s; this.y *= s; return this; }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y); }, normalize: function () { var len = Math.sqrt(this.x * this.x + this.y * this.y); if (len) { this.x /= len; this.y /= len; } return this; }, angle: function () { return Math.atan2(this.y, this.x); }, distanceTo: function (v) { var dx = v.x - this.x, dy = v.y - this.y; return Math.sqrt(dx * dx + dy * dy); }, distanceToSq: function (v) { var dx = v.x - this.x, dy = v.y - this.y; return dx * dx + dy * dy; }, clone: function () { return new Vector(this.x, this.y); } }; /** * Point */ function Point(x, y, radius) { Vector.call(this, x, y); this.radius = radius || 7; this.vec = new Vector(random(1, -1), random(1, -1)).normalize(); this._easeRadius = this.radius; this._currentRadius = this.radius; } Point.prototype = function (o) { var s = new Vector(0, 0),p; for (p in o) { s[p] = o[p]; } return s; }({ color: 'rgb(255, 255, 255)', dragging: false, _latestDrag: null, update: function (points, bounds) { this._currentRadius = random(this._easeRadius, this._easeRadius * 0.35); this._easeRadius += (this.radius - this._easeRadius) * 0.1; if (this.dragging) return; var vec = this.vec, i,len,p,d; for (i = 0, len = points.length; i < len; i++) { p = points[i]; if (p !== this) { d = this.distanceToSq(p); if (d < 90000) { vec.add(Vector.sub(this, p).normalize().scale(0.03)); } else if (d > 250000) { vec.add(Vector.sub(p, this).normalize().scale(0.015)); } } } if (vec.length() > 3) vec.normalize().scale(3); this.add(vec); if (this.x < bounds.x) { this.x = bounds.x; if (vec.x < 0) vec.x *= -1; } else if (this.x > bounds.right) { this.x = bounds.right; if (vec.x > 0) vec.x *= -1; } if (this.y < bounds.y) { this.y = bounds.y; if (vec.y < 0) vec.y *= -1; } else if (this.y > bounds.bottom) { this.y = bounds.bottom; if (vec.y > 0) vec.y *= -1; } }, hitTest: function (p) { if (this.distanceToSq(p) < 900) { this._easeRadius = this.radius * 2.5; return true; } return false; }, startDrag: function () { this.dragging = true; this.vec.set(0, 0); this._latestDrag = new Vector().set(this); }, drag: function (p) { this._latestDrag.set(this); this.set(p); }, endDrag: function () { this.vec = Vector.sub(this, this._latestDrag); this.dragging = false; }, draw: function (ctx) { ctx.save(); ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.x, this.y, this._currentRadius, 0, Math.PI * 2, false); ctx.fill(); ctx.shadowBlur = 20; ctx.shadowColor = this.color; ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.globalCompositeOperation = 'lighter'; ctx.beginPath(); ctx.arc(this.x, this.y, this._currentRadius, 0, Math.PI * 2, false); ctx.fill(); ctx.restore(); } }); /** * Lightning */ function Lightning(startPoint, endPoint, step) { this.startPoint = startPoint || new Vector(); this.endPoint = endPoint || new Vector(); this.step = step || 45; this.children = []; } Lightning.prototype = { color: 'rgba(255, 255, 255, 1)', speed: 0.025, amplitude: 1, lineWidth: 5, blur: 50, blurColor: 'rgba(255, 255, 255, 0.5)', points: null, off: 0, _simplexNoise: new SimplexNoise(), // Case by child parent: null, startStep: 0, endStep: 0, length: function () { return this.startPoint.distanceTo(this.endPoint); }, getChildNum: function () { return children.length; }, setChildNum: function (num) { var children = this.children,child, i,len; len = this.children.length; if (len > num) { for (i = num; i < len; i++) { children[i].dispose(); } children.splice(num, len - num); } else { for (i = len; i < num; i++) { child = new Lightning(); child._setAsChild(this); children.push(child); } } }, update: function () { var startPoint = this.startPoint, endPoint = this.endPoint, length,normal,radian,sinv,cosv, points,off,waveWidth,n,av,ax,ay,bv,bx,by,m,x,y, children,child, i,len; if (this.parent) { if (this.endStep > this.parent.step) { this._updateStepsByParent(); } startPoint.set(this.parent.points[this.startStep]); endPoint.set(this.parent.points[this.endStep]); } length = this.length(); normal = Vector.sub(endPoint, startPoint).normalize().scale(length / this.step); radian = normal.angle(); sinv = Math.sin(radian); cosv = Math.cos(radian); points = this.points = []; off = this.off += random(this.speed, this.speed * 0.2); waveWidth = (this.parent ? length * 1.5 : length) * this.amplitude; if (waveWidth > 750) waveWidth = 750; for (i = 0, len = this.step + 1; i < len; i++) { n = i / 60; av = waveWidth * this._noise(n - off, 0) * 0.5; ax = sinv * av; ay = cosv * av; bv = waveWidth * this._noise(n + off, 0) * 0.5; .........完整代码请登录后点击上方下载按钮下载查看
网友评论0