Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
Mechanical Waves & Sound
css
html, body { background: #aaa; height: 100%; width: 100%; } body { -webkit-box-align: center; -ms-flex-align: center; align-items: center; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; margin: 0; } .container { background: #1e202e; border: 2px solid #aaa; -webkit-box-shadow: 0 0 12px #444; box-shadow: 0 0 12px #444; -webkit-box-sizing: border-box; box-sizing: border-box; height: 480px; max-height: 90vh; max-width: 90vh; overflow: hidden; position: relative; width: 480px; } .container canvas { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .container h1 { background: rgba(0, 0, 0, 0.33); bottom: 6px; -webkit-box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.33); box-shadow: 0 0 10px 10px rgba(0, 0, 0, 0.33); color: #fff; display: inline-block; font-family: sans-serif; font-size: 16px; left: 12px; letter-spacing: 3px; margin: 0; pointer-events: none; position: absolute; text-transform: uppercase; width: 100%; z-index: 1; }
JavaScript
// Constants var BACKGROUND_COLOR = '#1e202e'; var FOREGROUND_COLOR = '#5b6b87'; var LINE_WIDTH = 2; var PEAK_AGE = 20; var DECAY_LENGTH_FACTOR = 20; var DECAY_WIDTH_FACTOR = 1 / 25; var SPEED = 1; var WOBBLE_SPEED = 1 / 300; var LINE_SPACING_PX = 8; var NODE_SPACING_PX = 10; var NEIGHBOR_GAP = 3; var AMPLITUDE_PX = 3; var PEAK_HEIGHT_PX = 42; var DEBUG_COLORS = false; // State // Keeping the baseline offset decoupled from `t` lets us transition smoothly // to !isMoving, etc var t = 0; var baselineOffset = 0; var phase = 0; var isMoving = true; var peak = {}; // Simplex noise kicks Perlin noise's butt! Don't let the name fool you :D var simplex = new SimplexNoise(); // DOM things var container = document.querySelector('.container'); var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); var h = canvas.height = container.offsetHeight; var w = canvas.width = container.offsetWidth; container.appendChild(canvas); peak.x = w / 2; peak.y = h / 2; canvas.addEventListener('mousemove', function (e) { return peak = mouseCoords(e); }); canvas.addEventListener('click', function (e) { return isMoving = !isMoving; }); ctx.fillStyle = BACKGROUND_COLOR; ctx.strokeStyle = FOREGROUND_COLOR; ctx.lineWidth = LINE_WIDTH; // Each line is a typed array of node height values. var MAX_INT_16_VALUE = Math.pow(2, Int16Array.BYTES_PER_ELEMENT * 8 - 1) - 1; var numNodes = Math.floor(w / NODE_SPACING_PX) + 1; var numLines = Math.floor(h / LINE_SPACING_PX) + 1 + Math.ceil(PEAK_HEIGHT_PX / LINE_SPACING_PX); var lines = Array.from({ length: numLines }, function () { var buffer = new ArrayBuffer(numNodes * Int16Array.BYTES_PER_ELEMENT); return new Int16Array(buffer); }); // We also record the ages of peak nodes on a line. var linePeaks = Array.from({ length: numLines }, function () { var buffer = new ArrayBuffer(numNodes * Uint16Array.BYTES_PER_ELEMENT); return new Uint16Array(buffer); }); var hTotal = numLines * LINE_SPACING_PX; // Self-executing game loop. Here we go! (function step() { // Line & node index for the center of our bell curve. var peakNode = { x: mod(Math.ceil(peak.x / NODE_SPACING_PX), numNodes), y: mod(Math.ceil(peak.y / LINE_SPACING_PX) + 1, numLines) }; // Clear the last frame ctx.clearRect(0, 0, w, h); if (isMoving) { ++baselineOffset; if (t % LINE_SPACING_PX === 0) { // Whenever a line shifts off the screen's top, we move it to the // front of our array. `phase` keeps track of the array's offset. // We could be more clever about this and keep the array intact, // but this method has the advantage of matching idx to draw order. lines.unshift(lines.pop()); phase = mod(phase + 1, numLines); linePeaks[phase].fill(0); baselineOffset = 0; } } // Draw each line sequentially. A few definitions, before we get into it: // // lineIdx: Loop index. Represents the order things are drawn to the canvas // in, which means it holds a steady y position on the canvas, // independent of phase. // phase: Entries in our `lines` array are frequently shifted from the back // of the array to the front. `phase` records how many times the // array has been shifted so we can keep track of specific lines. // adjustedLineIdx: The actual line index that should be drawn on this // step. Represents a single characteristic line that // evolves over time via the simplex function. // peakNode: line (y) and node (x) coordinates of wherever the mouse is. for (var lineIdx = 0; lineIdx < numLines; ++lineIdx) { // Update our nodes with the next simplex value times a gaussian curve // centred on peakNode. var adjustedLineIdx = mod(lineIdx + phase, numLines); var nodes = lines[adjustedLineIdx]; var peakNodes = linePeaks[adjustedLineIdx]; var isHighlighted = peakNode.y === lineIdx; if (isHighlighted && !peakNodes[peakNode.x]) { var newAge = 1; for (var i = peakNode.x - NEIGHBOR_GAP, _len = peakNode.x + NEIGHBOR_GAP; i < _len; ++i) { if (peakNodes[i]) { newAge = 0; break; } } peakNodes[peakNode.x] = newAge; } for (var nodeIdx = 0; nodeIdx < numNodes; ++nodeIdx) { var noise = simplex.noise3D(adjustedLineIdx, nodeIdx, t * SPEED * WOBBLE_SPEED); var peaksValue = 0; var numPeaks = 0; for (var peakNodeIdx = 0; peakNodeIdx < numNodes; ++peakNodeIdx) { var age = peakNodes[peakNodeIdx] * SPEED; if (age) { ++numPeaks; var ageDiff = age - PEAK_AGE; var rising = ageDiff <= 0; peaksValue += (noise + 1) / 2 * gaussian2d(PEAK_HEIGHT_PX, age, nodeIdx - peakNodeIdx, PEAK_AGE, 0, 10 * SPEED * (rising ? 1 : 1 + DECAY_LENGTH_FACTOR), 0.5 / SPEED * (rising ? 1 : 1 + ageDiff * DECAY_WIDTH_FACTOR * 2)); } } // Normalize it. Commented out for now, because the abrupt jump // doesn't cut it. // // peaksValue /= numPeaks || 1; // Put some bounds on our node height. peaksValue = Math.max(Math.min(peaksValue, PEAK_HEIGHT_PX * 3), 0); nodes[nodeIdx] = Math.min(MAX_INT_16_VALUE, noise * AMPLITUDE_PX + peaksValue); } // Visual debugging is fun debugging : ) if (DEBUG_COLORS) { if (false) 'noop';else if (adjustedLineIdx === 42) { ctx.strokeStyle = 'orange'; } else if (lineIdx === 42) { ctx.strokeStyle = 'magenta'; } else if (phase === lineIdx) { ctx.strokeStyle = 'cyan'; } else if (phase === 0) { ctx.strokeStyle = 'limegreen'; } else { ctx.strokeStyle = FOREGROUND_COLOR; } } // Draw the line var baseline = mod(lineIdx * LINE_SPACING_PX - baselineOffset, hTotal); ctx.beginPath(); ctx.moveTo(0, baseline); ctx.lineTo(0, baseline - nodes[0]); for (var x = 1; x < numNodes - 1; ++x) { var y = nodes[x]; var midX = x + 0.5; var midY = (y + nodes[x + 1]) / 2; // Rather than drawing straight lines between nodes, this gives us // a curve that *approximates* each node value. If we were trying // to represent real data, this wouldn't fly. ctx.quadraticCurveTo(x * NODE_SPACING_PX, baseline - y, midX * NODE_SPACING_PX, baseline - midY); } ctx.lineTo(w, baseline); ctx.fill(); ctx.stroke(); // Increment the peak nodes' ages once we've drawn our line (Probably // nicer to set age = timestamp and compare against `t`, but this // works). for (var _peakNodeIdx = 0; _peakNodeIdx < numNodes; ++_peakNodeIdx) { if (peakNodes[_peakNodeIdx]) ++peakNodes[_peakNodeIdx]; } }; // And around and around we go... t += 1; window.requestAnimationFrame(step); })(); // Util functions function mouseCoords(_ref) { var clientX = _ref.clientX, clientY = _ref.clientY; var _canvas$getBoundingCl = canvas.getBoundingClientRect(), left = _canvas$getBoundingCl.left, top = _canvas$getBoundingCl.top; return { x: clientX - left, y: clientY - top }; } // Proper modulo :-) function mod(a, b) { return (a % b + b) % b; } function gaussian2d(a, x, y, x0, y0, sigmaX, sigmaY) { return a * Math.exp(-Math.pow(x - x0, 2) / 2 / Math.pow(sigmaX, 2) - Math.pow(y - y0, 2) / 2 / Math.pow(sigmaY, 2)); }
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>动态波纹-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号