mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add a basic sky-scrollable element that scrolls
We still need to polish sky-scrollable, but it basically works. R=esprehn@chromium.org Review URL: https://codereview.chromium.org/875953004
This commit is contained in:
parent
9f0f8f500c
commit
7ded81cc4f
42
examples/example-scrollable.sky
Normal file
42
examples/example-scrollable.sky
Normal file
@ -0,0 +1,42 @@
|
||||
<!--
|
||||
// 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.
|
||||
-->
|
||||
<sky>
|
||||
<import src="/sky/framework/sky-element/sky-element.sky" as="SkyElement" />
|
||||
<import src="/sky/framework/sky-scrollable.sky" />
|
||||
<import src="data/cities.sky" as="cities" />
|
||||
|
||||
<sky-element name="example-scrollable">
|
||||
<template>
|
||||
<style>
|
||||
sky-scrollable {
|
||||
margin: 20px;
|
||||
height: 400px;
|
||||
border: 2px solid blue;
|
||||
}
|
||||
b {
|
||||
display: inline;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<sky-scrollable>
|
||||
<template repeat="{{ cities }}">
|
||||
<template>
|
||||
<div>{{ name }}</div>
|
||||
</template>
|
||||
</template>
|
||||
</sky-scrollable>
|
||||
</template>
|
||||
<script>
|
||||
module.exports = class extends SkyElement {
|
||||
created() {
|
||||
this.cities = cities;
|
||||
}
|
||||
}.register();
|
||||
</script>
|
||||
</sky-element>
|
||||
|
||||
<example-scrollable />
|
||||
</sky>
|
||||
101
framework/sky-scrollable.sky
Normal file
101
framework/sky-scrollable.sky
Normal file
@ -0,0 +1,101 @@
|
||||
<!--
|
||||
// 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/framework/sky-element/sky-element.sky" as="SkyElement" />
|
||||
|
||||
<sky-element
|
||||
name="sky-scrollable"
|
||||
on-gesturescrollstart="handleScrollStart_"
|
||||
on-gesturescrollend="handleScrollEnd_"
|
||||
on-gesturescrollupdate="handleScrollUpdate_"
|
||||
on-gestureflingstart="handleFlingStart_"
|
||||
on-gestureflingcancel="handleFlingCancel_">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
overflow: hidden;
|
||||
}
|
||||
#scrollable {
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
<div id="scrollable">
|
||||
<content />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// TODO(abarth): Move the fling curve to a separate module.
|
||||
var kFlingFriction = 0.9;
|
||||
var kFlingVelocityMin = 1;
|
||||
|
||||
module.exports = class extends SkyElement {
|
||||
created() {
|
||||
this.scrollable_ = null;
|
||||
this.scrollOffset_ = 0;
|
||||
this.flingVelocity_ = 0;
|
||||
this.flingAnimationId_ = null;
|
||||
}
|
||||
|
||||
shadowRootReady() {
|
||||
this.scrollable_ = this.shadowRoot.getElementById('scrollable');
|
||||
}
|
||||
|
||||
scrollBy(scrollDelta) {
|
||||
var offset = Math.max(0, Math.min(this.scrollable_.offsetHeight, this.scrollOffset_ + scrollDelta));
|
||||
if (offset == this.scrollOffset_)
|
||||
return false;
|
||||
this.scrollOffset_ = offset;
|
||||
this.applyScrollOffset_();
|
||||
return true;
|
||||
}
|
||||
|
||||
applyScrollOffset_() {
|
||||
var transform = 'translateY(' + -this.scrollOffset_.toFixed(2) + 'px)';
|
||||
this.scrollable_.style.transform = transform;
|
||||
}
|
||||
|
||||
scheduleFlingTick_() {
|
||||
this.flingAnimationId_ = requestAnimationFrame(this.tickFling_.bind(this));
|
||||
}
|
||||
|
||||
tickFling_() {
|
||||
this.flingAnimationId_ = null;
|
||||
if (!this.scrollBy(this.flingVelocity_)) {
|
||||
this.flingVelocity_ = 0;
|
||||
return;
|
||||
}
|
||||
var velocity = this.flingVelocity_ * kFlingFriction;
|
||||
if (velocity < kFlingVelocityMin)
|
||||
velocity = 0;
|
||||
this.flingVelocity_ = velocity;
|
||||
if (velocity)
|
||||
this.scheduleFlingTick_();
|
||||
}
|
||||
|
||||
handleScrollStart_(event) {
|
||||
}
|
||||
|
||||
handleScrollEnd_(event) {
|
||||
}
|
||||
|
||||
handleScrollUpdate_(event) {
|
||||
this.scrollBy(-event.dy);
|
||||
}
|
||||
|
||||
handleFlingStart_(event) {
|
||||
this.flingVelocity_ = -event.velocityY;
|
||||
this.scheduleFlingTick_();
|
||||
}
|
||||
|
||||
handleFlingCancel_(event) {
|
||||
if (!this.flingAnimationId_)
|
||||
return;
|
||||
cancelAnimationFrame(this.flingAnimationId_);
|
||||
this.flingVelocity_ = 0;
|
||||
this.flingAnimationId_ = null;
|
||||
}
|
||||
}.register();
|
||||
</script>
|
||||
</sky-element>
|
||||
@ -101,13 +101,17 @@ scoped_ptr<blink::WebInputEvent> BuildWebGestureEvent(
|
||||
break;
|
||||
case mojo::EVENT_TYPE_GESTURE_SCROLL_UPDATE:
|
||||
web_event->type = blink::WebInputEvent::GestureScrollUpdate;
|
||||
web_event->data.scrollUpdate.deltaX = event->gesture_data->scroll_x;
|
||||
web_event->data.scrollUpdate.deltaY = event->gesture_data->scroll_y;
|
||||
web_event->data.scrollUpdate.deltaX =
|
||||
event->gesture_data->scroll_x / device_pixel_ratio;
|
||||
web_event->data.scrollUpdate.deltaY =
|
||||
event->gesture_data->scroll_y / device_pixel_ratio;
|
||||
break;
|
||||
case mojo::EVENT_TYPE_SCROLL_FLING_START:
|
||||
web_event->type = blink::WebInputEvent::GestureFlingStart;
|
||||
web_event->data.flingStart.velocityX = event->gesture_data->velocity_x;
|
||||
web_event->data.flingStart.velocityY = event->gesture_data->velocity_y;
|
||||
web_event->data.flingStart.velocityX =
|
||||
event->gesture_data->velocity_x / device_pixel_ratio;
|
||||
web_event->data.flingStart.velocityY =
|
||||
event->gesture_data->velocity_y / device_pixel_ratio;
|
||||
break;
|
||||
case mojo::EVENT_TYPE_SCROLL_FLING_CANCEL:
|
||||
web_event->type = blink::WebInputEvent::GestureFlingCancel;
|
||||
@ -150,7 +154,8 @@ scoped_ptr<blink::WebInputEvent> BuildWebGestureEvent(
|
||||
break;
|
||||
case mojo::EVENT_TYPE_GESTURE_PINCH_UPDATE:
|
||||
web_event->type = blink::WebInputEvent::GesturePinchUpdate;
|
||||
web_event->data.pinchUpdate.scale = event->gesture_data->scale;
|
||||
web_event->data.pinchUpdate.scale =
|
||||
event->gesture_data->scale / device_pixel_ratio;
|
||||
break;
|
||||
default:
|
||||
NOTIMPLEMENTED() << "Received unexpected event: " << event->action;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user