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