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:
Adam Barth 2015-01-26 13:29:38 -08:00
parent 9f0f8f500c
commit 7ded81cc4f
3 changed files with 153 additions and 5 deletions

View 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>

View 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>

View File

@ -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;