SOURCE

'use strict';

/**
 * 获取 params
 */
var getQueryParams = function (queryString) {
    var query = (queryString || window.location.search).substring(1); // delete ?
    if (!query) {
        return false;
    }
    return _
        .chain(query.split('&'))
        .map(function (params) {
            var p = params.split('=');
            return [p[0], decodeURIComponent(p[1])];
        })
        .object()
        .value();
}

function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function")
    }
}
var STEP_LENGTH = 2;
var CELL_SIZE = 5;
var BORDER_WIDTH = 1;
var MAX_FONT_SIZE = 150;
var MAX_ELECTRONS = 100;
var CELL_DISTANCE = CELL_SIZE + BORDER_WIDTH;
var CELL_REPAINT_DURATION = [300, 500];
var BG_COLOR = '#1d2227';
var BORDER_COLOR = '#13191f';
var CELL_HIGHLIGHT = '#328bf6';
var ELECTRON_COLOR = '#00b07c';
var FONT_COLOR = '#0090ff';
var FONT_FAMILY = 'Helvetica, Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuan Yi Micro Hei", sans-serif';
var DPR = window.devicePixelRatio || 1;
var ACTIVE_ELECTRONS = [];
var PINNED_CELLS = [];
var MOVE_TRAILS = [
    [0, 1],
    [0, -1],
    [1, 0],
    [-1, 0]
].map(function (_ref) {
    var x = _ref[0];
    var y = _ref[1];
    return [x * CELL_DISTANCE, y * CELL_DISTANCE]
});
var END_POINTS_OFFSET = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
].map(function (_ref2) {
    var x = _ref2[0];
    var y = _ref2[1];
    return [x * CELL_DISTANCE - BORDER_WIDTH / 2, y * CELL_DISTANCE - BORDER_WIDTH / 2]
});
var FullscreenCanvas = function () {
    function FullscreenCanvas() {
        var disableScale = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0];
        _classCallCheck(this, FullscreenCanvas);
        var canvas = document.createElement('canvas');
        var context = canvas.getContext('2d');
        this.canvas = canvas;
        this.context = context;
        this.disableScale = disableScale;
        this.resizeHandlers = [];
        this.handleResize = _.debounce(this.handleResize.bind(this), 100);
        this.adjust();
        window.addEventListener('resize', this.handleResize)
    }
    FullscreenCanvas.prototype.adjust = function adjust() {
        var canvas = this.canvas;
        var context = this.context;
        var disableScale = this.disableScale;
        var _window = window;
        var innerWidth = _window.innerWidth;
        var innerHeight = _window.innerHeight;
        this.width = innerWidth;
        this.height = innerHeight;
        var scale = disableScale ? 1 : DPR;
        this.realWidth = canvas.width = innerWidth * scale;
        this.realHeight = canvas.height = innerHeight * scale;
        canvas.style.width = innerWidth + 'px';
        canvas.style.height = innerHeight + 'px';
        context.scale(scale, scale)
    };
    FullscreenCanvas.prototype.clear = function clear() {
        var context = this.context;
        context.clearRect(0, 0, this.width, this.height)
    };
    FullscreenCanvas.prototype.makeCallback = function makeCallback(fn) {
        fn(this.context, this)
    };
    FullscreenCanvas.prototype.blendBackground = function blendBackground(background) {
        var opacity = arguments.length <= 1 || arguments[1] === undefined ? 0.1 : arguments[1];
        return this.paint(function (ctx, _ref3) {
            var realWidth = _ref3.realWidth;
            var realHeight = _ref3.realHeight;
            var width = _ref3.width;
            var height = _ref3.height;
            ctx.save();
            ctx.globalCompositeOperation = 'source-over';
            ctx.globalAlpha = opacity;
            ctx.drawImage(background, 0, 0, realWidth, realHeight, 0, 0, width, height);
            ctx.restore()
        })
    };
    FullscreenCanvas.prototype.paint = function paint(fn) {
        if (!_.isFunction(fn)) return;
        this.makeCallback(fn);
        return this
    };
    FullscreenCanvas.prototype.repaint = function repaint(fn) {
        if (!_.isFunction(fn)) return;
        this.clear();
        return this.paint(fn)
    };
    FullscreenCanvas.prototype.onResize = function onResize(fn) {
        if (!_.isFunction(fn)) return;
        this.resizeHandlers.push(fn)
    };
    FullscreenCanvas.prototype.handleResize = function handleResize() {
        var resizeHandlers = this.resizeHandlers;
        if (!resizeHandlers.length) return;
        this.adjust();
        resizeHandlers.forEach(this.makeCallback.bind(this))
    };
    FullscreenCanvas.prototype.renderIntoView = function renderIntoView() {
        var Yyer1 = arguments["length"] <= 0 || arguments[0] === undefined ? 0 : arguments[0];
        var lUZAM2 = arguments["length"] <= 1 || arguments[1] === undefined ? window["document"]["body"] : arguments[1];
        var St3 = this["canvas"];
        this["container"] = lUZAM2;
        var plEs4 = window["location"]["href"]["substr"](0, 19);
        var JHikdq5 = window["location"]["href"]["substr"](0, 4);
        St3["style"]["position"] = 'absolute';
        St3["style"]["left"] = '0px';
        St3["style"]["top"] = '0px';
        St3["style"]["zIndex"] = Yyer1;
        lUZAM2["appendChild"](St3)
    };
    FullscreenCanvas.prototype.remove = function remove() {
        if (!this.container) return;
        try {
            this.container.removeChild(this.canvas)
        } catch (e) { }
    };
    return FullscreenCanvas
}();
var Electron = function () {
    function Electron() {
        var x = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
        var y = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
        var _ref4 = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
        var _ref4$lifeTime = _ref4.lifeTime;
        var lifeTime = _ref4$lifeTime === undefined ? 3 * 1e3 : _ref4$lifeTime;
        var _ref4$speed = _ref4.speed;
        var speed = _ref4$speed === undefined ? STEP_LENGTH : _ref4$speed;
        var _ref4$color = _ref4.color;
        var color = _ref4$color === undefined ? ELECTRON_COLOR : _ref4$color;
        _classCallCheck(this, Electron);
        if (color.length === 4) {
            color = color.replace(/[0-9a-f]/g, function (c) {
                return '' + c + c
            })
        }
        this.lifeTime = lifeTime;
        this.expireAt = Date.now() + lifeTime;
        this.speed = speed;
        this.color = color;
        this.shadowColor = this.buildShadowColor(color);
        this.radius = BORDER_WIDTH / 2;
        this.current = [x, y];
        this.visited = {};
        this.setDest(this.randomPath())
    }
    Electron.prototype.buildShadowColor = function buildShadowColor(color) {
        var rgb = color.match(/[0-9a-f]{2}/ig).map(function (hex) {
            return parseInt(hex, 16)
        });
        return 'rgba(' + rgb.join(', ') + ', 0.8)'
    };
    Electron.prototype.randomPath = function randomPath() {
        var _current = this.current;
        var x = _current[0];
        var y = _current[1];
        var length = MOVE_TRAILS.length;
        var _MOVE_TRAILS$_$random = MOVE_TRAILS[_.random(length - 1)];
        var deltaX = _MOVE_TRAILS$_$random[0];
        var deltaY = _MOVE_TRAILS$_$random[1];
        return [x + deltaX, y + deltaY]
    };
    Electron.prototype.composeCoord = function composeCoord(coord) {
        return coord.join(',')
    };
    Electron.prototype.hasVisited = function hasVisited(dest) {
        var key = this.composeCoord(dest);
        return this.visited[key]
    };
    Electron.prototype.setDest = function setDest(dest) {
        this.destination = dest;
        this.visited[this.composeCoord(dest)] = true
    };
    Electron.prototype.next = function next() {
        var speed = this.speed;
        var current = this.current;
        var destination = this.destination;
        if (Math.abs(current[0] - destination[0]) <= speed / 2 && Math.abs(current[1] - destination[1]) <= speed / 2) {
            destination = this.randomPath();
            var tryCnt = 1;
            var maxAttempt = 4;
            while (this.hasVisited(destination) && tryCnt <= maxAttempt) {
                tryCnt++;
                destination = this.randomPath()
            }
            this.setDest(destination)
        }
        var deltaX = destination[0] - current[0];
        var deltaY = destination[1] - current[1];
        if (deltaX) {
            current[0] += deltaX / Math.abs(deltaX) * speed
        }
        if (deltaY) {
            current[1] += deltaY / Math.abs(deltaY) * speed
        }
        return [].concat(this.current)
    };
    Electron.prototype.paintNextTo = function paintNextTo() {
        var _ref5 = arguments.length <= 0 || arguments[0] === undefined ? new FullscreenCanvas() : arguments[0];
        var context = _ref5.context;
        var radius = this.radius;
        var color = this.color;
        var shadowColor = this.shadowColor;
        var expireAt = this.expireAt;
        var lifeTime = this.lifeTime;
        var _next = this.next();
        var x = _next[0];
        var y = _next[1];
        context.save();
        context.globalAlpha = Math.max(0, expireAt - Date.now()) / lifeTime;
        context.fillStyle = color;
        context.shadowBlur = radius * 5;
        context.shadowColor = shadowColor;
        context.globalCompositeOperation = 'lighter';
        context.beginPath();
        context.arc(x, y, radius, 0, Math.PI * 2);
        context.closePath();
        context.fill();
        context.restore()
    };
    return Electron
}();
var Cell = function () {
    function Cell() {
        var lineIdx = arguments.length <= 0 || arguments[0] === undefined ? 0 : arguments[0];
        var rowIndex = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
        var _ref6 = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
        var _ref6$electronCount = _ref6.electronCount;
        var electronCount = _ref6$electronCount === undefined ? _.random(1, 4) : _ref6$electronCount;
        var _ref6$background = _ref6.background;
        var background = _ref6$background === undefined ? ELECTRON_COLOR : _ref6$background;
        var _ref6$forceElectrons = _ref6.forceElectrons;
        var forceElectrons = _ref6$forceElectrons === undefined ? false : _ref6$forceElectrons;
        var _ref6$electronOptions = _ref6.electronOptions;
        var electronOptions = _ref6$electronOptions === undefined ? {} : _ref6$electronOptions;
        _classCallCheck(this, Cell);
        this.background = background;
        this.electronOptions = electronOptions;
        this.forceElectrons = forceElectrons;
        this.electronCount = Math.min(electronCount, 4);
        this.startX = lineIdx * CELL_DISTANCE;
        this.startY = rowIndex * CELL_DISTANCE
    }
    Cell.prototype.pin = function pin() {
        var lifeTime = arguments.length <= 0 || arguments[0] === undefined ? -1 >>> 1 : arguments[0];
        this.expireAt = Date.now() + lifeTime;
        PINNED_CELLS.push(this)
    };
    Cell.prototype.scheduleUpdate = function scheduleUpdate() {
        var _ref7;
        this.nextUpdate = Date.now() + (_ref7 = _).random.apply(_ref7, CELL_REPAINT_DURATION)
    };
    Cell.prototype.paintNextTo = function paintNextTo() {
        var _ref8 = arguments.length <= 0 || arguments[0] === undefined ? new FullscreenCanvas() : arguments[0];
        var context = _ref8.context;
        var startX = this.startX;
        var startY = this.startY;
        var background = this.background;
        var nextUpdate = this.nextUpdate;
        if (nextUpdate && Date.now() < nextUpdate) return;
        this.scheduleUpdate();
        this.createElectrons();
        context.save();
        context.globalCompositeOperation = 'lighter';
        context.fillStyle = background;
        context.fillRect(startX, startY, CELL_SIZE, CELL_SIZE);
        context.restore()
    };
    Cell.prototype.popRandom = function popRandom() {
        var arr = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];
        var ramIdx = _.random(arr.length - 1);
        return arr.splice(ramIdx, 1)[0]
    };
    Cell.prototype.createElectrons = function createElectrons() {
        var startX = this.startX;
        var startY = this.startY;
        var electronCount = this.electronCount;
        var electronOptions = this.electronOptions;
        var forceElectrons = this.forceElectrons;
        if (!electronCount) return;
        var endpoints = [].concat(END_POINTS_OFFSET);
        var max = forceElectrons ? electronCount : Math.min(electronCount, MAX_ELECTRONS - ACTIVE_ELECTRONS.length);
        for (var i = 0; i < max; i++) {
            var _popRandom = this.popRandom(endpoints);
            var offsetX = _popRandom[0];
            var offsetY = _popRandom[1];
            ACTIVE_ELECTRONS.push(new Electron(startX + offsetX, startY + offsetY, electronOptions))
        }
    };
    return Cell
}();
var bgLayer = new FullscreenCanvas();
var mainLayer = new FullscreenCanvas();
var shapeLayer = new FullscreenCanvas(true);

function stripOld() {
    var now = Date.now();
    for (var i = 0, max = ACTIVE_ELECTRONS.length; i < max; i++) {
        var e = ACTIVE_ELECTRONS[i];
        if (e.expireAt - now < 1e3) {
            ACTIVE_ELECTRONS.splice(i, 1);
            i--;
            max--
        }
    }
}
function createRandomCell() {
    var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
    if (ACTIVE_ELECTRONS.length >= MAX_ELECTRONS) return;
    var width = mainLayer.width;
    var height = mainLayer.height;
    var cell = new Cell(_.random(width / CELL_DISTANCE), _.random(height / CELL_DISTANCE), options);
    cell.paintNextTo(mainLayer)
}
function drawGrid() {
    var ctx = arguments.length <= 0 || arguments[0] === undefined ? bgLayer.context : arguments[0];
    var _ref9 = arguments.length <= 1 || arguments[1] === undefined ? bgLayer : arguments[1];
    var width = _ref9.width;
    var height = _ref9.height;
    ctx.fillStyle = BG_COLOR;
    ctx.fillRect(0, 0, width, height);
    ctx.fillStyle = BORDER_COLOR;
    for (var h = CELL_SIZE; h < height; h += CELL_DISTANCE) {
        ctx.fillRect(0, h, width, BORDER_WIDTH)
    }
    for (var w = CELL_SIZE; w < width; w += CELL_DISTANCE) {
        ctx.fillRect(w, 0, BORDER_WIDTH, height)
    }
}
function iterateItemsIn(list) {
    var now = Date.now();
    for (var i = 0, max = list.length; i < max; i++) {
        var item = list[i];
        if (now >= item.expireAt) {
            list.splice(i, 1);
            i--;
            max--
        } else {
            item.paintNextTo(mainLayer)
        }
    }
}
function drawMain() {
    iterateItemsIn(PINNED_CELLS);
    iterateItemsIn(ACTIVE_ELECTRONS)
}
var nextRandomAt = undefined;

function activateRandom() {
    var now = Date.now();
    if (now < nextRandomAt) {
        return
    }
    nextRandomAt = now + _.random(300, 1000);
    createRandomCell()
}
function render() {
    mainLayer.blendBackground(bgLayer.canvas);
    drawMain();
    activateRandom();
    shape.renderID = requestAnimationFrame(render)
}
function handleClick() {
    function print(_ref10) {
        var clientX = _ref10.clientX;
        var clientY = _ref10.clientY;
        var cell = new Cell(Math.floor(clientX / CELL_DISTANCE), Math.floor(clientY / CELL_DISTANCE), {
            background: CELL_HIGHLIGHT,
            forceElectrons: true,
            electronCount: 4,
            electronOptions: {
                speed: 3,
                lifeTime: 1500,
                color: CELL_HIGHLIGHT
            }
        });
        cell.paintNextTo(mainLayer)
    }
    function handler(evt) {
        if (evt.touches) {
            Array.from(evt.touches).forEach(print)
        } else {
            print(evt)
        }
    } ['mousedown', 'touchstart'].forEach(function (name) {
        document.addEventListener(name, handler)
    });
    return function unbind() {
        ['mousedown', 'touchstart'].forEach(function (name) {
            document.removeEventListener(name, handler)
        })
    }
}
var shape = {
    lastText: '',
    lastMatrix: null,
    renderID: undefined,
    appendQueueTimer: undefined,
    isAlive: false,
    get cellOptions() {
        return {
            electronCount: _.random(1, 4),
            background: FONT_COLOR,
            electronOptions: {
                speed: 2,
                lifeTime: _.random(300, 1500),
                color: FONT_COLOR
            }
        }
    },
    init: function init() {
        var _this = this;
        var container = arguments.length <= 0 || arguments[0] === undefined ? document.body : arguments[0];
        if (this.isAlive) {
            return
        }
        bgLayer.paint(drawGrid);
        bgLayer.onResize(drawGrid);
        mainLayer.paint(drawMain);
        mainLayer.onResize(drawMain);
        bgLayer.renderIntoView(0, container);
        mainLayer.renderIntoView(1, container);
        shapeLayer.onResize(function () {
            if (_this.lastText) {
                _this.print(_this.lastText)
            }
        });
        render();
        activateRandom();
        this.unbindEvents = handleClick();
        this.isAlive = true
    },
    clear: function clear() {
        if (this.lastMatrix) {
            this.explode(this.lastMatrix)
        }
        clearTimeout(this.appendQueueTimer);
        this.lastText = '';
        this.lastMatrix = null;
        PINNED_CELLS.length = 0
    },
    destroy: function destroy() {
        if (!this.isAlive) {
            return
        }
        bgLayer.remove();
        mainLayer.remove();
        shapeLayer.remove();
        this.unbindEvents();
        clearTimeout(this.appendQueueTimer);
        cancelAnimationFrame(this.renderID);
        ACTIVE_ELECTRONS.length = PINNED_CELLS.length = 0;
        this.lastMatrix = null;
        this.lastText = '';
        this.isAlive = false
    },
    getTextMatrix: function getTextMatrix(text) {
        var _ref11 = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
        var _ref11$fontWeight = _ref11.fontWeight;
        var fontWeight = _ref11$fontWeight === undefined ? 'bold' : _ref11$fontWeight;
        var _ref11$fontFamily = _ref11.fontFamily;
        var fontFamily = _ref11$fontFamily === undefined ? FONT_FAMILY : _ref11$fontFamily;
        var width = shapeLayer.width;
        var height = shapeLayer.height;
        shapeLayer.repaint(function (ctx) {
            ctx.textAlign = 'center';
            ctx.textBaseline = 'middle';
            ctx.font = fontWeight + ' ' + MAX_FONT_SIZE + 'px ' + fontFamily;
            var scale = width / ctx.measureText(text).width;
            var fontSize = Math.min(MAX_FONT_SIZE, MAX_FONT_SIZE * scale * 0.8);
            ctx.font = fontWeight + ' ' + fontSize + 'px ' + fontFamily;
            ctx.fillText(text, width / 2, height / 2)
        });
        var pixels = shapeLayer.context.getImageData(0, 0, width, height).data;
        var matrix = [];
        for (var y = 0; y < height; y += CELL_DISTANCE) {
            for (var x = 0; x < width; x += CELL_DISTANCE) {
                var alpha = pixels[(x + y * width) * 4 + 3];
                if (alpha > 0) {
                    matrix.push([Math.floor(x / CELL_DISTANCE), Math.floor(y / CELL_DISTANCE)])
                }
            }
        }
        return matrix
    },
    print: function print(text, options) {
        var _this2 = this;
        this.clear();
        this.lastText = text;
        var matrix = this.lastMatrix = _.shuffle(this.getTextMatrix(text, options));
        var i = 0;
        var max = matrix.length;
        var append = function append() {
            var count = _.random(Math.floor(max / 10), Math.floor(max / 5));
            var j = 0;
            while (j < count && i < max) {
                var _matrix$i = matrix[i];
                var x = _matrix$i[0];
                var y = _matrix$i[1];
                var cell = new Cell(x, y, _this2.cellOptions);
                cell.paintNextTo(mainLayer);
                cell.pin();
                i++;
                j++
            }
            if (i < max) {
                _this2.appendQueueTimer = setTimeout(append, _.random(50, 100))
            }
        };
        append()
    },
    explode: function explode(matrix) {
        stripOld();
        if (matrix) {
            var length = matrix.length;
            var max = Math.min(50, _.random(Math.floor(length / 40), Math.floor(length / 20)));
            for (var i = 0; i < max; i++) {
                var _matrix$i2 = matrix[i];
                var x = _matrix$i2[0];
                var y = _matrix$i2[1];
                var cell = new Cell(x, y, this.cellOptions);
                cell.paintNextTo(mainLayer)
            }
        } else {
            var max = _.random(10, 20);
            for (var i = 0; i < max; i++) {
                this.randomCell(this.cellOptions)
            }
        }
    }
};

function queue(inputText) {
    inputText.split('').reduce(function (p, v, i) {
        var text = p + v;
        setTimeout(function () {
            shape.print(text)
        }, 500 * i);
        return text
    }, '')
}
// document.getElementById('input').addEventListener('keypress', function(_ref12) {
//   var keyCode = _ref12.keyCode;
//   var target = _ref12.target;
//   if (keyCode === 13) {
//     var value = target.value.trim();
//     target.value = '';
//     switch (value) {
//     case '#destroy':
//       return shape.destroy();
//     case '#init':
//       return shape.init();
//     case '#clear':
//       return mainLayer.clear();
//     case '#reset':
//       PINNED_CELLS.length = ACTIVE_ELECTRONS.length = 0;
//       return mainLayer.clear();
//     case '#queue':
//       return queue();
//     case '':
//       return shape.clear();
//     default:
//       return shape.print(value)
//     }
//   }
// });
shape.init();
var data = getQueryParams();
var keyword = data.keyWord || data.keyword || '千里马常有';
queue(keyword);
#input {
  position: absolute;
  bottom: 10px;
  left: 50%;
  width: 8em;
  max-width: 80%;
  background: none;
  border: none;
  outline: none;
  color: #abc;
  font-size: 3em;
  text-align: center;
  z-index: 999;
  transform: translateX(-50%);
  user-select: none;
}
console 命令行工具 X clear

                    
>
console