@evg-b/evg-ui
Version:
EVG-UI library inspired by Material Design.
713 lines (619 loc) • 23.3 kB
JavaScript
import _extends from '@babel/runtime/helpers/extends';
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import _assertThisInitialized from '@babel/runtime/helpers/assertThisInitialized';
import _inherits from '@babel/runtime/helpers/inherits';
import _possibleConstructorReturn from '@babel/runtime/helpers/possibleConstructorReturn';
import _getPrototypeOf from '@babel/runtime/helpers/getPrototypeOf';
import _construct from '@babel/runtime/helpers/construct';
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
import _createClass from '@babel/runtime/helpers/createClass';
import React from 'react';
import PropTypes from 'prop-types';
import '@babel/runtime/helpers/slicedToArray';
import withStyles from '../styles/withStyles.js';
import Color from '../styles/Color/Color.js';
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
var styles = {
base: {
width: '100%',
height: '100%'
}
};
var config = {
sizeCub: 40,
minLevel: 30,
maxLevel: 200,
speedDefault: 1,
colorBase: '#E0E0E0',
// 300
factorRejection: 0.3
};
var mapFrontColorCache = new Map();
var mapSideColorCache = new Map();
function getShift(x, y, w, h) {
var centerX = w / 2,
centerY = h / 2;
var _ref = [Math.abs(centerX - x), Math.abs(centerY - y)],
difX = _ref[0],
difY = _ref[1];
return {
x: Number((difX / centerX).toFixed(2)),
y: Number((difY / centerY).toFixed(2))
};
}
function getDirection(x, y, w, h) {
var _ref2;
var centerX = w / 2,
centerY = h / 2;
/*
direction - в какую сторону направлять движение
1 ####### 2
# \ / #
# / \ #
4 ####### 3
x = 1 -> 2 и 3 стороны иначе наоборот
y = 1 -> 3 и 4 стороны иначе наоборот
*/
return _ref2 = [x > centerX ? 1 : -1, y > centerY ? 1 : -1], _ref2[0], _ref2[1], _ref2;
}
var Cub = /*#__PURE__*/function () {
function Cub(ctx, x, y) {
var directionX = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1;
var directionY = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
var shiftX = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
var shiftY = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 1;
var colorBase = arguments.length > 7 ? arguments[7] : undefined;
var levelMin = arguments.length > 8 ? arguments[8] : undefined;
var levelMax = arguments.length > 9 ? arguments[9] : undefined;
var size = arguments.length > 10 ? arguments[10] : undefined;
_classCallCheck(this, Cub);
this.ctx = ctx;
this.startX = x;
this.startY = y;
this.x = x;
this.y = y;
this.shiftX = shiftX;
this.shiftY = shiftY;
this.colorBase = colorBase;
this.size = size;
this.directionX = directionX;
this.directionY = directionY; // this.levelMax = Math.random() * config.maxLevel
this.levelMaxGlobal = levelMax;
this.levelMax = Math.floor(Math.random() * (levelMax - levelMin)) + levelMin;
this.level = 0;
this.levelTarget = 0;
this.levelFreez = -1;
this.levelDirect = 1; // this.water = true
this.autopilot = false;
this.speed = config.speedDefault;
this.speedTarget = config.speedDefault; // this.speed = 1
}
_createClass(Cub, [{
key: "setLevelTarget",
value: function setLevelTarget(level) {
var speed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.speed;
this.levelTarget = level;
this.speedTarget = speed;
} // onFreez(levelFreez, speed = this.speed) {
// this.levelFreez = levelFreez
// this.speed = speed
// }
// offFreez() {
// this.levelFreez = -1
// this.speed = this.speed
// }
}, {
key: "setSpeed",
value: function setSpeed() {
var speed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.speed;
this.speed = speed;
}
}, {
key: "setColor",
value: function setColor(color) {
this.colorBase = color;
}
}, {
key: "setAutopilot",
value: function setAutopilot(autopilot) {
this.autopilot = autopilot;
}
}, {
key: "changeLevelDirect",
value: function changeLevelDirect(maxLevel, speed) {
var newLevel = this.level + this.levelDirect * speed;
if (newLevel >= maxLevel) {
this.levelDirect = -1;
}
if (newLevel <= 0) {
this.levelDirect = 1;
}
this.level = newLevel < 0 ? 0 : newLevel;
}
}, {
key: "move",
value: function move() {
var shiftNowX = +(this.level * this.directionX * this.shiftX * (this.level === 0 ? 0 : config.factorRejection)).toFixed(1);
var shiftNowY = +(this.level * this.directionY * this.shiftY * (this.level === 0 ? 0 : config.factorRejection)).toFixed(1);
this.x = this.startX + shiftNowX;
this.y = this.startY + shiftNowY;
}
}, {
key: "autopilotAnimation",
value: function autopilotAnimation() {
this.changeLevelDirect(this.levelMax, this.speed);
this.move();
}
}, {
key: "targetAnimation",
value: function targetAnimation() {
this.changeLevelDirect(this.levelTarget, this.speedTarget);
if (this.levelDirect === -1) {
this.levelTarget = this.levelTarget - 1 * this.speedTarget;
}
this.levelTarget = this.levelTarget < 0 ? 0 : this.levelTarget;
this.move();
} // freezAnimation() {
// if (this.level !== this.levelFreez) {
// this.changeLevelDirect(this.levelFreez)
// this.move()
// }
// }
}, {
key: "renderSides",
value: function renderSides() {
var centeringBySize = this.size / 2;
var startX1 = this.startX - centeringBySize,
startX2 = this.startX + centeringBySize;
var startY1 = this.startY - centeringBySize,
startY2 = this.startY + centeringBySize;
var nowX1 = this.x - centeringBySize,
nowX2 = this.x + centeringBySize;
var nowY1 = this.y - centeringBySize,
nowY2 = this.y + centeringBySize;
var levelPercent = this.level / this.levelMaxGlobal * 50;
var keySideX = "X".concat(levelPercent * this.shiftX),
keySideY = "Y".concat(levelPercent * this.shiftY);
var colorSideX, colorSideY;
if (mapSideColorCache.has(keySideX)) {
colorSideX = mapSideColorCache.get(keySideX);
} else {
var colorSidetoFront = Color(this.colorBase).Bright('rgb', -20);
colorSideX = Color(colorSidetoFront).Bright('rgb', levelPercent * this.shiftX); // кэшируем значение цвета для каждого уровня
mapSideColorCache.set(keySideX, colorSideX);
}
if (mapSideColorCache.has(keySideY)) {
colorSideY = mapSideColorCache.get(keySideY);
} else {
var _colorSidetoFront = Color(this.colorBase).Bright('rgb', -20);
colorSideY = Color(_colorSidetoFront).Bright('rgb', levelPercent * this.shiftY); // кэшируем значение цвета для каждого уровня
mapSideColorCache.set(keySideY, colorSideY);
}
if (this.directionY === 1) {
// top
this.ctx.beginPath();
this.ctx.fillStyle = colorSideY;
this.ctx.moveTo(startX1, startY1);
this.ctx.lineTo(startX2, startY1);
this.ctx.lineTo(nowX2, nowY1);
this.ctx.lineTo(nowX1, nowY1);
this.ctx.closePath();
this.ctx.fill();
} else {
// bottom
this.ctx.beginPath();
this.ctx.fillStyle = colorSideY;
this.ctx.moveTo(startX1, startY2);
this.ctx.lineTo(startX2, startY2);
this.ctx.lineTo(nowX2, nowY2);
this.ctx.lineTo(nowX1, nowY2);
this.ctx.closePath();
this.ctx.fill();
}
if (this.directionX === 1) {
// right
this.ctx.beginPath();
this.ctx.fillStyle = colorSideX;
this.ctx.moveTo(startX1, startY1);
this.ctx.lineTo(nowX1, nowY1);
this.ctx.lineTo(nowX1, nowY2);
this.ctx.lineTo(startX1, startY2);
this.ctx.closePath();
this.ctx.fill();
} else {
// left
this.ctx.beginPath();
this.ctx.fillStyle = colorSideX;
this.ctx.moveTo(startX2, startY1);
this.ctx.lineTo(nowX2, nowY1);
this.ctx.lineTo(nowX2, nowY2);
this.ctx.lineTo(startX2, startY2);
this.ctx.closePath();
this.ctx.fill();
}
}
}, {
key: "renderFront",
value: function renderFront() {
// mapFrontColorCache
var levelPercent = this.level / this.levelMaxGlobal * 50;
var keyFront = "".concat(levelPercent, ",").concat(this.shiftX * this.shiftY);
if (mapFrontColorCache.has(keyFront)) {
this.ctx.fillStyle = mapFrontColorCache.get(keyFront);
} else {
var colorFrontToCenter = Color(this.colorBase).Bright('rgb', -(this.shiftX * this.shiftY) * 10);
var colorFront = Color(colorFrontToCenter).Bright('rgb', levelPercent);
this.ctx.fillStyle = colorFront; // кэшируем значение цвета для каждого уровня
mapFrontColorCache.set(keyFront, colorFront);
}
this.ctx.fillRect(this.x - this.size / 2, this.y - this.size / 2, this.size, this.size);
}
}, {
key: "render",
value: function render() {
// if (this.levelFreez === -1) {
// if (this.levelTarget === 0 && this.autopilot) {
// this.speed !== 1 ? this.speed = 1 : null
// this.autopilotAnimation()
// }
// if (this.levelTarget !== 0) {
// this.targetAnimation()
// }
// } else {
// this.freezAnimation()
// }
if (this.levelTarget === 0 && this.autopilot) {
// this.speed !== 1 ? this.speed = 1 : null
this.autopilotAnimation();
}
if (this.levelTarget !== 0) {
this.targetAnimation();
}
this.renderSides();
this.renderFront();
}
}]);
return Cub;
}();
var OverseerCubs = /*#__PURE__*/function () {
function OverseerCubs(ctx, OverseerId, width, height) {
var color = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : config.colorBase;
var speed = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : config.speedDefault;
_classCallCheck(this, OverseerCubs);
this.ctx = ctx;
this.OverseerId = OverseerId;
this.w = width;
this.h = height;
this.cubs = [];
this.step = 0; // this.stepMax = 5
this.timeAnimationSpeed = 60;
this.mapInWork = new Map();
this.mapInRipple = new Map();
this.mapInFreez = new Map();
this.ripple = false;
this.rippleLevel = 0;
this.rippleSpeed = 1;
this.color = color;
this.sped = speed;
this.render = this.render.bind(this);
}
_createClass(OverseerCubs, [{
key: "setRipple",
value: function setRipple() {
var rippleLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var rippleSpeed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
this.ripple = true;
this.rippleLevel = rippleLevel;
this.rippleSpeed = rippleSpeed;
}
}, {
key: "filling",
value: function filling(fillingX, fillingY, levelMin, levelMax, sizeCub) {
var cubsCounX = fillingX === 0 ? 2 + (this.w / sizeCub | 0) : fillingX;
var cubsCounY = fillingY === 0 ? 2 + (this.h / sizeCub | 0) : fillingY;
var startX = (sizeCub + this.w - cubsCounX * sizeCub) / 2;
var startY = (sizeCub + this.h - cubsCounY * sizeCub) / 2;
for (var j = 0; j < cubsCounY; j++) {
var y = startY + j * sizeCub; // found y
for (var i = 0; i < cubsCounX; i++) {
var x = startX + i * sizeCub; // found x
var dif = getShift(x, y, this.w, this.h); // let dif = { x: 0.37, y: 0.5 } // заглушка
this.cubs.push(_construct(Cub, [this.ctx, x, y].concat(_toConsumableArray(getDirection(x, y, this.w, this.h)), [dif.x, dif.y, this.color, levelMin, levelMax, sizeCub])));
}
}
this.cubs = this.cubs.sort(function (a, b) {
return a.shiftX + a.shiftY < b.shiftX + b.shiftY ? 1 : -1;
}); // this.stepMax = Math.max(...this.cubs.map(cub => cub.shiftX * cub.shiftX + cub.shiftY * cub.shiftY))
} // centerFreez() {
// this.cubs.forEach((cub, index) => {
// let w = cub.shiftX * cub.shiftX + cub.shiftY * cub.shiftY
// if (w > 0 && w < 0.01) {
// this.mapInFreez.set(index, cub)
// }
// })
// this.mapInFreez.forEach((cub) => {
// cub.onFreez(0, 1)
// cub.setColor(config.colorPurple)
// })
// }
// offFreez() {
// this.mapInFreez.forEach(cub => cub.offFreez())
// this.mapInFreez = new Map()
// }
}, {
key: "rippleAnimation",
value: function rippleAnimation() {
var _this = this;
var stepSize = 0.01;
var thickWave = 0.07;
var step = this.step * 3;
var newMap = new Map();
this.cubs.forEach(function (cub, index) {
var w = cub.shiftX * cub.shiftX + cub.shiftY * cub.shiftY;
if (w > step && w < step + thickWave) {
newMap.set(index, cub);
}
}); // 1) убираем из старого Map тех кого нету и при удалении даем им команду
this.mapInWork.forEach(function (cub, index) {
if (!newMap.has(index)) {
// этих кубов нету в новой Map
// cub.setLevelTarget(1, 6)
// colorDev && cub.setColor(config.colorBase)
_this.mapInWork["delete"](index);
}
}); // 2) находим новых в новой Map и даем им команду
newMap.forEach(function (cub, index) {
if (!_this.mapInWork.has(index)) {
// colorDev && cub.setColor(config.colorRed)
cub.setLevelTarget(_this.rippleLevel, _this.rippleSpeed);
_this.mapInRipple.set(index, index);
}
}); // 3) заменяем старую мапу на новую
this.mapInWork = newMap;
if (this.cubs.length === this.mapInRipple.size) {
// заканчиваем ripple т.к все уже получили команду на новый Level
this.ripple = false; // clear
this.mapInRipple.clear();
this.mapInWork.clear();
this.step = 0;
} else {
this.step += stepSize;
}
}
}, {
key: "autopilot",
value: function autopilot() {
var switchBool = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this.cubs.forEach(function (cub) {
return cub.setAutopilot(switchBool);
});
}
}, {
key: "setColor",
value: function setColor() {
var color = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.color;
var newColor = color ? Color(color).Base() : config.colorBase;
mapFrontColorCache.clear();
mapSideColorCache.clear();
this.cubs.forEach(function (cub) {
return cub.setColor(newColor);
});
}
}, {
key: "setSpeed",
value: function setSpeed() {
var newSpeed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.speed;
this.cubs.forEach(function (cub) {
return cub.setSpeed(newSpeed);
});
}
}, {
key: "render",
value: function render() {
this.cubs.forEach(function (cub) {
return cub.render();
}); // render
this.ripple && this.rippleAnimation();
this.OverseerId.id = requestAnimationFrame(this.render);
}
}, {
key: "renderTest",
value: function renderTest() {
var _this2 = this;
setInterval(function () {
_this2.cubs.forEach(function (cub) {
return cub.render();
}); // render
if (_this2.ripple) {
_this2.rippleAnimation();
}
}, 500);
}
}]);
return OverseerCubs;
}();
/**
* Cubes - интерактивный живой фон из кубов. Работает все с помощью `canvas` 2d без сторонних зависимостей.
* Удивляйте своих пользователей красивой фоновой анимацией.
*/
var Cubes = /*#__PURE__*/function (_React$Component) {
_inherits(Cubes, _React$Component);
var _super = _createSuper(Cubes);
function Cubes(props) {
var _this3;
_classCallCheck(this, Cubes);
_this3 = _super.call(this, props);
_this3.CanvasWrapper_Ref = /*#__PURE__*/React.createRef();
_this3.Canvas_Ref = _this3.props.innerRef || /*#__PURE__*/React.createRef();
_this3.OverseerId = {
id: 0
};
_this3.renderIsStart = false;
_this3.stop = _this3.stop.bind(_assertThisInitialized(_this3));
_this3.start = _this3.start.bind(_assertThisInitialized(_this3));
_this3.ripple = _this3.ripple.bind(_assertThisInitialized(_this3));
return _this3;
}
_createClass(Cubes, [{
key: "componentDidMount",
value: function componentDidMount() {
var _this4 = this;
// 1) init
var ctx = this.Canvas_Ref.current;
setTimeout(function () {
var _ctx$parentNode$getBo = ctx.parentNode.getBoundingClientRect(),
width = _ctx$parentNode$getBo.width,
height = _ctx$parentNode$getBo.height;
ctx.width = width;
ctx.height = height;
_this4.Overseer = new OverseerCubs(ctx.getContext('2d', {
alpha: false
}), _this4.OverseerId, ctx.width, ctx.height);
_this4.Overseer.filling(_this4.props.fillingX, _this4.props.fillingY, _this4.props.levelMin, _this4.props.levelMax, _this4.props.size); // // 2) start requestAnimationFrame
_this4.Overseer.autopilot(_this4.props.autopilot);
_this4.Overseer.setColor(_this4.props.color);
_this4.Overseer.setSpeed(_this4.props.speed);
_this4.start();
}, 0);
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
var autopilot = prevProps.autopilot,
color = prevProps.color,
speed = prevProps.speed,
size = prevProps.size;
var _this$props = this.props,
newAutopilot = _this$props.autopilot,
newColor = _this$props.color,
newSpeed = _this$props.speed,
newSize = _this$props.size; // autopilot
if (autopilot !== newAutopilot) {
this.Overseer.autopilot(newAutopilot);
} // color
if (color !== newColor) {
this.Overseer.setColor(newColor);
} // speed
if (speed !== newSpeed) {
this.Overseer.setSpeed(newSpeed);
} // size
if (size !== newSize) {
this.Overseer.cubs = [];
this.Overseer.filling(this.props.fillingX, this.props.fillingY, this.props.levelMin, this.props.levelMax, newSize);
this.Overseer.autopilot(this.props.autopilot);
}
}
}, {
key: "stop",
value: function stop() {
this.renderIsStart = false;
var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
cancelAnimationFrame(this.OverseerId.id);
}
}, {
key: "ripple",
value: function ripple(level, speed) {
this.Overseer.setRipple(level, speed);
}
}, {
key: "start",
value: function start() {
if (!this.renderIsStart) {
this.renderIsStart = true;
this.Overseer.render();
}
}
}, {
key: "render",
value: function render() {
var _this$props2 = this.props;
_this$props2.children;
_this$props2.classes;
_this$props2.className;
_this$props2.autopilot;
_this$props2.innerRef;
_this$props2.color;
_this$props2.fillingX;
_this$props2.fillingY;
_this$props2.levelMin;
_this$props2.levelMax;
_this$props2.speed;
_this$props2.size;
var otherProps = _objectWithoutProperties(_this$props2, ["children", "classes", "className", "autopilot", "innerRef", "color", "fillingX", "fillingY", "levelMin", "levelMax", "speed", "size"]);
return /*#__PURE__*/React.createElement("canvas", _extends({
ref: this.Canvas_Ref
}, otherProps));
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.stop();
}
}]);
return Cubes;
}(React.Component);
Cubes.propTypes = {
/**
* Объект содержит jss стили компонента.
*/
classes: PropTypes.object,
/**
* Чтобы указать CSS классы, используйте этот атрибут.
*/
className: PropTypes.string,
/**
* Это свойство не реализуется.
*/
children: PropTypes.any,
/**
* ref ссылка компонента.
*/
innerRef: PropTypes.object,
/**
* Название цвета в разных форматах.
*/
color: PropTypes.string,
/**
* Если true, кубы начинают двигаться сами по себе.
*/
autopilot: PropTypes.bool,
/**
* Заполнение области по X. Если 0 то полное заполнение до краев.
*/
fillingX: PropTypes.number,
/**
* Заполнение области по Y. Если 0 то полное заполнение до краев.
*/
fillingY: PropTypes.number,
/**
* Минимальный уровень высоты до которого может опускаться один куб.
*/
levelMin: PropTypes.number,
/**
* Максимальный уровень высоты до которого может опускаться один куб.
*/
levelMax: PropTypes.number,
/**
* Размер куба.
*/
size: PropTypes.number,
/**
* Скорость изменения высоты куба.
*/
speed: PropTypes.number
};
Cubes.defaultProps = {
autopilot: true,
color: '#E0E0E0',
fillingX: 0,
fillingY: 0,
levelMin: 30,
levelMax: 100,
size: 40,
speed: 1
};
Cubes.displayName = 'CubesEVG';
var Cubes$1 = withStyles(styles)(Cubes);
export default Cubes$1;