1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
const {
createSummaryGraphPathStringFunction,
SummaryGraphHelper,
} = require("resource://devtools/client/inspector/animation/utils/graph-helper.js");
const TimingPath = require("resource://devtools/client/inspector/animation/components/graph/TimingPath.js");
class ComputedTimingPath extends TimingPath {
static get propTypes() {
return {
animation: PropTypes.object.isRequired,
durationPerPixel: PropTypes.number.isRequired,
keyframes: PropTypes.object.isRequired,
offset: PropTypes.number.isRequired,
opacity: PropTypes.number.isRequired,
simulateAnimation: PropTypes.func.isRequired,
totalDuration: PropTypes.number.isRequired,
};
}
render() {
const {
animation,
durationPerPixel,
keyframes,
offset,
opacity,
simulateAnimation,
totalDuration,
} = this.props;
const { state } = animation;
const effectTiming = Object.assign({}, state, {
iterations: state.iterationCount ? state.iterationCount : Infinity,
});
// Create new keyframes for opacity as computed style.
// The reason why we use computed value instead of computed timing progress is to
// include the easing in keyframes as well. Although the computed timing progress
// is not affected by the easing in keyframes at all, computed value reflects that.
const frames = keyframes.map(keyframe => {
return {
opacity: keyframe.offset,
offset: keyframe.offset,
easing: keyframe.easing,
};
});
const simulatedAnimation = simulateAnimation(frames, effectTiming, true);
if (!simulatedAnimation) {
return null;
}
const simulatedElement = simulatedAnimation.effect.target;
const win = simulatedElement.ownerGlobal;
const endTime = simulatedAnimation.effect.getComputedTiming().endTime;
// Set the underlying opacity to zero so that if we sample the animation's output
// during the delay phase and it is not filling backwards, we get zero.
simulatedElement.style.opacity = 0;
const getValueFunc = time => {
if (time < 0) {
return 0;
}
simulatedAnimation.currentTime = time < endTime ? time : endTime;
return win.getComputedStyle(simulatedElement).opacity;
};
const toPathStringFunc = createSummaryGraphPathStringFunction(
endTime,
state.playbackRate
);
const helper = new SummaryGraphHelper(
state,
keyframes,
totalDuration,
durationPerPixel,
getValueFunc,
toPathStringFunc
);
return dom.g(
{
className: "animation-computed-timing-path",
style: { opacity },
transform: `translate(${offset})`,
},
super.renderGraph(state, helper)
);
}
}
module.exports = ComputedTimingPath;
|