SummaryGraph.js (5983B)
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 { 8 createFactory, 9 PureComponent, 10 } = require("resource://devtools/client/shared/vendor/react.mjs"); 11 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); 12 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs"); 13 14 const AnimationName = createFactory( 15 require("resource://devtools/client/inspector/animation/components/graph/AnimationName.js") 16 ); 17 const DelaySign = createFactory( 18 require("resource://devtools/client/inspector/animation/components/graph/DelaySign.js") 19 ); 20 const EndDelaySign = createFactory( 21 require("resource://devtools/client/inspector/animation/components/graph/EndDelaySign.js") 22 ); 23 const SummaryGraphPath = createFactory( 24 require("resource://devtools/client/inspector/animation/components/graph/SummaryGraphPath.js") 25 ); 26 27 const { 28 getFormattedTitle, 29 getFormatStr, 30 getStr, 31 numberWithDecimals, 32 } = require("resource://devtools/client/inspector/animation/utils/l10n.js"); 33 34 class SummaryGraph extends PureComponent { 35 static get propTypes() { 36 return { 37 animation: PropTypes.object.isRequired, 38 getAnimatedPropertyMap: PropTypes.func.isRequired, 39 selectAnimation: PropTypes.func.isRequired, 40 simulateAnimation: PropTypes.func.isRequired, 41 timeScale: PropTypes.object.isRequired, 42 }; 43 } 44 45 constructor(props) { 46 super(props); 47 48 this.onClick = this.onClick.bind(this); 49 } 50 51 onClick(event) { 52 event.stopPropagation(); 53 this.props.selectAnimation(this.props.animation); 54 } 55 56 getTitleText(state) { 57 const getTime = time => 58 getFormatStr("player.timeLabel", numberWithDecimals(time / 1000, 2)); 59 const getTimeOrInfinity = time => 60 time === Infinity ? getStr("player.infiniteDurationText") : getTime(time); 61 62 let text = ""; 63 64 // Adding the name. 65 text += getFormattedTitle(state); 66 text += "\n"; 67 68 // Adding the delay. 69 if (state.delay) { 70 text += getStr("player.animationDelayLabel") + " "; 71 text += getTime(state.delay); 72 text += "\n"; 73 } 74 75 // Adding the duration. 76 text += getStr("player.animationDurationLabel") + " "; 77 text += getTimeOrInfinity(state.duration); 78 text += "\n"; 79 80 // Adding the endDelay. 81 if (state.endDelay) { 82 text += getStr("player.animationEndDelayLabel") + " "; 83 text += getTime(state.endDelay); 84 text += "\n"; 85 } 86 87 // Adding the iteration count (the infinite symbol, or an integer). 88 if (state.iterationCount !== 1) { 89 text += getStr("player.animationIterationCountLabel") + " "; 90 text += 91 state.iterationCount || getStr("player.infiniteIterationCountText"); 92 text += "\n"; 93 } 94 95 // Adding the iteration start. 96 if (state.iterationStart !== 0) { 97 text += getFormatStr( 98 "player.animationIterationStartLabel2", 99 state.iterationStart, 100 getTimeOrInfinity(state.iterationStart * state.duration) 101 ); 102 text += "\n"; 103 } 104 105 // Adding the easing if it is not "linear". 106 if (state.easing && state.easing !== "linear") { 107 text += getStr("player.animationOverallEasingLabel") + " "; 108 text += state.easing; 109 text += "\n"; 110 } 111 112 // Adding the fill mode. 113 if (state.fill && state.fill !== "none") { 114 text += getStr("player.animationFillLabel") + " "; 115 text += state.fill; 116 text += "\n"; 117 } 118 119 // Adding the direction mode if it is not "normal". 120 if (state.direction && state.direction !== "normal") { 121 text += getStr("player.animationDirectionLabel") + " "; 122 text += state.direction; 123 text += "\n"; 124 } 125 126 // Adding the playback rate if it's different than 1. 127 if (state.playbackRate !== 1) { 128 text += getStr("player.animationRateLabel") + " "; 129 text += state.playbackRate; 130 text += "\n"; 131 } 132 133 // Adding the animation-timing-function 134 // if it is not "ease" which is default value for CSS Animations. 135 if ( 136 state.animationTimingFunction && 137 state.animationTimingFunction !== "ease" 138 ) { 139 text += getStr("player.animationTimingFunctionLabel") + " "; 140 text += state.animationTimingFunction; 141 text += "\n"; 142 } 143 144 // Adding a note that the animation is running on the compositor thread if 145 // needed. 146 if (state.propertyState) { 147 if ( 148 state.propertyState.every(propState => propState.runningOnCompositor) 149 ) { 150 text += getStr("player.allPropertiesOnCompositorTooltip"); 151 } else if ( 152 state.propertyState.some(propState => propState.runningOnCompositor) 153 ) { 154 text += getStr("player.somePropertiesOnCompositorTooltip"); 155 } 156 } else if (state.isRunningOnCompositor) { 157 text += getStr("player.runningOnCompositorTooltip"); 158 } 159 160 return text; 161 } 162 163 render() { 164 const { animation, getAnimatedPropertyMap, simulateAnimation, timeScale } = 165 this.props; 166 167 const { iterationCount } = animation.state; 168 const { delay, endDelay } = animation.state.absoluteValues; 169 170 return dom.div( 171 { 172 className: 173 "animation-summary-graph" + 174 (animation.state.isRunningOnCompositor ? " compositor" : ""), 175 onClick: this.onClick, 176 title: this.getTitleText(animation.state), 177 }, 178 SummaryGraphPath({ 179 animation, 180 getAnimatedPropertyMap, 181 simulateAnimation, 182 timeScale, 183 }), 184 delay 185 ? DelaySign({ 186 animation, 187 timeScale, 188 }) 189 : null, 190 iterationCount && endDelay 191 ? EndDelaySign({ 192 animation, 193 timeScale, 194 }) 195 : null, 196 animation.state.name 197 ? AnimationName({ 198 animation, 199 }) 200 : null 201 ); 202 } 203 } 204 205 module.exports = SummaryGraph;