Commit e2f934fe authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

Add main-thread support for {start,end}ScrollOffset on ScrollTimelines

This CL changes the currentTime algorithm to respect the start and end
scroll offset specified for the ScrollTimeline. It does not change the
compositor logic - that is left for a followup.

https://wicg.github.io/scroll-animations/#dom-scrolltimeline-startscrolloffset

Bug: 885196
Change-Id: I732a39659f1f354a8dec982bf75e14f11c0f2134
Reviewed-on: https://chromium-review.googlesource.com/1238376
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Reviewed-by: default avatarAnders Ruud <andruud@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595487}
parent cd315c05
......@@ -4,13 +4,17 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/css/css_calculation_value.h"
#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/length_functions.h"
namespace blink {
......@@ -159,22 +163,76 @@ double ScrollTimeline::currentTime(bool& is_null) {
current_offset = scroll_offset.Height();
max_offset = scroll_dimensions.Height();
}
// When using a rtl direction, current_offset grows correctly from 0 to
// max_offset, but is negative. Since our offsets are all just deltas along
// the orientation direction, we can just take the absolute current_offset and
// use that everywhere.
current_offset = std::abs(current_offset);
double resolved_start_scroll_offset = 0;
double resolved_end_scroll_offset = max_offset;
ResolveScrollStartAndEnd(layout_box, max_offset, resolved_start_scroll_offset,
resolved_end_scroll_offset);
// 3. If current scroll offset is less than startScrollOffset, return an
// unresolved time value if fill is none or forwards, or 0 otherwise.
// TODO(smcgruer): Implement |startScrollOffset| and |fill|.
// TODO(smcgruer): Implement |fill|.
if (current_offset < resolved_start_scroll_offset) {
return std::numeric_limits<double>::quiet_NaN();
}
// 4. If current scroll offset is greater than or equal to endScrollOffset,
// return an unresolved time value if fill is none or backwards, or the
// effective time range otherwise.
// TODO(smcgruer): Implement |endScrollOffset| and |fill|.
//
// TODO(smcgruer): Implement |fill|.
//
// Note we deliberately break the spec here by only returning if the current
// offset is strictly greater, as that is more in line with the web animation
// spec. See https://github.com/WICG/scroll-animations/issues/19
if (current_offset > resolved_end_scroll_offset) {
return std::numeric_limits<double>::quiet_NaN();
}
// This is not by the spec, but avoids both negative current time and a
// divsion by zero issue. See
// https://github.com/WICG/scroll-animations/issues/20 and
// https://github.com/WICG/scroll-animations/issues/21
if (resolved_start_scroll_offset >= resolved_end_scroll_offset) {
return std::numeric_limits<double>::quiet_NaN();
}
// 5. Return the result of evaluating the following expression:
// ((current scroll offset - startScrollOffset) /
// (endScrollOffset - startScrollOffset)) * effective time range
is_null = false;
return (std::abs(current_offset) / max_offset) * time_range_;
return ((current_offset - resolved_start_scroll_offset) /
(resolved_end_scroll_offset - resolved_start_scroll_offset)) *
time_range_;
}
void ScrollTimeline::ResolveScrollStartAndEnd(
const LayoutBox* layout_box,
double max_offset,
double& resolved_start_scroll_offset,
double& resolved_end_scroll_offset) {
const ComputedStyle& computed_style = layout_box->StyleRef();
Document& document = layout_box->GetDocument();
const ComputedStyle* root_style =
document.documentElement()
? document.documentElement()->GetComputedStyle()
: document.GetComputedStyle();
CSSToLengthConversionData conversion_data = CSSToLengthConversionData(
&computed_style, root_style, document.GetLayoutView(),
computed_style.EffectiveZoom());
if (start_scroll_offset_) {
resolved_start_scroll_offset = FloatValueForLength(
start_scroll_offset_->ConvertToLength(conversion_data), max_offset);
}
if (end_scroll_offset_) {
resolved_end_scroll_offset = FloatValueForLength(
end_scroll_offset_->ConvertToLength(conversion_data), max_offset);
}
}
Element* ScrollTimeline::scrollSource() {
......
......@@ -78,6 +78,11 @@ class CORE_EXPORT ScrollTimeline final : public AnimationTimeline {
CSSPrimitiveValue*,
double);
void ResolveScrollStartAndEnd(const LayoutBox*,
double max_offset,
double& resolved_start_scroll_offset,
double& resolved_end_scroll_offset);
Member<Element> scroll_source_;
ScrollDirection orientation_;
Member<CSSPrimitiveValue> start_scroll_offset_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment