magic-hover
Version:
Transform perspective/tilt/rotate effect for nested react components.
212 lines (189 loc) • 8.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _reactDom = require("react-dom");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var MagicHover = function (_Component) {
_inherits(MagicHover, _Component);
function MagicHover(props) {
_classCallCheck(this, MagicHover);
var _this = _possibleConstructorReturn(this, (MagicHover.__proto__ || Object.getPrototypeOf(MagicHover)).call(this, props));
_this.state = {
style: {}
};
var defaultSettings = {
reverse: true,
rotate: 0,
max: 35,
perspective: 1000,
easing: "cubic-bezier(.03,.98,.52,.99)",
scale: { x: 1, y: 1, z: 1 },
translate: { x: 0, y: 0 },
speed: "1000",
transition: true,
axis: null,
reset: true
};
_this.width = null;
_this.height = null;
_this.left = null;
_this.top = null;
_this.transitionTimeout = null;
_this.updateCall = null;
_this.element = null;
_this.settings = _extends({}, defaultSettings, _this.props.options);
_this.reverse = _this.settings.reverse ? -1 : 1;
_this.handleMouseEnter = _this.handleMouseEnter.bind(_this, _this.props.handleMouseEnter);
_this.handleMouseMove = _this.handleMouseMove.bind(_this, _this.props.handleMouseMove);
_this.handleMouseLeave = _this.handleMouseLeave.bind(_this, _this.props.handleMouseLeave);
return _this;
}
_createClass(MagicHover, [{
key: "componentDidMount",
value: function componentDidMount() {
this.element = (0, _reactDom.findDOMNode)(this);
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
clearTimeout(this.transitionTimeout);
cancelAnimationFrame(this.updateCall);
}
}, {
key: "handleMouseEnter",
value: function handleMouseEnter() {
var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
var e = arguments[1];
this.updateElementPosition();
this.setTransition();
return cb(e);
}
}, {
key: "reset",
value: function reset() {
var _this2 = this;
window.requestAnimationFrame(function () {
_this2.setState(function (prevState) {
return {
style: _extends({}, prevState.style, {
transform: "perspective(" + _this2.settings.perspective + "px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1) translate(0, 0) rotate(0)"
})
};
});
});
}
}, {
key: "handleMouseMove",
value: function handleMouseMove() {
var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
var e = arguments[1];
e.persist();
if (this.updateCall !== null) {
window.cancelAnimationFrame(this.updateCall);
}
this.event = e;
this.updateCall = requestAnimationFrame(this.update.bind(this, e));
return cb(e);
}
}, {
key: "setTransition",
value: function setTransition() {
var _this3 = this;
clearTimeout(this.transitionTimeout);
this.setState(function (prevState) {
return {
style: _extends({}, prevState.style, {
transition: _this3.settings.speed + "ms " + _this3.settings.easing
})
};
});
this.transitionTimeout = setTimeout(function () {
_this3.setState(function (prevState) {
return {
style: _extends({}, prevState.style, {
transition: ""
})
};
});
}, this.settings.speed);
}
}, {
key: "handleMouseLeave",
value: function handleMouseLeave() {
var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
var e = arguments[1];
this.setTransition();
if (this.settings.reset) {
this.reset();
}
return cb(e);
}
}, {
key: "getValues",
value: function getValues(e) {
var x = (e.nativeEvent.clientX - this.left) / this.width;
var y = (e.nativeEvent.clientY - this.top) / this.height;
var _x = Math.min(Math.max(x, 0), 1);
var _y = Math.min(Math.max(y, 0), 1);
var tiltX = (this.reverse * (this.settings.max / 2 - _x * this.settings.max)).toFixed(2);
var tiltY = (this.reverse * (_y * this.settings.max - this.settings.max / 2)).toFixed(2);
var percentageX = _x * 100;
var percentageY = _y * 100;
return {
tiltX: tiltX,
tiltY: tiltY,
percentageX: percentageX,
percentageY: percentageY
};
}
}, {
key: "updateElementPosition",
value: function updateElementPosition() {
var rect = this.element.getBoundingClientRect();
this.width = this.element.offsetWidth;
this.height = this.element.offsetHeight;
this.left = rect.left;
this.top = rect.top;
}
}, {
key: "update",
value: function update(e) {
var _this4 = this;
var values = this.getValues(e);
this.setState(function (prevState) {
return {
style: _extends({}, prevState.style, {
transform: "\n perspective(" + _this4.settings.perspective + "px) \n rotateX(" + (-_this4.settings.axis === "x" ? 0 : values.tiltY / 2) + "deg) \n rotateY(" + (-_this4.settings.axis === "y" ? 0 : values.tiltX / 2) + "deg)\n scale3d(" + _this4.settings.scale.x + ", " + _this4.settings.scale.y + ", " + _this4.settings.scale.z + ")\n translate(" + _this4.settings.translate.x + "px, " + _this4.settings.translate.y + "px)\n rotate(" + _this4.settings.rotate + "deg)\n "
})
};
});
this.updateCall = null;
}
}, {
key: "render",
value: function render() {
var style = _extends({}, this.props.style, this.state.style);
return _react2.default.createElement(
"div",
{
style: style,
className: this.props.className,
onMouseEnter: this.handleMouseEnter,
onMouseMove: this.handleMouseMove,
onMouseLeave: this.handleMouseLeave
},
this.props.children
);
}
}]);
return MagicHover;
}(_react.Component);
exports.default = MagicHover;