mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Previously the scrollbar wasn't constrained to the scrollable element and we had messed up the math on the fling curve. TBR=eseidel@chromium.org Review URL: https://codereview.chromium.org/947303003
138 lines
3.5 KiB
Plaintext
138 lines
3.5 KiB
Plaintext
<!--
|
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
-->
|
|
<import src="sky-element.sky" />
|
|
|
|
<sky-element>
|
|
<template>
|
|
<style>
|
|
:host {
|
|
overflow: hidden;
|
|
position: relative;
|
|
will-change: transform;
|
|
}
|
|
#scrollable {
|
|
will-change: transform;
|
|
}
|
|
#vbar {
|
|
position: absolute;
|
|
right: 0;
|
|
width: 3px;
|
|
background-color: lightgray;
|
|
pointer-events: none;
|
|
top: 0;
|
|
height: 0;
|
|
will-change: opacity;
|
|
opacity: 0;
|
|
transition: opacity 0.2s ease-in-out;
|
|
}
|
|
</style>
|
|
<div id="scrollable">
|
|
<content />
|
|
</div>
|
|
<div id="vbar" />
|
|
</template>
|
|
<script>
|
|
import "dart:math" as math;
|
|
import "dart:sky";
|
|
import "fling-curve.dart";
|
|
|
|
@Tagname('sky-scrollable')
|
|
class SkyScrollable extends SkyElement {
|
|
Element _scrollable;
|
|
Element _vbar;
|
|
double _scrollOffset = 0.0;
|
|
FlingCurve _flingCurve;
|
|
int _flingAnimationId;
|
|
|
|
SkyScrollable() {
|
|
addEventListener('gesturescrollstart', _handleScrollStart);
|
|
addEventListener('gesturescrollend', _handleScrollEnd);
|
|
addEventListener('gesturescrollupdate', _handleScrollUpdate);
|
|
addEventListener('gestureflingstart', _handleFlingStart);
|
|
addEventListener('gestureflingcancel', _handleFlingCancel);
|
|
addEventListener('wheel', _handleWheel);
|
|
}
|
|
|
|
void shadowRootReady() {
|
|
_scrollable = shadowRoot.getElementById('scrollable');
|
|
_vbar = shadowRoot.getElementById('vbar');
|
|
}
|
|
|
|
double get scrollOffset => _scrollOffset;
|
|
|
|
set scrollOffset(double value) {
|
|
// TODO(abarth): Can we get these values without forcing a synchronous layout?
|
|
double outerHeight = clientHeight.toDouble();
|
|
double innerHeight = _scrollable.clientHeight.toDouble();
|
|
double scrollRange = innerHeight - outerHeight;
|
|
double newScrollOffset = math.max(0.0, math.min(scrollRange, value));
|
|
if (newScrollOffset == _scrollOffset)
|
|
return;
|
|
_scrollOffset = newScrollOffset;
|
|
String transform = 'translateY(${(-_scrollOffset).toStringAsFixed(2)}px)';
|
|
_scrollable.style['transform'] = transform;
|
|
|
|
double topPercent = newScrollOffset / innerHeight * 100.0;
|
|
double heightPercent = outerHeight / innerHeight * 100.0;
|
|
_vbar.style['top'] = '${topPercent}%';
|
|
_vbar.style['height'] = '${heightPercent}%';
|
|
}
|
|
|
|
bool scrollBy(double scrollDelta) {
|
|
double oldScrollOffset = _scrollOffset;
|
|
scrollOffset += scrollDelta;
|
|
return _scrollOffset != oldScrollOffset;
|
|
}
|
|
|
|
void _scheduleFlingUpdate() {
|
|
_flingAnimationId = window.requestAnimationFrame(_updateFling);
|
|
}
|
|
|
|
void _stopFling() {
|
|
window.cancelAnimationFrame(_flingAnimationId);
|
|
_flingCurve = null;
|
|
_flingAnimationId = null;
|
|
_vbar.style['opacity'] = '0';
|
|
}
|
|
|
|
void _updateFling(double timeStamp) {
|
|
double scrollDelta = _flingCurve.update(timeStamp);
|
|
if (scrollDelta == 0.0 || !scrollBy(scrollDelta))
|
|
_stopFling();
|
|
else
|
|
_scheduleFlingUpdate();
|
|
}
|
|
|
|
void _handleScrollStart(_) {
|
|
_vbar.style['opacity'] = '1';
|
|
}
|
|
|
|
void _handleScrollEnd(_) {
|
|
_vbar.style['opacity'] = '0';
|
|
}
|
|
|
|
void _handleScrollUpdate(GestureEvent event) {
|
|
scrollBy(-event.dy);
|
|
}
|
|
|
|
void _handleFlingStart(GestureEvent event) {
|
|
_flingCurve = new FlingCurve(-event.velocityY, event.timeStamp);
|
|
_scheduleFlingUpdate();
|
|
}
|
|
|
|
void _handleFlingCancel(_) {
|
|
_stopFling();
|
|
}
|
|
|
|
void _handleWheel(WheelEvent event) {
|
|
scrollBy(-event.offsetY);
|
|
}
|
|
}
|
|
|
|
_init(script) => register(script, SkyScrollable);
|
|
</script>
|
|
</sky-element>
|