Lightning Points (Lightning 2)

Size
7,238 Kb
Views
40,480

How do I make an lightning points (lightning 2)?

Http://jsdo.it/akm2/amk0. What is a lightning points (lightning 2)? How do you make a lightning points (lightning 2)? This script and codes were developed by Akimitsu Hamamuro on 13 June 2022, Monday.

Lightning Points (Lightning 2) Previews

Lightning Points (Lightning 2) - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>Lightning Points (Lightning 2)</title> <link rel="stylesheet" href="css/style.css">
</head>
<body> <canvas id='c'></canvas> <script src='https://rawgit.com/akm2/simplex-noise.js/master/simplex-noise.js'></script> <script src="js/index.js"></script>
</body>
</html>

Lightning Points (Lightning 2) - Script Codes CSS Codes

body { font-family: Helvetica 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;
}

Lightning Points (Lightning 2) - Script Codes JS Codes

/** * requestAnimationFrame */
window.requestAnimationFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); };
})();
/** * Lightning */
var Lightning = (function(window) { /** * LightningAbstract */ var LightningAbstract = { points: null, children: null, _simplexNoise: new SimplexNoise(), render: function(ctx, controls) { this._update(controls); this._draw(ctx); }, _update: function(controls) { throw new Error('Not override'); }, _draw: function(ctx) { var points = this.points, isRoot = false, opts, p, p1, dx, dy, dist, lineWidth, i, len; isRoot = !this.parent; opts = isRoot ? this : this.parent; if (isRoot) { // is root var radius, gradient, children = this.children, c; ctx.save(); for (i = 0, len = points.length; i < len; i += len - 1) { p = points[i]; radius = Math.random() * (8 - 3) + 3; gradient = ctx.createRadialGradient(p.x, p.y, radius / 3, p.x, p.y, radius); gradient.addColorStop(0, this._colorToString(1)); gradient.addColorStop(1, this._colorToString(0)); ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); ctx.fill(); } ctx.restore(); for (i = 0, len = children.length; i < len; i += len - 1) { children[i].render(ctx); } } ctx.save(); ctx.globalCompositeOperation = 'lighter'; ctx.lineCap = 'round'; ctx.fillStyle = 'rgba(0, 0, 0, 1)'; ctx.shadowBlur = opts.blur; ctx.shadowColor = this._colorToString(1); ctx.beginPath(); for (i = 0, len = points.length; i < len; i++) { p = points[i]; if (len > 1) { p1 = points[i === len - 1 ? i - 1 : i + 1]; dx = p.x - p1.x; dy = p.y - p1.y; dist = Math.sqrt(dx * dx + dy * dy); } else { dist = 0; } if (dist > 30) dist = 30; ctx.moveTo(p.x + dist, p.y); ctx.arc(p.x, p.y, dist, 0, Math.PI * 2, false); } ctx.fill(); ctx.restore(); ctx.save(); ctx.beginPath(); ctx.strokeStyle = this._colorToString(Math.random() * (opts.maxAlpha - opts.minAlpha) + opts.minAlpha); lineWidth = Math.random() * (opts.maxLineWidth - opts.minLineWidth) + opts.minLineWidth; ctx.lineWidth = isRoot ? lineWidth : lineWidth * 0.5; for (i = 0; i < len; i++) { p = points[i]; ctx[i === 0 ? 'moveTo' : 'lineTo'](p.x, p.y); } ctx.stroke(); ctx.restore(); }, _noise2d: function(x, y) { var octaves = 3, fallout = 0.5, amp = 1, f = 1, sum = 0, i; for (i = 0; i < octaves; ++i) { amp *= fallout; sum += amp * (this._simplexNoise.noise2D(x * f, y * f) + 1) * 0.5; f *= 2; } return sum; }, _filterApply: function(points, lineLength, segmentsNum, base, amp, offset) { var pointsOld = this.points, // spline spline = [], catmullRom = this._catmullRom, p0, p1, p2, p3, t, per, // noise p, next, angle, sin, cos, nx, av, ax, ay, bv, bx, by, m, px, py, // shortest shortest, dx, dy, distSq, minDist, i, len, j, k; // Spline // スプライン補完用に配列の前後にラインの始点, 終点の参照をそれぞれ複製する points.unshift(points[0]); points.push(points[points.length - 1]); per = 1 / segmentsNum; // スプライン曲線のポイントを取得 for (i = 0, len = points.length - 3; i < len; i++) { p0 = points[i]; p1 = points[i + 1]; p2 = points[i + 2]; p3 = points[i + 3]; for (j = 0; j < segmentsNum; j++) { t = (j + 1) * per; spline.push({ x: catmullRom(p0.x, p1.x, p2.x, p3.x, t), y: catmullRom(p0.y, p1.y, p2.y, p3.y, t) }); } } // 補完用に追加した参照を削除 points.pop(); // 削除のついでに描画の始点として追加 spline.unshift(points.shift()); // Noise points = []; len = spline.length; per = 1 / (len - 1); base = 1 / base; for (i = 0, len = spline.length; i < len; i++) { p = spline[i]; next = i === len - 1 ? p : spline[i + 1]; angle = Math.atan2(next.y - p.y, next.x - p.x); sin = Math.sin(angle); cos = Math.cos(angle); nx = i * base; av = lineLength * this._noise2d(nx - offset, offset) * 0.5 * amp; ax = av * sin; ay = av * cos; bv = lineLength * this._noise2d(nx + offset, offset) * 0.5 * amp; bx = bv * sin; by = bv * cos; m = Math.sin(Math.PI * (i * per)); px = p.x + (ax - bx) * m; py = p.y - (ay - by) * m; if (pointsOld.length) { p = pointsOld.shift(); p.x = px; p.y = py; } else { p = { x: px, y: py }; } points.push(p); } // Shortest shortest = [points[0]]; for (i = 0, len = points.length; i < len; i++) { p = points[i]; minDist = Infinity; k = -1; for (j = i; j < len; j++) { p2 = points[j]; dx = p.x - p2.x; dy = p.y - p2.y; distSq = dx * dx + dy * dy; if (p !== p2 && distSq < minDist * minDist) { minDist = Math.sqrt(distSq); k = j; } } if (k < 0) break; shortest.push(points[k]); i = k - 1; } return shortest; }, _catmullRom: function(p0, p1, p2, p3, t) { var v0 = (p2 - p0) * 0.5, v1 = (p3 - p1) * 0.5; return (2 * p1 - 2 * p2 + v0 + v1) * t * t * t + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t * t + v0 * t + p1; }, _colorToString: function(alpha) { var c = this.color; return this.colorType === 'rgb' ? 'rgba(' + c.join(',') + ',' + alpha + ')' : 'hsla(' + c[0] + ',' + c[1] + '%,' + c[2] + '%,' + alpha + ')'; } }; /** * @constructor */ function Lightning(segmentsNum) { this.points = []; this.children = []; this._params = []; this._offsets = []; } Lightning.prototype = extend(LightningAbstract, { color: [255, 255, 255], colorType: 'rgb', blur: 50, maxAlpha: 1, minAlpha: 0.75, maxLineWidth: 5, minLineWidth: 0.5, _params: null, _offsets: null, addParam: function(segmentsNum, base, amplitude, speed) { this._params.push({ segmentsNum: segmentsNum, base: base, amplitude: amplitude, speed: speed }); this._offsets[this._params.length - 1] = 0; }, createChild: function(base, amplitude, speed) { var child = new LChild(this, { base: base || this._params.base, amplitude: amplitude || this._params.amplitude, speed: speed || this._params.speed }); this.children.push(child); return child; }, _update: function(points) { var params = this._params, param, offsets = this._offsets, lineLength, p0, p1, dx, dy, i, ilen, j, jlen; for (i = 0, ilen = params.length; i < ilen; i++) { param = params[i]; lineLength = 0; for (j = 0, jlen = points.length; j < jlen; j++) { if (j !== jlen - 1) { p0 = points[j]; p1 = points[j + 1]; dx = p0.x - p1.x; dy = p0.y - p1.y; lineLength += dx * dx + dy * dy; } } lineLength = Math.sqrt(lineLength); offsets[i] += Math.random() * param.speed; points = this._filterApply(points, lineLength, param.segmentsNum, param.base, param.amplitude, offsets[i]); } this.points = points; } }); /** * LChild */ function LChild(parent, param) { this.parent = parent; this.points = []; this._param = param; } LChild.prototype = extend(LightningAbstract, { parent: null, _startStep: 0, _endStep: 0, _separate: 2, _param: null, _offset: 0, _lastChangeTime: 0, _update: function() { var parent = this.parent, plen = this.parent.points.length, param = this._param, points = [], currentTime, range, rangeLen, sep, seg, c0, c1, dx, dy, lineLength, i, j; // 一定時間ごと, あるいは親のポイントの数が子の終了ステップ位置を下回った場合に始点と終点の親からの取得位置を更新する currentTime = new Date().getTime(); if ( currentTime - this._lastChangeTime > 10000 * Math.random() || plen < this._endStep ) { var stepMin = plen * 0.1 | 0, startStep = this._startStep = (Math.random() * (plen / 3 * 2 | 0) | 0); this._endStep = startStep + stepMin + ((Math.random() * (plen - startStep - stepMin) + 1) | 0); this._lastChangeTime = currentTime; } // 親のポイント配列から取得範囲を切り出す range = parent.points.slice(this._startStep, this._endStep); rangeLen = range.length; // 範囲からスプライン曲線の制御点を取得する seg = (rangeLen - 1) / this._separate; for (i = 0; i <= this._separate; i++) { j = seg * i | 0; points.push(range[j]); } // ノイズの実際の振り幅 c0 = points[0]; c1 = points[points.length - 1]; dx = c0.x - c1.x; dy = c0.y - c1.y; lineLength = Math.sqrt(dx * dx + dy * dy); this._offset += Math.random() * param.speed; this.points = this._filterApply(points, lineLength, rangeLen * 0.5 | 0, param.base, param.amplitude, this._offset); }, _colorToString: function(alpha) { var c = this.parent.color; return this.parent.colorType === 'rgb' ? 'rgba(' + c.join(',') + ',' + alpha + ')' : 'hsla(' + c[0] + ',' + c[1] + '%,' + c[2] + '%,' + alpha + ')'; } }); // Helpers function extend() { var t = {}, o, p, i, len; for (i = 0, len = arguments.length; i < len; i++) { o = arguments[i]; for (p in o) t[p] = o[p]; } return t; } return Lightning;
})(window);
/** * Point */
function Point(x, y, color, colorType) { this.x = x; this.y = y; this.color = color; this.colorType = colorType; this.vx = Math.random() * (3 + 3) - 3; this.vy = Math.random() * (3 + 3) - 3; this._latest = { x: this.x, y: this.y };
}
Point._field = null;
Point.setField = function(x, y, width, height) { Point._field = { x: x, y: y, width: width, height: height, right: x + width, bottom: y + height };
};
Point.prototype = { color: null, colorType: 'rgb', radius: 50, alpha: 0.2, dragging: false, dying: false, dead: false, _mouse: null, _latest: null, _mouseDist: null, _currentAlpha: 0, _currentRadius: 0, lengthSq: function() { return this.x * this.x + this.y * this.y; }, hitTest: function(mouse) { var dx = mouse.x - this.x, dy = mouse.y - this.y; return dx * dx + dy * dy < this.radius * this.radius; }, dragStart: function(mouse) { if (this.hitTest(mouse)) { this._mouse = mouse; this._mouseDist = { x: this.x - mouse.x, y: this.y - mouse.y }; this.dragging = true; } return this.dragging; }, dragEnd: function() { this.dragging = false; this._mouse = this._mouseDist = null; }, kill: function() { this.dying = true; this.radius = 0; }, update: function(mouse) { var field = Point._field, radius = this.radius, vlen, d; if (this._mouse) { this._latest.x = this.x; this._latest.y = this.y; this.x = this._mouse.x + this._mouseDist.x; this.y = this._mouse.y + this._mouseDist.y; this.vx = this.x - this._latest.x; this.vy = this.y - this._latest.y; } else { this.x += this.vx; this.y += this.vy; this.vx *= 0.98; this.vy *= 0.98; } vlen = Math.sqrt(this.vx * this.vx + this.vy * this.vy); if (vlen && vlen > 20) { this.vx /= vlen / 20; this.vy /= vlen / 20; } if (this.x < field.x + radius) { this.x = field.x + radius; if (this.vx < 0) this.vx *= -1; } else if (this.x > field.right - radius) { this.x = field.right - radius; if (this.vx > 0) this.vx *= -1; } if (this.y < field.y + radius) { this.y = field.y + radius; if (this.vy < 0) this.vy *= -1; } else if (this.y > field.bottom - radius) { this.y = field.bottom - radius; if (this.vy > 0) this.vy *= -1; } // Alpha d = this.alpha - this._currentAlpha; if ((d < 0 ? -d : d) > 0.001) this._currentAlpha += d * 0.1; // Radius d = radius - this._currentRadius; if ((d < 0 ? -d : d) > 0.01) { this._currentRadius += d * 0.35; } else if (this.dying) { this.dead = true; } this._currentRadius *= Math.random() * (1 - 0.85) + 0.85; }, draw: function(ctx) { var radius = this._currentRadius; var gradient = ctx.createRadialGradient(this.x, this.y, radius / 3, this.x, this.y, radius); gradient.addColorStop(0, this._colorToString(this._currentAlpha)); gradient.addColorStop(1, this._colorToString(0)); ctx.fillStyle = gradient; ctx.beginPath(); ctx.moveTo(this.x + radius, this.y); ctx.arc(this.x, this.y, radius, 0, Math.PI * 2, false); ctx.fill(); }, _colorToString: function(alpha) { var c = this.color; return this.colorType === 'rgb' ? 'rgba(' + c.join(',') + ',' + alpha + ')' : 'hsla(' + c[0] + ',' + c[1] + '%,' + c[2] + '%,' + alpha + ')'; }
};
(function() { // Configs var DRAG_POINT_NUM = 4, DRAG_POINT_MAX_NUM = 8, CHILD_NUM = 2, LIHTNING_COLOR = [195, 100, 50]; // HSL BACKGROUND_COLOR = 'rgba(0, 15, 20, 0.8)'; // Vars var canvas, context, canvasMinSize, centerX, centerY, points = [], mouse = { x: 0, y: 0 }, lightning, grad, i; // Event Listeners function resize(e) { canvas.width = window.innerWidth; canvas.height = window.innerHeight; context = canvas.getContext('2d'); context.lineCap = 'round'; canvasMinSize = Math.min(canvas.width, canvas.height); centerX = canvas.width * 0.5; centerY = canvas.height * 0.5; grad = context.createLinearGradient(0, 0, 0, canvas.height); grad.addColorStop(0, 'hsla(195, 100%, 50%, 0.08)'); grad.addColorStop(0.5, 'hsla(195, 100%, 50%, 0)'); grad.addColorStop(1, 'hsla(195, 100%, 50%, 0.08)'); Point.setField(0, 0, canvas.width, canvas.height); } function mouseMove(e) { mouse.x = e.clientX; mouse.y = e.clientY; var hit = false, i, len; for (i = 0, len = points.length; i < len; i++) { if (points[i].hitTest(mouse)) { hit = true; break; } } document.body.style.cursor = hit ? 'pointer' : 'default'; } function mouseDown(e) { var i, len; for (i = 0, len = points.length; i < len; i++) { if (points[i].dragStart(mouse)) return; } for (i = 0; i < len; i++) { if (points[i].hitTest(mouse)) { if (len > 1) points.splice(i, 1); return; } } if (len < DRAG_POINT_MAX_NUM) { points.push(createPoint(e.clientX, e.clientY)); } else { for (i = 0; i < len - 2; i++) { points[i].kill(); } } } function mouseUp(e) { for (var i = 0, len = points.length; i < len; i++) { points[i].dragEnd(mouse); } } function doubleClick(e) { var i, len = points.length; if (len < 3) return; for (i = 0; i < len; i++) { if (points[i].hitTest(mouse)) { points[i].kill(); return; } } } // Functions function createPoint(x, y) { return new Point(x, y, LIHTNING_COLOR.slice(), 'hsl'); } // Array sort callback function sortPoints(p1, p2) { return p1.lengthSq() - p2.lengthSq(); } // Init document.body.style.backgroundColor = BACKGROUND_COLOR; canvas = document.getElementById('c'); window.addEventListener('resize', resize, false); resize(null); for (i = 0; i < DRAG_POINT_NUM; i++) { points.push(createPoint(Math.random() * canvasMinSize + centerX - canvasMinSize * 0.5, Math.random() * canvasMinSize + centerY - canvasMinSize * 0.5)); } lightning = new Lightning(); lightning.addParam(8, 10, 0.7, 0.01); // segumentsNum, noiseBase, amplitude, speed lightning.addParam(16, 60, 0.5, 0.03); lightning.colorType = 'hsl'; lightning.color = LIHTNING_COLOR.slice(); for (i = 0; i < CHILD_NUM; i++) { lightning.createChild(80, 0.5, 0.06); // noiseBase, amplitude, speed } canvas.addEventListener('mousemove', mouseMove, false); canvas.addEventListener('mousedown', mouseDown, false); canvas.addEventListener('mouseup', mouseUp, false); canvas.addEventListener('dblclick', doubleClick, false); // Start update var loop = function() { var controls = [], i, len, p; context.save(); context.globalCompositeOperation = 'source-over'; context.fillStyle = BACKGROUND_COLOR; context.fillRect(0, 0, canvas.width, canvas.height); context.fillStyle = grad; context.fillRect(0, 0, canvas.width, canvas.height); context.restore(); context.globalCompositeOperation = 'lighter'; for (i = 0, len = points.length; i < len; i++) { p = points[i]; p.update(); p.alpha = p.hitTest(mouse) ? 0.75 : 0.2; p.draw(context); if (p.dead) { points.splice(i, 1); i--; len--; continue; } if (!p.dying) controls.push(p); } // 原点からの距離でソート controls.sort(sortPoints); lightning.render(context, controls); lightning.color[2] = Math.random() * (100 - 35) + 35; requestAnimationFrame(loop); }; loop();
})();
Lightning Points (Lightning 2) - Script Codes
Lightning Points (Lightning 2) - Script Codes
Home Page Home
Developer Akimitsu Hamamuro
Username akm2
Uploaded June 13, 2022
Rating 4.5
Size 7,238 Kb
Views 40,480
Do you need developer help for Lightning Points (Lightning 2)?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Akimitsu Hamamuro (akm2) Script Codes
Create amazing video scripts with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!