Rx.animationFrames

Animations with Knockout, Rx and requestAnimationFrame

by bman654

HTML

<script src="http://cdn.strategiqcommerce.com/ajax/libs/rxjs/2.1.0/rx.min.js"></script>
<div data-bind="text: 'Distance: ' + distance()"></div>
<div id="block" data-bind="style: { left: position().x + 'px', top: position().y + 'px' }"></div>

CSS

#block {
    position: absolute;
    background-color: red;
    border: 1px solid black;
    width: 5px;
    height: 5px;
    box-sizing: border-box;
    margin-left: -2.5px;
    margin-top: -2.5px;
}
html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

JavaScript

ko.subscribable.fn.toRx = function (startWithCurrentValue) {
    /// <summary>Returns an Rx.Observable that signals whenever the underlying ko object changes</summary>
    /// <param name="startWithCurrentValue" type="Boolean">If true, the resulting observable sequence will start with the current value of the ko object at the time of subscription, unless the current value is 'undefined'.</param>
    /// <returns type="Rx.Observable"></returns>
    var source = this;

    return Rx.Observable.createWithDisposable(function (observer) {
        var onNext = observer.onNext.bind(observer),
            subscription = source.subscribe(onNext),
            currentValue;

        if (startWithCurrentValue && ko.isObservable(source)) {
            currentValue = source();

            if (currentValue !== undefined) {
                onNext(currentValue);
            }
        }

        return subscription;
    });
};

Rx.Observable.prototype.toKO = function () {
    /// <summary>Returns a read-only ko.observable which will be subscribed to the source Rx.Observable and will always contain the most recent value received from source</summary>
    /// <returns type="ko.observable"></returns>
    var source = this,
        value = ko.observable(),
        subscription = new Rx.SingleAssignmentDisposable(),
        computed = ko.computed({
            read: function () {
                if (!subscription.disposable()) {
                    ko.computed(function () {
                        subscription.disposable(source.subscribe(value));
                    }).dispose();
                }

                return value();
            },
            deferEvaluation: true
        }),
        dispose = computed.dispose;

    computed.dispose = function () {
        subscription.dispose();
        dispose.apply(this, arguments);
    };

    return computed;
};

Rx.Observable.animationFrames = function () {
    /// <summary>
    /// Returns an observable that triggers on every...