react-spinnable
Version:
A React component designed to add the ability to easily rotate a target element.
411 lines (390 loc) • 13.3 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(["exports", "react", "react-dom", "react-draggable", "velocity-react", "velocity-animate", "lodash"], factory);
} else if (typeof exports !== "undefined") {
factory(exports, require("react"), require("react-dom"), require("react-draggable"), require("velocity-react"), require("velocity-animate"), require("lodash"));
} else {
var mod = {
exports: {}
};
factory(mod.exports, global.react, global.reactDom, global.reactDraggable, global.velocityReact, global.velocityAnimate, global.lodash);
global.index = mod.exports;
}
})(this, function (exports, _react, _reactDom, _reactDraggable, _velocityReact, _velocityAnimate, _lodash) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react2 = _interopRequireDefault(_react);
var _reactDom2 = _interopRequireDefault(_reactDom);
var _reactDraggable2 = _interopRequireDefault(_reactDraggable);
var _lodash2 = _interopRequireDefault(_lodash);
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");
}
}
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;
};
}();
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;
}
//
//*************************
//*************************
// Nonpublished Imports
//
function updateState(ScopeProxy, Parcel) {
var existingState = ScopeProxy.state !== null ? _lodash2.default.cloneDeep(ScopeProxy.state) : {};
var adjustedState = _lodash2.default.merge(existingState, _lodash2.default.cloneDeep(Parcel));
//
try {
ScopeProxy.setState(adjustedState);
} catch (event) {
console.warn("::react-spinnable:problem::updateState:", event);
}
}
//
//*************************
//*************************
// Exports
//
var Spinnable = function (_Component) {
_inherits(Spinnable, _Component);
//*************************
//*************************
// Standard Methods
//
function Spinnable(props) {
_classCallCheck(this, Spinnable);
return _possibleConstructorReturn(this, (Spinnable.__proto__ || Object.getPrototypeOf(Spinnable)).call(this, props));
}
_createClass(Spinnable, [{
key: "getChildContext",
value: function getChildContext() {
// empty
}
}, {
key: "getInitialState",
value: function getInitialState() {
return {};
}
}, {
key: "componentWillMount",
value: function componentWillMount() {
// empty
}
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
// empty
}
}, {
key: "componentDidMount",
value: function componentDidMount() {
var scopeProxy = this;
//
scopeProxy.setState({
"Ready": false,
"Portal": {
"Velocity": {
"Profile": {
"runOnMount": false
}
},
"Rotation": {
"X": 0,
"Y": 0,
"Z": 0
}
}
});
}
}, {
key: "componentWillUpdate",
value: function componentWillUpdate() {
// empty
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
var scopeProxy = this;
//
window.requestAnimationFrame(function () {
if (scopeProxy.state !== null && scopeProxy.state !== undefined && scopeProxy.state.Ready === false) {
var spinnableState = {
"Ready": true
};
//
scopeProxy.setState(spinnableState);
scopeProxy.props.Report.Ready(scopeProxy.props.children);
}
});
}
}, {
key: "render",
value: function render() {
var scopeProxy = this;
var spinnabletargetportalClassname = scopeProxy.props.children.props.className;
var portalPerspective = scopeProxy.props.Portal.Distort.Perspective;
var portalmorphProfile = _lodash2.default.has(scopeProxy, "state.Portal.Velocity.Profile") ? scopeProxy.state.Portal.Velocity.Profile : null;
var adjustedChildTransform = "translateX(0)".concat(" translateY(0)", " translateZ(0)", " rotateX(0)", " rotateY(0)", " rotateZ(0)");
//
var portalmorphStyle = {
"display": "inline-block",
"position": "absolute",
"visibility": "0",
"left": "0",
"opacity": "0",
"width": "0",
"height": "0"
};
//
var spinnabletargetportalStyle = {
"margin": "0",
"padding": "0",
"perspective": portalPerspective,
"transform-style": "preserve-3d",
"border": "none",
"background": "none",
"background-attachment": "scroll",
"background-blend-mode": "normal",
"bakcground-clip": "border-box",
"background-image": "none",
"background-origin": "padding-box",
"background-position": "0% 0%",
"background-repeat": "repeat",
"background-size": "auto",
"background-color": "transparent"
};
//
this.props.children.props.style = this.props.children.props.style !== undefined ? this.props.children.props.style : {};
//
Object.assign(this.props.children.props.style, {
"top": "0",
"bottom": "0",
"left": "0",
"right": "0",
"width": "100%",
"height": "100%",
"margin": "0",
"transform": adjustedChildTransform
});
return _react2.default.createElement(
"div",
{ id: "spinnable-portal-container", className: spinnabletargetportalClassname, style: spinnabletargetportalStyle },
this.props.children,
_react2.default.createElement(
_velocityReact.VelocityComponent,
portalmorphProfile,
_react2.default.createElement("div", { id: "portal-morph-container", ref: "portalmorph", style: portalmorphStyle })
)
);
}
}, {
key: "spinnableApply",
value: function spinnableApply(rotationAxis) {
var scopeProxy = this;
var targetId = this.props.children.props.id;
var targetElement = document.getElementById(targetId);
var rotateEasing = scopeProxy.props.Portal.Rotate.Easing;
var rotateDuration = parseFloat(scopeProxy.props.Portal.Rotate.Duration);
var rotateDisplacement = parseFloat(scopeProxy.props.Portal.Rotate.Displace);
var rotationaxisIsValid = rotationAxis.toLowerCase() === "x" && scopeProxy.state.Portal.Rotation.X === 0 || rotationAxis.toLowerCase() === "y" && scopeProxy.state.Portal.Rotation.Y === 0 || rotationAxis.toLowerCase() === "z" && scopeProxy.state.Portal.Rotation.Z === 0 ? true : false;
var portalRotationX = rotationAxis.toLowerCase() === "x" ? rotateDisplacement : scopeProxy.state.Portal.Rotation.X;
var portalRotationY = rotationAxis.toLowerCase() === "y" ? rotateDisplacement : scopeProxy.state.Portal.Rotation.Y;
var portalRotationZ = rotationAxis.toLowerCase() === "z" ? rotateDisplacement : scopeProxy.state.Portal.Rotation.Z;
//
var rotateProfile = {
"runOnMount": false,
"easing": rotateEasing,
"duration": rotateDuration,
"animation": {
"opacity": 1
},
"progress": function progress(elements, complete, remaining, start, tweenValue) {
// http://velocityjs.org/
// The value of tweenValue is being reported as null for
// unknown reasons. In order to tween the rotation according
// to the easing, the actual value of the opacity must be
// used as it tweens from zero to one. Additionally, at the
// completion of the tween, the value of the opacity is set
// back to zero by Velocity.
//
var progressValue = parseFloat(elements[0].style.opacity);
var rotateAngle = progressValue * rotateDisplacement;
var targetElement = document.getElementById(targetId);
var targetTransform = "rotate".concat(rotationAxis.toUpperCase(), "(", rotateAngle, "deg)");
//
Object.assign(targetElement.style, {
"transform": targetTransform
});
scopeProxy.props.Report.Change(targetElement);
},
"complete": function complete(event) {
var completeProfile = {
"runOnMount": false,
"easing": rotateEasing,
"duration": 10,
"animation": {
"opacity": 0
},
"progress": function progress(elements, complete, remaining, start, tweenValue) {
// empty
},
"complete": function complete(event) {
scopeProxy.props.Report.Complete(targetElement);
}
};
//
updateState(scopeProxy, {
"Portal": {
"Velocity": {
"Profile": completeProfile
},
"Rotation": {
"X": portalRotationX,
"Y": portalRotationY,
"Z": portalRotationZ
}
}
});
}
};
//
if (rotationaxisIsValid === true) {
updateState(scopeProxy, {
"Portal": {
"Velocity": {
"Profile": rotateProfile
}
}
});
}
scopeProxy.props.Report.Start(targetElement);
}
}, {
key: "spinnableReset",
value: function spinnableReset(rotationAxis) {
var scopeProxy = this;
var targetId = this.props.children.props.id;
var targetElement = document.getElementById(targetId);
var rotateEasing = scopeProxy.props.Portal.Rotate.Easing;
var rotateDuration = parseFloat(scopeProxy.props.Portal.Rotate.Duration);
var rotationaxisIsValid = rotationAxis.toLowerCase() === "x" || rotationAxis.toLowerCase() === "y" || rotationAxis.toLowerCase() === "z" ? true : false;
var rotateDisplacement = rotationaxisIsValid === true ? parseFloat(scopeProxy.state.Portal.Rotation[rotationAxis.toUpperCase()]) : 0;
var portalRotationX = rotationAxis.toLowerCase() === "x" ? 0 : scopeProxy.state.Portal.Rotation.X;
var portalRotationY = rotationAxis.toLowerCase() === "y" ? 0 : scopeProxy.state.Portal.Rotation.Y;
var portalRotationZ = rotationAxis.toLowerCase() === "z" ? 0 : scopeProxy.state.Portal.Rotation.Z;
//
var rotateProfile = {
"runOnMount": false,
"easing": rotateEasing,
"duration": rotateDuration,
"animation": {
"opacity": 1
},
"progress": function progress(elements, complete, remaining, start, tweenValue) {
// http://velocityjs.org/
// The value of tweenValue is being reported as null for
// unknown reasons. In order to tween the rotation according
// to the easing, the actual value of the opacity must be
// used as it tweens from zero to one. Additionally, at the
// completion of the tween, the value of the opacity is set
// back to zero by Velocity.
//
var progressValue = parseFloat(elements[0].style.opacity);
var rotateAngle = rotateDisplacement - progressValue * rotateDisplacement;
var targetElement = document.getElementById(targetId);
var targetTransform = "rotate".concat(rotationAxis.toUpperCase(), "(", rotateAngle, "deg)");
//
Object.assign(targetElement.style, {
"transform": targetTransform
});
},
"complete": function complete(event) {
var completeProfile = {
"runOnMount": false,
"easing": rotateEasing,
"duration": 0,
"animation": {
"opacity": 0
},
"progress": function progress(elements, complete, remaining, start, tweenValue) {
// empty
},
"complete": function complete(event) {
// empty
}
};
//
updateState(scopeProxy, {
"Portal": {
"Velocity": {
"Profile": completeProfile
},
"Rotation": {
"X": portalRotationX,
"Y": portalRotationY,
"Z": portalRotationZ
}
}
});
}
};
//
if (rotationaxisIsValid === true) {
updateState(scopeProxy, {
"Portal": {
"Velocity": {
"Profile": rotateProfile
}
}
});
}
}
}]);
return Spinnable;
}(_react.Component);
Spinnable.contextTypes = {}
// empty
//
;
exports.default = Spinnable;
});