| Index: client/base/AnimationScheduler.dart
|
| ===================================================================
|
| --- client/base/AnimationScheduler.dart (revision 4144)
|
| +++ client/base/AnimationScheduler.dart (working copy)
|
| @@ -1,166 +0,0 @@
|
| -// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -typedef void AnimationCallback(num currentTime);
|
| -
|
| -class CallbackData {
|
| - final AnimationCallback callback;
|
| - final num minTime;
|
| - int id;
|
| -
|
| - static int _nextId;
|
| -
|
| - bool ready(num time) => minTime === null || minTime <= time;
|
| -
|
| - CallbackData(this.callback, this.minTime) {
|
| - // TODO(jacobr): static init needs cleanup, see http://b/4161827
|
| - if (_nextId === null) {
|
| - _nextId = 1;
|
| - }
|
| - id = _nextId++;
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * Animation scheduler implementing the functionality provided by
|
| - * [:window.requestAnimationFrame:] for platforms that do not support it
|
| - * or support it badly. When multiple UI components are animating at once,
|
| - * this approach yields superior performance to calling setTimeout directly as
|
| - * all pieces of the UI will animate at the same time resulting in fewer
|
| - * layouts.
|
| - */
|
| -// TODO(jacobr): use window.requestAnimationFrame when it is available and
|
| -// 60fps for the current browser.
|
| -class AnimationScheduler {
|
| - static final FRAMES_PER_SECOND = 60;
|
| - static final MS_PER_FRAME = 1000 ~/ FRAMES_PER_SECOND;
|
| - static final USE_INTERVALS = false;
|
| -
|
| - /** List of callbacks to be executed next animation frame. */
|
| - List<CallbackData> _callbacks;
|
| - int _intervalId;
|
| - bool _isMobileSafari = false;
|
| - CSSStyleDeclaration _safariHackStyle;
|
| - int _frameCount = 0;
|
| - bool _webkitAnimationFrameMaybeAvailable = true;
|
| -
|
| - AnimationScheduler()
|
| - : _callbacks = new List<CallbackData>() {
|
| - if (_isMobileSafari) {
|
| - // TODO(jacobr): find a better workaround for the issue that 3d transforms
|
| - // sometimes don't render on iOS without forcing a layout.
|
| - final element = new Element.tag('div');
|
| - document.body.nodes.add(element);
|
| - _safariHackStyle = element.style;
|
| - _safariHackStyle.position = 'absolute';
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Cancel the pending callback matching the specified [id].
|
| - * This is not heavily optimized as typically users don't cancel animation
|
| - * frames.
|
| - */
|
| - void cancelRequestAnimationFrame(int id) {
|
| - _callbacks = _callbacks.filter((CallbackData e) => e.id != id);
|
| - }
|
| -
|
| - /**
|
| - * Schedule [callback] to execute at the next animation frame that occurs
|
| - * at or after [minTime]. If [minTime] is not specified, the first available
|
| - * animation frame is used. Returns an id that can be used to cancel the
|
| - * pending callback.
|
| - */
|
| - int requestAnimationFrame(AnimationCallback callback,
|
| - [Element element = null,
|
| - num minTime = null]) {
|
| - final callbackData = new CallbackData(callback, minTime);
|
| - _requestAnimationFrameHelper(callbackData);
|
| - return callbackData.id;
|
| - }
|
| -
|
| - void _requestAnimationFrameHelper(CallbackData callbackData) {
|
| - _callbacks.add(callbackData);
|
| - if (_intervalId === null) {
|
| - _setupInterval();
|
| - }
|
| - }
|
| -
|
| - void _setupInterval() {
|
| - // Assert that we never schedule multiple frames at once.
|
| - assert(_intervalId === null);
|
| - if (USE_INTERVALS) {
|
| - _intervalId = window.setInterval(_step, MS_PER_FRAME);
|
| - } else {
|
| - if (_webkitAnimationFrameMaybeAvailable) {
|
| - try {
|
| - // TODO(jacobr): passing in document should not be required.
|
| - _intervalId = window.webkitRequestAnimationFrame(
|
| - (int ignored) { _step(); }, document);
|
| - // TODO(jacobr) fix this odd type error.
|
| - } catch (var e) {
|
| - _webkitAnimationFrameMaybeAvailable = false;
|
| - }
|
| - }
|
| - if (!_webkitAnimationFrameMaybeAvailable) {
|
| - _intervalId = window.setTimeout(() { _step(); }, MS_PER_FRAME);
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _step() {
|
| - if (_callbacks.isEmpty()) {
|
| - // Cancel the interval on the first frame where there aren't actually
|
| - // any available callbacks.
|
| - assert(_intervalId != null);
|
| - if (USE_INTERVALS) {
|
| - window.clearInterval(_intervalId);
|
| - }
|
| - _intervalId = null;
|
| - } else if (USE_INTERVALS == false) {
|
| - _intervalId = null;
|
| - _setupInterval();
|
| - }
|
| - int numRemaining = 0;
|
| - int minTime = new Date.now().value + MS_PER_FRAME;
|
| -
|
| - int len = _callbacks.length;
|
| - for (final callback in _callbacks) {
|
| - if (!callback.ready(minTime)) {
|
| - numRemaining++;
|
| - }
|
| - }
|
| -
|
| - if (numRemaining == len) {
|
| - // TODO(jacobr): we could be more clever about this case if delayed
|
| - // requests really become the main use case...
|
| - return;
|
| - }
|
| - // Some callbacks need to be executed.
|
| - final currentCallbacks = _callbacks;
|
| - _callbacks = new List<CallbackData>();
|
| -
|
| - for (final callbackData in currentCallbacks) {
|
| - if (callbackData.ready(minTime)) {
|
| - try {
|
| - (callbackData.callback)(minTime);
|
| - } catch (var e) {
|
| - final msg = e.toString();
|
| - print('Suppressed exception ${msg} triggered by callback');
|
| - }
|
| - } else {
|
| - _callbacks.add(callbackData);
|
| - }
|
| - }
|
| -
|
| - _frameCount++;
|
| - if (_isMobileSafari) {
|
| - // Hack to work around an iOS bug where sometimes animations do not
|
| - // render if only webkit transforms were modified.
|
| - // TODO(jacobr): find a cleaner workaround.
|
| - int offset = _frameCount % 2;
|
| - _safariHackStyle.left = '${offset}px';
|
| - }
|
| - }
|
| -}
|
|
|