react-mdc-web
Version:
React web components for Material Design
133 lines (116 loc) • 4.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getTransformPropertyName = getTransformPropertyName;
exports.clamp = clamp;
exports.bezierProgress = bezierProgress;
/**
* Copyright 2016 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var storedTransformPropertyName_ = void 0;
// Returns the name of the correct transform property to use on the current browser.
function getTransformPropertyName(globalObj) {
var forceRefresh = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (storedTransformPropertyName_ === undefined || forceRefresh) {
var el = globalObj.document.createElement('div');
var transformPropertyName = 'transform' in el.style ? 'transform' : 'webkitTransform';
storedTransformPropertyName_ = transformPropertyName;
}
return storedTransformPropertyName_;
}
// Clamps a value between the minimum and the maximum, returning the clamped value.
function clamp(value) {
var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
return Math.min(max, Math.max(min, value));
}
// Returns the easing value to apply at time t, for a given cubic bezier curve.
// Control points P0 and P3 are assumed to be (0,0) and (1,1), respectively.
// Paramters are as follows:
// - time: The current time in the animation, scaled between 0 and 1.
// - x1: The x value of control point P1.
// - y1: The y value of control point P1.
// - x2: The x value of control point P2.
// - y2: The y value of control point P2.
function bezierProgress(time, x1, y1, x2, y2) {
return getBezierCoordinate_(solvePositionFromXValue_(time, x1, x2), y1, y2);
}
// Compute a single coordinate at a position point between 0 and 1.
// c1 and c2 are the matching coordinate on control points P1 and P2, respectively.
// Control points P0 and P3 are assumed to be (0,0) and (1,1), respectively.
// Adapted from https://github.com/google/closure-library/blob/master/closure/goog/math/bezier.js.
function getBezierCoordinate_(t, c1, c2) {
// Special case start and end.
if (t === 0 || t === 1) {
return t;
}
// Step one - from 4 points to 3
var ic0 = t * c1;
var ic1 = c1 + t * (c2 - c1);
var ic2 = c2 + t * (1 - c2);
// Step two - from 3 points to 2
ic0 += t * (ic1 - ic0);
ic1 += t * (ic2 - ic1);
// Final step - last point
return ic0 + t * (ic1 - ic0);
}
// Project a point onto the Bezier curve, from a given X. Calculates the position t along the curve.
// Adapted from https://github.com/google/closure-library/blob/master/closure/goog/math/bezier.js.
function solvePositionFromXValue_(xVal, x1, x2) {
var EPSILON = 1e-6;
var MAX_ITERATIONS = 8;
if (xVal <= 0) {
return 0;
} else if (xVal >= 1) {
return 1;
}
// Initial estimate of t using linear interpolation.
var t = xVal;
// Try gradient descent to solve for t. If it works, it is very fast.
var tMin = 0;
var tMax = 1;
var value = 0;
for (var i = 0; i < MAX_ITERATIONS; i++) {
value = getBezierCoordinate_(t, x1, x2);
var derivative = (getBezierCoordinate_(t + EPSILON, x1, x2) - value) / EPSILON;
if (Math.abs(value - xVal) < EPSILON) {
return t;
} else if (Math.abs(derivative) < EPSILON) {
break;
} else {
if (value < xVal) {
tMin = t;
} else {
tMax = t;
}
t -= (value - xVal) / derivative;
}
}
// If the gradient descent got stuck in a local minimum, e.g. because
// the derivative was close to 0, use a Dichotomy refinement instead.
// We limit the number of interations to 8.
for (var _i = 0; Math.abs(value - xVal) > EPSILON && _i < MAX_ITERATIONS; _i++) {
if (value < xVal) {
tMin = t;
t = (t + tMax) / 2;
} else {
tMax = t;
t = (t + tMin) / 2;
}
value = getBezierCoordinate_(t, x1, x2);
}
return t;
}