提交 6eba4a04 编写于 作者: A Adam Barth

Add a simple inksplash example

We'll eventually turn this into a full fn2 component, but for now it's just an
example.

To make this work, I created a schedule.dart as a start to implementing
scheduler.md. For now, I've kept the API similar to the web platform so that
the old world can continue use it backed by sky.window.requestAnimationFrame.

R=eseidel@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1145973009
上级 bf30484e
// 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 'dart:sky' as sky;
import 'package:sky/framework/app.dart';
import 'package:sky/framework/rendering/render_box.dart';
import 'package:sky/framework/rendering/render_node.dart';
import 'package:sky/framework/animation/animated_value.dart';
import 'package:sky/framework/animation/curves.dart';
const double _kInitialSize = 0.0;
const double _kTargetSize = 100.0;
const double _kSplashDuration = 500.0;
const int _kInitialOpacity = 0x80;
class InkSplash {
final InkWell inkWell;
final sky.Paint _paint = new sky.Paint();
final sky.Point position;
AnimatedValue radius;
InkSplash({ this.position, this.inkWell }) {
radius = new AnimatedValue(_kInitialSize, onChange: _handleRadiusChange);
radius.animateTo(_kTargetSize, _kSplashDuration, curve: easeOut);
}
void _handleRadiusChange() {
if (radius.value == _kTargetSize)
inkWell._splashes.remove(this);
inkWell.markNeedsPaint();
}
void paint(RenderNodeDisplayList canvas) {
int opacity = (_kInitialOpacity * (1.0 - (radius.value / _kTargetSize))).floor();
_paint.color = opacity << 24;
canvas.drawCircle(position.x, position.y, radius.value, _paint);
}
}
class InkWell extends RenderBox {
final List<InkSplash> _splashes = new List<InkSplash>();
void handlePointer(sky.PointerEvent event) {
switch (event.type) {
case 'pointerdown':
_splashes.add(new InkSplash(position: new sky.Point(event.x, event.y),
inkWell: this));
break;
}
markNeedsPaint();
}
void performLayout() {
size = constraints.constrain(new sky.Size.infinite());
}
void paint(RenderNodeDisplayList canvas) {
canvas.drawRect(new sky.Rect.fromLTRB(0.0, 0.0, size.width, size.height),
new sky.Paint()..color = 0xFFCCCCCC);
for (InkSplash splash in _splashes)
splash.paint(canvas);
}
}
AppView app;
void main() {
app = new AppView(new InkWell());
}
......@@ -61,6 +61,10 @@ class RenderTouchDemo extends RenderBox {
markNeedsPaint();
}
void performLayout() {
size = constraints.constrain(new Size.infinite());
}
void paint(RenderNodeDisplayList canvas) {
dots.forEach((_, Dot dot) {
dot.paint(canvas);
......
......@@ -100,6 +100,7 @@ dart_pkg("sdk") {
"lib/framework/rendering/render_flex.dart",
"lib/framework/rendering/render_node.dart",
"lib/framework/rendering/render_paragraph.dart",
"lib/framework/scheduler.dart",
"lib/framework/shell.dart",
"lib/framework/theme/colors.dart",
"lib/framework/theme/shadows.dart",
......
......@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '../scheduler.dart' as scheduler;
import 'curves.dart';
import 'dart:async';
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'mechanics.dart';
abstract class Generator {
......@@ -34,7 +34,7 @@ class FrameGenerator extends Generator {
return;
}
if (_animationId != 0) {
sky.window.cancelAnimationFrame(_animationId);
scheduler.cancelAnimationFrame(_animationId);
}
_animationId = 0;
_cancelled = true;
......@@ -45,7 +45,7 @@ class FrameGenerator extends Generator {
void _scheduleTick() {
assert(_animationId == 0);
_animationId = sky.window.requestAnimationFrame(_tick);
_animationId = scheduler.requestAnimationFrame(_tick);
}
void _tick(double timeStamp) {
......
......@@ -5,18 +5,20 @@
import 'dart:sky' as sky;
import 'rendering/render_box.dart';
import 'rendering/render_node.dart';
import 'scheduler.dart' as scheduler;
class AppView {
AppView(RenderBox root) {
sky.view.setEventCallback(_handleEvent);
sky.view.setBeginFrameCallback(_beginFrame);
scheduler.init();
scheduler.addPersistentFrameCallback(_beginFrame);
_renderView = new RenderView(child: root);
_renderView.attach();
_renderView.layout(new ViewConstraints(width: sky.view.width, height: sky.view.height));
sky.view.scheduleFrame();
scheduler.ensureVisualUpdate();
}
RenderView _renderView;
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import '../node.dart';
import '../scheduler.dart' as scheduler;
import 'dart:math' as math;
import 'dart:sky' as sky;
......@@ -173,10 +174,7 @@ abstract class RenderNode extends AbstractNode {
static bool debugDoingPaint = false;
void markNeedsPaint() {
assert(!debugDoingPaint);
// TODO(abarth): It's very redundant to call this for every node in the
// render tree during layout. We should instead compute a summary bit and
// call it once at the end of layout.
sky.view.scheduleFrame();
scheduler.ensureVisualUpdate();
}
void paint(RenderNodeDisplayList canvas) { }
......
// 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 'dart:async';
import 'dart:sky' as sky;
typedef void Callback(double timeStamp);
bool _haveScheduledVisualUpdate = false;
int _nextCallbackId = 1;
final List<Callback> _persistentCallbacks = new List<Callback>();
Map<int, Callback> _transientCallbacks = new Map<int, Callback>();
void _beginFrame(double timeStamp) {
_haveScheduledVisualUpdate = false;
Map<int, Callback> callbacks = _transientCallbacks;
_transientCallbacks = new Map<int, Callback>();
callbacks.forEach((id, callback) {
callback(timeStamp);
});
for (Callback callback in _persistentCallbacks)
callback(timeStamp);
}
void init() {
assert(sky.window == null);
sky.view.setBeginFrameCallback(_beginFrame);
}
void addPersistentFrameCallback(Callback callback) {
assert(sky.window == null);
_persistentCallbacks.add(callback);
}
int requestAnimationFrame(Callback callback) {
if (sky.window != null)
return sky.window.requestAnimationFrame(callback);
int id = _nextCallbackId++;
_transientCallbacks[id] = callback;
ensureVisualUpdate();
return id;
}
void cancelAnimationFrame(int id) {
if (sky.window != null)
return sky.window.cancelAnimationFrame(id);
_transientCallbacks.remove(id);
}
void ensureVisualUpdate() {
assert(sky.window == null);
if (_haveScheduledVisualUpdate)
return;
sky.view.scheduleFrame();
_haveScheduledVisualUpdate = true;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册