UNPKG

@evg-b/evg-ui

Version:

EVG-UI library inspired by Material Design.

713 lines (619 loc) 23.3 kB
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;