'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