Необязательно чёрный квадрат и не Малевича
Спрячу эффект под кат, чтобы не тормозил ленту. Идея в том, что плотный поток частиц, расположенных поверх фоновой картинки (или просто фона) подвергается "течению", открывающему её часть. Скрипт подгружается после загрузки страницы, при медленных компьютере/инете, возможно, придётся немного подождать.
Можно поводить мышью по канве и самому управлять "очисткой" (без нажатия), но с первым же движением мыши по канве автоматически обновляющаяся "рыбка" исчезнет, так что если не уловили, как всё работало, перезагрузите страницу в браузере нажатием клавиши F5.
Ниже приводится эффект в работе и исходники (разметка .html без обрамления + код на Javascript).
Внешних библиотек не нужно.
<div id="container" style="margin: 0 auto; text-align: center; background: url(back.gif) center no-repeat;"> </div> <script> function particlesMatrix (id) { let ROWS = 600, COLS = 600, NUM_PARTICLES = ROWS * COLS, //размерность матрицы THICKNESS = Math.pow(80, 2), //размер активной зоны SPACING = 1, //расстояние между частицами MARGIN = 10, //ширина внешних краев COLOR = 153, //цвет частиц, R=G=B DRAG1 = 0.85, //коэффициенты для DRAG2 = 0.15, //вычисления новых координат, [0;1] container, particle, canvas, mouse, list, ctx, tog, man, dx, dy, mx, my, d, t, f, a, b, i, n, w, h, p, s, r, c; particle = { vx: 0, vy: 0, x: 0, y: 0 }; function relMouseCoords (event) { let totalOffsetX = 0, totalOffsetY = 0, canvasX = 0, canvasY = 0, currentElement = this; do { totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft; totalOffsetY += currentElement.offsetTop - currentElement.scrollTop; } while (currentElement = currentElement.offsetParent); canvasX = event.pageX - totalOffsetX; canvasY = event.pageY - totalOffsetY; return { x:canvasX, y:canvasY }; } HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords; function init() { container = document.getElementById (id); canvas = document.createElement("canvas"); ctx = canvas.getContext("2d"); man = false; tog = true; list = []; w = canvas.width = COLS * SPACING + MARGIN * 2; h = canvas.height = ROWS * SPACING + MARGIN * 2; for (i = 0; i < NUM_PARTICLES; i++) { p = Object.create(particle); p.x = p.ox = MARGIN + SPACING * (i % COLS); p.y = p.oy = MARGIN + SPACING * Math.floor(i / COLS); list[i] = p; } container.addEventListener("mousemove", function(e) { mouse = canvas.relMouseCoords (e); mx = mouse.x; my = mouse.y; man = true; }); container.appendChild (canvas); } function step() { if ((tog = !tog)) { if (!man) { t = +new Date() * 0.001; mx = w * 0.5 + Math.cos(t * 2) * Math.cos(t * 0.5) * w * 0.4; my = h * 0.5 + Math.sin(t * 2) * Math.sin(t * 0.5) * h * 0.4; } for (i = 0; i < NUM_PARTICLES; i++) { p = list[i]; d = (dx = mx - p.x) * dx + (dy = my - p.y) * dy; f = -THICKNESS / d; if (d < THICKNESS) { t = Math.atan2(dy, dx); p.vx += f * Math.cos(t); p.vy += f * Math.sin(t); } p.x += (p.vx *= DRAG1) + (p.ox - p.x) * DRAG2; p.y += (p.vy *= DRAG1) + (p.oy - p.y) * DRAG2; } } else { a = ctx.createImageData(w, h); b = a.data; for (i = 0; i < NUM_PARTICLES; i++) { p = list [i]; b[(n = (~~p.x + ~~p.y * w) * 4)] = b[n + 1] = b[n + 2] = COLOR; //Быстро ставим все 3 компоненты в COLOR b[n + 3] = 255; //Alpha = 255 } ctx.putImageData(a, 0, 0); } requestAnimationFrame(step); } init(); step(); } window.addEventListener ('load', function (e) { particlesMatrix("container"); }); </script> <noscript> <div style="margin: 0 auto; text-align: center;"> Включите в браузере JavaScript для работы приложения! </div> </noscript>
Картинка back.gif из исходника скрипта
Ниже также прикреплена "нулевая" версия скрипта с абсолютным позиционированием чёрного полотна по центру и без рисунка внизу. Увидеть исходник можно из исходника страницы, файл сохранён в кодировке Юникода UTF-8.
ParticlesMatrix0.html, открыть в текущем окне/вкладке (3 Кб)
09.02.2020, 18:20 [1291 просмотр]