Bug 1358011 - Part 1: Handle frames() timing function. r?pbro
MozReview-Commit-ID: CGIZONHWaqu
--- a/devtools/client/animationinspector/graph-helper.js
+++ b/devtools/client/animationinspector/graph-helper.js
@@ -511,19 +511,25 @@ function appendPathElement(parentEl, pat
}
if (i + 1 === pathSegments.length) {
// We already create steps or cubic-bezier path string in previous.
break;
}
const nextPathSegment = pathSegments[i + 1];
- path += pathSegment.easing.startsWith("steps")
- ? createStepsPathString(pathSegment, nextPathSegment)
- : createCubicBezierPathString(pathSegment, nextPathSegment);
+ let createPathFunction;
+ if (pathSegment.easing.startsWith("steps")) {
+ createPathFunction = createStepsPathString;
+ } else if (pathSegment.easing.startsWith("frames")) {
+ createPathFunction = createFramesPathString;
+ } else {
+ createPathFunction = createCubicBezierPathString;
+ }
+ path += createPathFunction(pathSegment, nextPathSegment);
}
path += ` L${ pathSegments[pathSegments.length - 1].x },0`;
if (isClosePathNeeded) {
path += " Z";
}
// Append and return the path element.
return createSVGNode({
parent: parentEl,
@@ -589,16 +595,38 @@ function createStepsPathString(currentSe
}
if (!isStepStart) {
path += ` L${ nextSegment.x },${ nextSegment.y }`;
}
return path;
}
/**
+ * Create a path string to represents a frames function.
+ * @param {Object} currentSegment - e.g. { x: 0, y: 0, easing: "frames(2)" }
+ * @param {Object} nextSegment - e.g. { x: 1, y: 1 }
+ * @return {String} path string - e.g. "C 0.25 0.1, 0.25 1, 1 1"
+ */
+function createFramesPathString(currentSegment, nextSegment) {
+ const matches =
+ currentSegment.easing.match(/^frames\((\d+)\)/);
+ const framesNumber = parseInt(matches[1], 10);
+ const oneFrameX = (nextSegment.x - currentSegment.x) / framesNumber;
+ const oneFrameY = (nextSegment.y - currentSegment.y) / (framesNumber - 1);
+ let path = "";
+ for (let frame = 0; frame < framesNumber; frame++) {
+ const sx = currentSegment.x + frame * oneFrameX;
+ const ex = sx + oneFrameX;
+ const y = currentSegment.y + frame * oneFrameY;
+ path += ` L${ sx },${ y } L${ ex },${ y }`;
+ }
+ return path;
+}
+
+/**
* Create a path string to represents a bezier curve.
* @param {Object} currentSegment - e.g. { x: 0, y: 0, easing: "ease" }
* @param {Object} nextSegment - e.g. { x: 1, y: 1 }
* @return {String} path string - e.g. "C 0.25 0.1, 0.25 1, 1 1"
*/
function createCubicBezierPathString(currentSegment, nextSegment) {
const controlPoints = parseTimingFunction(currentSegment.easing);
if (!controlPoints) {
@@ -679,14 +707,14 @@ function getPreferredKeyframesProgressTh
exports.getPreferredKeyframesProgressThreshold = getPreferredKeyframesProgressThreshold;
/**
* Return preferred progress threshold to render summary graph.
* @param {String} - easing e.g. steps(2), linear and so on.
* @return {float} - preferred threshold.
*/
function getPreferredProgressThreshold(easing) {
- const stepFunction = easing.match(/steps\((\d+)/);
- return stepFunction
- ? 1 / (parseInt(stepFunction[1], 10) + 1)
+ const stepOrFramesFunction = easing.match(/(steps|frames)\((\d+)/);
+ return stepOrFramesFunction
+ ? 1 / (parseInt(stepOrFramesFunction[2], 10) + 1)
: DEFAULT_MIN_PROGRESS_THRESHOLD;
}
exports.getPreferredProgressThreshold = getPreferredProgressThreshold;