react-dollyzoom-effect
Version:
A React component for applying a dollyzoom effect to a layout.
436 lines (415 loc) • 14.2 kB
JavaScript
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(["exports", "react", "react-dom", "velocity-react", "velocity-animate", "lodash", "jquery"], factory);
} else if (typeof exports !== "undefined") {
factory(exports, require("react"), require("react-dom"), require("velocity-react"), require("velocity-animate"), require("lodash"), require("jquery"));
} else {
var mod = {
exports: {}
};
factory(mod.exports, global.react, global.reactDom, global.velocityReact, global.velocityAnimate, global.lodash, global.jquery);
global.index = mod.exports;
}
})(this, function (exports, _react, _reactDom, _velocityReact, _velocityAnimate, _lodash, _jquery) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react2 = _interopRequireDefault(_react);
var _reactDom2 = _interopRequireDefault(_reactDom);
var _lodash2 = _interopRequireDefault(_lodash);
var _jquery2 = _interopRequireDefault(_jquery);
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-dollyzoom:problem::updateState:", event);
}
}
function watch(Testfunction) {
var watchCore = {
"Match": function Match(Target, Complete, ExpireAt) {
var intervalCount = 0;
var maximumAttempts = ExpireAt !== undefined ? ExpireAt : 2000;
//
var watchInterval = setInterval(function () {
if (Testfunction() === Target) {
Complete();
//
clearInterval(watchInterval);
}
if (intervalCount >= maximumAttempts) {
console.warn("react-dollyzoom.js::watch::exceeded watch limit timeout::action halted.");
//
clearInterval(watchInterval);
}
intervalCount++;
}, 1);
//
}
};
//
return watchCore;
}
//
//*************************
//*************************
// Exports
//
var Dollyzoom = function (_Component) {
_inherits(Dollyzoom, _Component);
//*************************
//*************************
// props
//
// props.Portal.Distort.Depth
// props.Portal.Distort.Perspective
// props.Portal.Distort.Blurfactor
// props.Portal.Distort.Fade
// props.Portal.Distort.Zoom
//
// props.Portal.Morph.Apply.Easing
// props.Portal.Morph.Apply.Duration
//
// props.Portal.Morph.Restore.Easing
// props.Portal.Morph.Restore.Duration
//
// props.Ready
//
//*************************
//*************************
// Standard Methods
//
function Dollyzoom(props) {
_classCallCheck(this, Dollyzoom);
return _possibleConstructorReturn(this, (Dollyzoom.__proto__ || Object.getPrototypeOf(Dollyzoom)).call(this, props));
}
_createClass(Dollyzoom, [{
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;
//
updateState(scopeProxy, {
"Ready": false,
"Portal": {
"Subject": null,
"Velocity": {
"Profile": {
"runOnMount": false
}
}
}
});
}
}, {
key: "componentWillUpdate",
value: function componentWillUpdate() {
// empty
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
var scopeProxy = this;
//
window.requestAnimationFrame(function () {
if (scopeProxy.state !== undefined && scopeProxy.state.Ready === false) {
updateState(scopeProxy, {
"Ready": true
});
scopeProxy.props.Ready(scopeProxy.props.children);
}
});
}
}, {
key: "render",
value: function render() {
var scopeProxy = this;
var dollyzoomportalClassname = this.props.className;
var currentTargetSelector = _lodash2.default.has(this, "state.Target.Selector") ? this.state.Target.Selector : null;
//
var dollyzoomportalStyle = {
"transform-style": "preserve-3d",
"perspective": "1000px"
};
//
var portalmorphProfileOnmount = {
"runOnMount": false
};
//
var portalmorphStyle = {
"display": "block",
"position": "absolute",
"visibility": "hidden",
"opacity": "0",
"top": "0",
"left": "0",
"width": "0",
"height": "0"
};
//
var portalmorphProfile = _lodash2.default.has(this, "state.Portal.Velocity.Profile") ? this.state.Portal.Velocity.Profile : portalmorphProfileOnmount;
//
var domParcel = _react2.default.createElement(
"div",
{ id: "dollyzoom-portal-container", ref: "dollyzoomportal", className: dollyzoomportalClassname, style: dollyzoomportalStyle },
this.props.children,
_react2.default.createElement(
_velocityReact.VelocityComponent,
portalmorphProfile,
_react2.default.createElement("div", { id: "portal-morph-container", ref: "portalmorph", style: portalmorphStyle })
)
);
//
return domParcel;
}
}, {
key: "setListeners",
value: function setListeners() {
var scopeProxy = this;
//
}
}, {
key: "dollyzoomApply",
value: function dollyzoomApply(applyParcel) {
var scopeProxy = this;
var subjectId = applyParcel.Subject;
var currentSubject = scopeProxy.state.Portal.Subject;
var completeCallback = applyParcel.Complete;
var distortDepth = this.props.Portal.Distort.Depth;
var distortBlurfactor = this.props.Portal.Distort.Blurfactor;
var distortFade = this.props.Portal.Distort.Fade;
var distortZoom = this.props.Portal.Distort.Zoom;
var morphEasing = this.props.Portal.Morph.Apply.Easing;
var morphDuration = this.props.Portal.Morph.Apply.Duration;
var distortDepthUnit = distortDepth.match(/([A-Z,a-z])\w+/g)[0];
var distortBlurUnit = distortBlurfactor.match(/([A-Z,a-z])\w+/g)[0];
var initialChildelementScale = 1;
var totalElements = this.props.children.length;
//
var childElements = this.props.children.map(function (childItem) {
var childId = childItem.props.id;
var childElement = document.getElementById(childId);
//
return childElement;
});
//
var portalProfile = {
"duration": morphDuration,
"easing": morphEasing,
"runOnMount": false,
"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. This must be avoided so that the
// rotation of the sections does not revert to its original
// rotation value.
//
var progressValue = elements[0].style.opacity > 0 ? parseFloat(elements[0].style.opacity) : 1;
var translateValue = (parseInt(distortDepth) * progressValue).toString().concat(distortDepthUnit);
var blurValue = (Math.abs(parseInt(distortDepth)) * progressValue * parseFloat(distortBlurfactor)).toString().concat(distortBlurUnit);
var opacityValue = 1 - (1 - distortFade) * progressValue;
var grayscaleValue = ((1 - distortFade) * progressValue * 100).toString().concat("%");
var zoomValue = (parseFloat(distortZoom) - parseFloat(initialChildelementScale)) * progressValue + parseFloat(initialChildelementScale);
var transformValue = "translateZ(".concat(translateValue, ")");
//
for (var elementCount = 0; elementCount < totalElements; elementCount++) {
if (childElements[elementCount].id !== subjectId) {
Object.assign(childElements[elementCount].style, {
"opacity": opacityValue,
"filter": "blur(".concat(blurValue, ") grayscale(", grayscaleValue, ")"),
"transform": transformValue
});
} else {
Object.assign(childElements[elementCount].style, {
"transform": "scale(".concat(zoomValue.toString())
});
}
}
},
"complete": function complete(event) {
completeCallback(subjectId);
}
};
//
if (currentSubject === null) {
updateState(scopeProxy, {
"Portal": {
"Subject": subjectId,
"Velocity": {
"Profile": portalProfile
}
}
});
} else {
scopeProxy.dollyzoomRestore(function (subjectId) {
// empty
});
}
}
}, {
key: "dollyzoomRestore",
value: function dollyzoomRestore(restoreCallback) {
var scopeProxy = this;
var subjectId = scopeProxy.state.Portal.Subject;
var distortDepth = this.props.Portal.Distort.Depth;
var distortBlurfactor = this.props.Portal.Distort.Blurfactor;
var distortFade = this.props.Portal.Distort.Fade;
var distortZoom = this.props.Portal.Distort.Zoom;
var morphEasing = this.props.Portal.Morph.Apply.Easing;
var morphDuration = this.props.Portal.Morph.Apply.Duration;
var distortDepthUnit = distortDepth.match(/([A-Z,a-z])\w+/g)[0];
var distortBlurUnit = distortBlurfactor.match(/([A-Z,a-z])\w+/g)[0];
var initialChildelementScale = 1;
var totalElements = this.props.children.length;
//
var childElements = this.props.children.map(function (childItem) {
var childId = childItem.props.id;
var childElement = document.getElementById(childId);
//
return childElement;
});
//
var portalProfile = {
"duration": morphDuration,
"easing": morphEasing,
"runOnMount": false,
"animation": {
"opacity": 0
},
"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. This must be avoided so that the
// rotation of the sections does not revert to its original
// rotation value.
//
var progressValue = elements[0].style.opacity > 0 ? parseFloat(elements[0].style.opacity) : 0;
var translateValue = (parseInt(distortDepth) * progressValue).toString().concat(distortDepthUnit);
var blurValue = (Math.abs(parseInt(distortDepth)) * progressValue * parseFloat(distortBlurfactor)).toString().concat(distortBlurUnit);
var opacityValue = 1 - (1 - distortFade) * progressValue;
var grayscaleValue = ((1 - distortFade) * progressValue * 100).toString().concat("%");
var zoomValue = (parseFloat(distortZoom) - parseFloat(initialChildelementScale)) * progressValue + parseFloat(initialChildelementScale);
var transformValue = "translateZ(".concat(translateValue, ")");
//
for (var elementCount = 0; elementCount < totalElements; elementCount++) {
if (childElements[elementCount].id !== subjectId) {
Object.assign(childElements[elementCount].style, {
"opacity": opacityValue,
"filter": "blur(".concat(blurValue, ") grayscale(", grayscaleValue, ")"),
"transform": transformValue
});
} else {
Object.assign(childElements[elementCount].style, {
"transform": "scale(".concat(zoomValue.toString())
});
}
}
},
"complete": function complete(event) {
restoreCallback(subjectId);
}
};
//
updateState(scopeProxy, {
"Portal": {
"Subject": null,
"Velocity": {
"Profile": portalProfile
}
}
});
}
}]);
return Dollyzoom;
}(_react.Component);
Dollyzoom.contextTypes = {}
// empty
//
;
exports.default = Dollyzoom;
});