зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1210796 - Part 9: Add progress indicator. r=pbro
MozReview-Commit-ID: GRcj1tFIKZB --HG-- extra : rebase_source : be49edec53ba2068b59a9095a2faa0957fbd8c64
This commit is contained in:
Родитель
781c534bf5
Коммит
f9582a91b0
|
@ -48,6 +48,7 @@ AnimationDetails.prototype = {
|
||||||
this.unrender();
|
this.unrender();
|
||||||
this.containerEl = null;
|
this.containerEl = null;
|
||||||
this.serverTraits = null;
|
this.serverTraits = null;
|
||||||
|
this.progressIndicatorEl = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
unrender: function () {
|
unrender: function () {
|
||||||
|
@ -186,11 +187,21 @@ AnimationDetails.prototype = {
|
||||||
// Get animation type for each CSS properties.
|
// Get animation type for each CSS properties.
|
||||||
const animationTypes = yield this.getAnimationTypes(Object.keys(this.tracks));
|
const animationTypes = yield this.getAnimationTypes(Object.keys(this.tracks));
|
||||||
|
|
||||||
|
// Render progress indicator.
|
||||||
|
this.renderProgressIndicator();
|
||||||
// Render animated properties header.
|
// Render animated properties header.
|
||||||
this.renderAnimatedPropertiesHeader();
|
this.renderAnimatedPropertiesHeader();
|
||||||
// Render animated properties body.
|
// Render animated properties body.
|
||||||
this.renderAnimatedPropertiesBody(animationTypes);
|
this.renderAnimatedPropertiesBody(animationTypes);
|
||||||
|
|
||||||
|
// Create dummy animation to indicate the animation progress.
|
||||||
|
const timing = Object.assign({}, animation.state, {
|
||||||
|
iterations: animation.state.iterationCount
|
||||||
|
? animation.state.iterationCount : Infinity
|
||||||
|
});
|
||||||
|
this.dummyAnimation =
|
||||||
|
new this.win.Animation(new this.win.KeyframeEffect(null, null, timing), null);
|
||||||
|
|
||||||
// Useful for tests to know when rendering of all animation detail UIs
|
// Useful for tests to know when rendering of all animation detail UIs
|
||||||
// have been completed.
|
// have been completed.
|
||||||
this.emit("animation-detail-rendering-completed");
|
this.emit("animation-detail-rendering-completed");
|
||||||
|
@ -286,6 +297,44 @@ AnimationDetails.prototype = {
|
||||||
keyframesComponent.on("frame-selected", this.onFrameSelected);
|
keyframesComponent.on("frame-selected", this.onFrameSelected);
|
||||||
this.keyframeComponents.push(keyframesComponent);
|
this.keyframeComponents.push(keyframesComponent);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderProgressIndicator: function () {
|
||||||
|
// The wrapper represents the area which the indicator is displayable.
|
||||||
|
const progressIndicatorWrapperEl = createNode({
|
||||||
|
parent: this.containerEl,
|
||||||
|
attributes: {
|
||||||
|
"class": "track-container progress-indicator-wrapper"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.progressIndicatorEl = createNode({
|
||||||
|
parent: progressIndicatorWrapperEl,
|
||||||
|
attributes: {
|
||||||
|
"class": "progress-indicator"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
createNode({
|
||||||
|
parent: this.progressIndicatorEl,
|
||||||
|
attributes: {
|
||||||
|
"class": "progress-indicator-shape"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
indicateProgress: function (time) {
|
||||||
|
if (!this.progressIndicatorEl) {
|
||||||
|
// Not displayed yet.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const startTime = this.animation.state.previousStartTime || 0;
|
||||||
|
this.dummyAnimation.currentTime =
|
||||||
|
(time - startTime) * this.animation.state.playbackRate;
|
||||||
|
this.progressIndicatorEl.style.left =
|
||||||
|
`${ this.dummyAnimation.effect.getComputedTiming().progress * 100 }%`;
|
||||||
|
},
|
||||||
|
|
||||||
|
get win() {
|
||||||
|
return this.containerEl.ownerDocument.defaultView;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const {Task} = require("devtools/shared/task");
|
||||||
const EventEmitter = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
const {
|
const {
|
||||||
createNode,
|
createNode,
|
||||||
|
@ -58,6 +59,7 @@ function AnimationsTimeline(inspector, serverTraits) {
|
||||||
this.onAnimationSelected = this.onAnimationSelected.bind(this);
|
this.onAnimationSelected = this.onAnimationSelected.bind(this);
|
||||||
this.onWindowResize = this.onWindowResize.bind(this);
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
this.onFrameSelected = this.onFrameSelected.bind(this);
|
this.onFrameSelected = this.onFrameSelected.bind(this);
|
||||||
|
this.onTimelineDataChanged = this.onTimelineDataChanged.bind(this);
|
||||||
|
|
||||||
EventEmitter.decorate(this);
|
EventEmitter.decorate(this);
|
||||||
}
|
}
|
||||||
|
@ -273,6 +275,7 @@ AnimationsTimeline.prototype = {
|
||||||
this.details.off("frame-selected", this.onFrameSelected);
|
this.details.off("frame-selected", this.onFrameSelected);
|
||||||
this.details.unrender();
|
this.details.unrender();
|
||||||
this.animationsEl.innerHTML = "";
|
this.animationsEl.innerHTML = "";
|
||||||
|
this.off("timeline-data-changed", this.onTimelineDataChanged);
|
||||||
},
|
},
|
||||||
|
|
||||||
onWindowResize: function () {
|
onWindowResize: function () {
|
||||||
|
@ -290,7 +293,7 @@ AnimationsTimeline.prototype = {
|
||||||
}, TIMELINE_BACKGROUND_RESIZE_DEBOUNCE_TIMER);
|
}, TIMELINE_BACKGROUND_RESIZE_DEBOUNCE_TIMER);
|
||||||
},
|
},
|
||||||
|
|
||||||
onAnimationSelected: function (e, animation) {
|
onAnimationSelected: Task.async(function* (e, animation) {
|
||||||
let index = this.animations.indexOf(animation);
|
let index = this.animations.indexOf(animation);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
return;
|
return;
|
||||||
|
@ -324,10 +327,11 @@ AnimationsTimeline.prototype = {
|
||||||
selectedAnimationEl.classList.add("selected");
|
selectedAnimationEl.classList.add("selected");
|
||||||
this.animationDetailEl.style.display =
|
this.animationDetailEl.style.display =
|
||||||
this.animationDetailEl.dataset.defaultDisplayStyle;
|
this.animationDetailEl.dataset.defaultDisplayStyle;
|
||||||
this.details.render(animation);
|
yield this.details.render(animation);
|
||||||
|
this.onTimelineDataChanged(null, { time: this.currentTime || 0 });
|
||||||
this.animationAnimationNameEl.textContent = getFormattedAnimationTitle(animation);
|
this.animationAnimationNameEl.textContent = getFormattedAnimationTitle(animation);
|
||||||
this.emit("animation-selected", animation);
|
this.emit("animation-selected", animation);
|
||||||
},
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When a frame gets selected, move the scrubber to the corresponding position
|
* When a frame gets selected, move the scrubber to the corresponding position
|
||||||
|
@ -483,6 +487,9 @@ AnimationsTimeline.prototype = {
|
||||||
? TimeScale.minStartTime
|
? TimeScale.minStartTime
|
||||||
: documentCurrentTime);
|
: documentCurrentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To indicate the animation progress in AnimationDetails.
|
||||||
|
this.on("timeline-data-changed", this.onTimelineDataChanged);
|
||||||
},
|
},
|
||||||
|
|
||||||
isAtLeastOneAnimationPlaying: function () {
|
isAtLeastOneAnimationPlaying: function () {
|
||||||
|
@ -592,5 +599,12 @@ AnimationsTimeline.prototype = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onTimelineDataChanged: function (e, { time }) {
|
||||||
|
this.currentTime = time;
|
||||||
|
const indicateTime =
|
||||||
|
TimeScale.minStartTime === Infinity ? 0 : this.currentTime + TimeScale.minStartTime;
|
||||||
|
this.details.indicateProgress(indicateTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -381,18 +381,11 @@ function* clickOnAnimation(panel, index, shouldAlreadySelected) {
|
||||||
? "animation-already-selected"
|
? "animation-already-selected"
|
||||||
: "animation-selected");
|
: "animation-selected");
|
||||||
|
|
||||||
// If we're opening the animation, also wait for
|
|
||||||
// the animation-detail-rendering-completed event.
|
|
||||||
let onReady = shouldAlreadySelected
|
|
||||||
? Promise.resolve()
|
|
||||||
: timeline.details.once("animation-detail-rendering-completed");
|
|
||||||
|
|
||||||
info("Click on animation " + index + " in the timeline");
|
info("Click on animation " + index + " in the timeline");
|
||||||
let timeBlock = timeline.rootWrapperEl.querySelectorAll(".time-block")[index];
|
let timeBlock = timeline.rootWrapperEl.querySelectorAll(".time-block")[index];
|
||||||
EventUtils.sendMouseEvent({type: "click"}, timeBlock,
|
EventUtils.sendMouseEvent({type: "click"}, timeBlock,
|
||||||
timeBlock.ownerDocument.defaultView);
|
timeBlock.ownerDocument.defaultView);
|
||||||
|
|
||||||
yield onReady;
|
|
||||||
return yield onSelectionChanged;
|
return yield onSelectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
/* The color for other animation type */
|
/* The color for other animation type */
|
||||||
--other-border-color: var(--theme-graphs-bluegrey);
|
--other-border-color: var(--theme-graphs-bluegrey);
|
||||||
--other-background-color: #5e88b080;
|
--other-background-color: #5e88b080;
|
||||||
|
/* The color for progress indicator */
|
||||||
|
--progress-indicator-color: var(--theme-highlight-gray);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-light {
|
.theme-light {
|
||||||
|
@ -47,6 +49,8 @@
|
||||||
/* The color for other animation type */
|
/* The color for other animation type */
|
||||||
--other-border-color: var(--theme-graphs-bluegrey);
|
--other-border-color: var(--theme-graphs-bluegrey);
|
||||||
--other-background-color: #0072ab80;
|
--other-background-color: #0072ab80;
|
||||||
|
/* The color for progress indicator */
|
||||||
|
--progress-indicator-color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
@ -621,7 +625,6 @@ body {
|
||||||
height: 0;
|
height: 0;
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.keyframes .frame::before {
|
.keyframes .frame::before {
|
||||||
|
@ -755,3 +758,31 @@ body {
|
||||||
/* To display animation progress graph clealy when the scroll is bottom. */
|
/* To display animation progress graph clealy when the scroll is bottom. */
|
||||||
padding-bottom: calc(var(--timeline-animation-height) / 2);
|
padding-bottom: calc(var(--timeline-animation-height) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.animated-properties .progress-indicator-wrapper {
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-indicator-wrapper .progress-indicator {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-indicator-wrapper .progress-indicator .progress-indicator-shape {
|
||||||
|
position: fixed;
|
||||||
|
width: 0;
|
||||||
|
height: 100vh;
|
||||||
|
border-right: 1px solid var(--progress-indicator-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-indicator-wrapper .progress-indicator .progress-indicator-shape::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: -6px;
|
||||||
|
width: 1px;
|
||||||
|
border-top: 5px solid var(--progress-indicator-color);
|
||||||
|
border-left: 5px solid transparent;
|
||||||
|
border-right: 5px solid transparent;
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче