| Index: LayoutTests/fast/workers/resources/scroll-linked-effects.js
|
| diff --git a/LayoutTests/fast/workers/resources/scroll-linked-effects.js b/LayoutTests/fast/workers/resources/scroll-linked-effects.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..967339d7241daa83557f03616b7362ff6984948f
|
| --- /dev/null
|
| +++ b/LayoutTests/fast/workers/resources/scroll-linked-effects.js
|
| @@ -0,0 +1,147 @@
|
| +// Copyright 2014 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.
|
| +(function(scope) {
|
| + "use strict";
|
| +
|
| + var width = 55;
|
| + var scaleFactor = 200.0;
|
| + var jumpHeight = 50;
|
| +
|
| + function createUIWorker() {
|
| + scope.worker = new UIWorker('resources/scroll-linked-effects.js');
|
| +
|
| + var scroller = document.getElementById('scroller');
|
| + var dancer = document.getElementById('dancer');
|
| + var shadow = document.getElementById('shadow');
|
| +
|
| + scope.worker.postMessage([
|
| + scroller.bindAnimatedProperty('scrollTop'),
|
| + dancer.bindAnimatedProperty('transform'),
|
| + shadow.bindAnimatedProperty('transform')
|
| + ]);
|
| + }
|
| +
|
| + function translate(x, y) {
|
| + return 'translate(' + x + 'px, ' + y + 'px) ';
|
| + }
|
| +
|
| + function translate3d(x, y, z) {
|
| + return 'translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px) ';
|
| + }
|
| +
|
| + function rotateX(deg) {
|
| + return 'rotateX(' + deg + 'deg) ';
|
| + }
|
| +
|
| + function rotateY(deg) {
|
| + return 'rotateY(' + deg + 'deg) ';
|
| + }
|
| +
|
| + function aboutPoint(x, y, transform) {
|
| + return translate(x, y) + transform + translate(-x, -y);
|
| + }
|
| +
|
| + function perspective(depth, x, y) {
|
| + return aboutPoint(x, y, 'perspective(' + depth + 'px) ');
|
| + }
|
| +
|
| + function matrixFromScrollTop(scrollTop, perspX, perspY) {
|
| + var str = perspective(depth, x, y) +
|
| + aboutPoint(0, width, rotateX(-scrollTop));
|
| + console.log(str);
|
| + return new WebKitCSSMatrix(str);
|
| + }
|
| +
|
| + function getTranslationForMove(index) {
|
| + var x = 0;
|
| + var y = 0;
|
| + for (var i = 0; i < index; i++) {
|
| + switch (moves[i]) {
|
| + case 'up': y -= 2*width; break;
|
| + case 'down': y += 2*width; break;
|
| + case 'left': x -= 2*width; break;
|
| + case 'right': x += 2*width; break;
|
| + case 'jump-up': y -= 4*width; break;
|
| + case 'jump-down': y += 4*width; break;
|
| + case 'jump-left': x -= 4*width; break;
|
| + case 'jump-right': x += 4*width; break;
|
| + }
|
| + }
|
| + return translate(x, y);
|
| + }
|
| +
|
| + function getRotationForMove(index, fraction) {
|
| + var degrees = fraction * 180.0 + 0.0001;
|
| + var radians = fraction * Math.PI;
|
| + switch (moves[index]) {
|
| + case 'up': return aboutPoint(0, -width, rotateX(degrees));
|
| + case 'down': return aboutPoint(0, width, rotateX(-degrees));
|
| + case 'left': return aboutPoint(-width, 0, rotateY(-degrees));
|
| + case 'right': return aboutPoint(width, 0, rotateY(degrees));
|
| + case 'jump-up':
|
| + return translate3d(0, -4 * width * fraction,
|
| + (-1.0 + Math.cos(radians * 2)) * -jumpHeight);
|
| + case 'jump-down':
|
| + return translate3d(0, 6 * width * fraction,
|
| + (-1.0 + Math.cos(radians * 2)) * -0.2 * jumpHeight)
|
| + + aboutPoint(0, -width, rotateX(degrees));
|
| + case 'jump-left':
|
| + return translate3d(-4 * width * fraction, 0,
|
| + (-1.0 + Math.cos(radians * 2)) * -jumpHeight)
|
| + + 'rotateZ(' + degrees + 'deg)';
|
| + case 'jump-right':
|
| + return translate3d(4 * width * fraction, 0,
|
| + (-1.0 + Math.cos(radians * 2)) * -jumpHeight);
|
| + }
|
| + }
|
| +
|
| + function tick(context) {
|
| + var scrollTop = context.getScalar(scope.scroll);
|
| +
|
| + var scaled = Math.floor(scrollTop / scaleFactor);
|
| + var index = scaled % moves.length;
|
| + var fraction = (scrollTop - scaled * scaleFactor) / scaleFactor;
|
| + var translation = getTranslationForMove(index);
|
| + var rotation = getRotationForMove(index, fraction);
|
| +
|
| + context.setMatrix(scope.dancer,
|
| + new WebKitCSSMatrix(translation + dancerPerspective + rotation));
|
| +
|
| + context.setMatrix(scope.shadow,
|
| + new WebKitCSSMatrix(translation + shadowPerspective + rotation));
|
| +
|
| + scope.teleportMessage(context, tick);
|
| + }
|
| +
|
| + function onMessage(e) {
|
| + var tokens = e.data
|
| + scope.scroll = tokens[0];
|
| + scope.dancer = tokens[1];
|
| + scope.shadow = tokens[2];
|
| +
|
| + // A cute trick: if you use different perspective origins, you get
|
| + // directional shadows.
|
| + scope.dancerPerspective = perspective(300, 50, 0);
|
| + scope.shadowPerspective = perspective(300, 100, 40);
|
| +
|
| + // The following moves define the path taken by the dancer.
|
| + scope.moves = [
|
| + "down", "right", "up", "right", "up", "left", "down", "left",
|
| + "jump-right", "left", "down", "jump-up", "right", "down", "left",
|
| + "jump-down", "up", "right", "up", "jump-left"
|
| + ];
|
| +
|
| + // TODO: we should have to request the current time. Otherwise, we should
|
| + // wait until a change in the given values before spamming tick for max
|
| + // battery efficiency.
|
| + scope.teleportMessage(new TeleportContext(tokens), tick);
|
| + }
|
| +
|
| + if (scope.window) {
|
| + scope.window.onload = createUIWorker;
|
| + } else {
|
| + scope.onmessage = onMessage;
|
| + }
|
| +
|
| +})(self);
|
|
|