Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1231)

Unified Diff: experimental/docs/animationCommon.js

Issue 1342523002: json based animation toy (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: wip whats next? Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | experimental/docs/backend.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: experimental/docs/animationCommon.js
diff --git a/experimental/docs/animationCommon.js b/experimental/docs/animationCommon.js
new file mode 100644
index 0000000000000000000000000000000000000000..1733ec203200a68903eaa136f39a888b28d46ead
--- /dev/null
+++ b/experimental/docs/animationCommon.js
@@ -0,0 +1,314 @@
+var animationState = {};
+animationState.reset = function (engine) {
+ if ('string' === typeof engine) {
+ this.defaultEngine = engine;
+ }
+ this.defaults = {};
+ this.displayList = [];
+ this.displayDict = {};
+ this.start = null;
+ this.time = 0;
+ this.timeline = [];
+ this.timelineIndex = 0;
+ this.requestID = null;
+ this.paused = false;
+ this.displayEngine = 'undefined' === typeof engine ? this.defaultEngine : engine;
+}
+
+function addActions(frame, timeline) {
+ var keyframe = keyframes[frame];
+ var len = keyframe.length;
+ for (var i = 0; i < len; ++i) {
+ var action = keyframe[i];
+ loopOver(action, timeline);
+ }
+}
+
+function animateList(now) {
+ if (animationState.paused) {
+ return;
+ }
+ if (animationState.start == null) {
+ animationState.start = now - animationState.time;
+ }
+ animationState.time = now - animationState.start;
+ var stillAnimating = false;
+ for (var index = animationState.timelineIndex; index < animationState.timeline.length; ++index) {
+ var animation = animationState.timeline[index];
+ if (animation.time > animationState.time) {
+ stillAnimating = true;
+ break;
+ }
+ if (animation.time + animation.duration < animationState.time) {
+ if (animation.finalized) {
+ continue;
+ }
+ animation.finalized = true;
+ }
+ stillAnimating = true;
+ var actions = animation.actions;
+ for (var aIndex = 0; aIndex < actions.length; ++aIndex) {
+ var action = actions[aIndex];
+ var hasDraw = 'draw' in action;
+ var hasRef = 'ref' in action;
+ var displayIndex;
+ if (hasDraw) {
+ var ref = hasRef ? action.ref : "anonymous_" + index + "_" + aIndex;
+ assert('string' == typeof(ref));
+ if (ref in animationState.displayDict) {
+ displayIndex = animationState.displayDict[ref];
+ } else {
+ assert('string' == typeof(action.draw));
+ var draw = (new Function("return " + action.draw))();
+ assert('object' == typeof(draw));
+ var paint;
+ if ('paint' in action) {
+ assert('string' == typeof(action.paint));
+ paint = (new Function("return " + action.paint))();
+ assert('object' == typeof(paint) && !isArray(paint));
+ } else {
+ paint = animationState.defaults.paint;
+ }
+ displayIndex = animationState.displayList.length;
+ animationState.displayList.push( { "ref":ref, "draw":draw, "paint":paint,
+ "drawSpec":action.draw, "paintSpec":action.paint,
+ "drawCopied":false, "paintCopied":false,
+ "drawDirty":true, "paintDirty":true, "once":false } );
+ animationState.displayDict[ref] = displayIndex;
+ }
+ } else if (hasRef) {
+ assert('string' == typeof(action.ref));
+ displayIndex = animationState.displayDict[action.ref];
+ } else {
+ assert(actions.length == 1);
+ for (var prop in action) {
+ if ('paint' == prop) {
+ assert('string' == typeof(action[prop]));
+ var obj = (new Function("return " + action[prop]))();
+ assert('object' == typeof(obj) && !isArray(obj));
+ animationState.defaults[prop] = obj;
+ } else {
+ animationState.defaults[prop] = action[prop];
+ }
+ }
+ continue;
+ }
+ var targetSpec = 'target' in action ? action.target : animationState.defaults.target;
+ assert(targetSpec);
+ assert('string' == typeof(targetSpec));
+ assert(displayIndex < animationState.displayList.length);
+ var display = animationState.displayList[displayIndex];
+ var modDraw = targetSpec.startsWith('draw');
+ assert(modDraw || targetSpec.startsWith('paint'));
+ var modType = modDraw ? "draw" : "paint";
+ var copied = modDraw ? display.drawCopied : action.paintCopied;
+ if (!copied) {
+ var copy;
+ if (!modDraw || display.drawSpec.startsWith("text")) {
+ copy = {};
+ var original = modDraw ? display.draw : display.paint;
+ for (var p in original) {
+ copy[p] = original[p];
+ }
+ } else if (display.drawSpec.startsWith("paths")) {
+ copy = [];
+ for (var i = 0; i < display.draw.length; ++i) {
+ var curves = display.draw[i];
+ var curve = Object.keys(curves)[0];
+ copy[i] = {};
+ copy[i][curve] = curves[curve].slice(0); // clone the array of curves
+ }
+ } else {
+ assert(display.drawSpec.startsWith("pictures"));
+ copy = [];
+ for (var i = 0; i < display.draw.length; ++i) {
+ var entry = display.draw[i];
+ copy[i] = { "draw":entry.draw, "paint":entry.paint };
+ }
+ }
+ display[modType] = copy;
+ display[modType + "Copied"] = true;
+ }
+ var targetField, targetObject, fieldOffset;
+ if (targetSpec.endsWith("]")) {
+ fieldOffset = targetSpec.lastIndexOf("[");
+ assert(fieldOffset >= 0);
+ targetField = targetSpec.substring(fieldOffset + 1, targetSpec.length - 1);
+ var arrayIndex = +targetField;
+ if (!isNaN(arrayIndex) && targetField.length > 0) {
+ targetField = arrayIndex;
+ }
+
+ } else {
+ fieldOffset = targetSpec.lastIndexOf(".");
+ if (fieldOffset >= 0) {
+ targetField = targetSpec.substring(fieldOffset + 1, targetSpec.length);
+ } else {
+ targetObject = display;
+ targetField = targetSpec;
+ }
+ }
+ if (fieldOffset >= 0) {
+ var sub = targetSpec.substring(0, fieldOffset);
+ targetObject = (new Function('display', "return display." + sub))(display);
+ }
+ assert(null != targetObject[targetField]);
+ if (!('start' in action) || action.start < animation.time) {
+ for (var p in animationState.defaults) {
+ if ('draw' == p || 'paint' == p || 'ref' == p) {
+ continue;
+ }
+ assert('range' == p || 'target' == p || 'formula' == p || 'params' == p);
+ if (!(p in action)) {
+ action[p] = animationState.defaults[p];
+ }
+ }
+ if ('number' == typeof(action.formula)) {
+ targetObject[targetField] = action.formula;
+ action.once = true;
+ }
+ action.start = animation.time;
+ }
+ if (action.once) {
+ continue;
+ }
+ var value = Math.min(1, (animationState.time - animation.time) / animation.duration);
+ var scaled = action.range[0] + (action.range[1] - action.range[0]) * value;
+ if ('params' in action) {
+ if (!('func' in action)) {
+ if (isArray(action.params)) {
+ action.funcParams = [];
+ var len = action.params.length;
+ for (var i = 0; i < len; ++i) {
+ action.funcParams[i] = 'target' == action.params[i]
+ ? targetObject[targetField]
+ : (new Function("return " + action.params[i]))();
+ }
+ } else {
+ action.funcParams = 'target' == action.params
+ ? targetObject[targetField]
+ : (new Function("return " + action.params))();
+ }
+ assert('formula' in action && 'string' == typeof(action.formula));
+ // evaluate inline function to get value
+ action.func = new Function('value', 'params', "return " + action.formula);
+ }
+ scaled = action.func(scaled, action.funcParams);
+ }
+ if (targetObject[targetField] != scaled) {
+ if (modDraw) {
+ display.drawDirty = true;
+ } else {
+ display.paintDirty = true;
+ }
+ targetObject[targetField] = scaled;
+ }
+ }
+ }
+ displayBackend(animationState.displayEngine, animationState.displayList);
+
+ if (stillAnimating) {
+ animationState.requestID = requestAnimationFrame(animateList);
+ }
+}
+
+function flattenPaint(paint) {
+ if (!paint.paint) {
+ return;
+ }
+ var parent = paints[paint.paint];
+ flattenPaint(parent);
+ for (var prop in parent) {
+ if (!(prop in paint)) {
+ paint[prop] = parent[prop];
+ }
+ }
+ paint.paint = null;
+}
+
+function init(engine, keyframe) {
+ animationState.reset(engine);
+ setupPaint();
+ setupBackend(animationState.displayEngine);
+ keyframeInit(keyframe);
+}
+
+function keyframeInit(frame) {
+ animationState.reset();
+ addActions("_default", animationState.timeline);
+ addActions(frame, animationState.timeline);
+ for (var index = 0; index < animationState.timeline.length; ++index) {
+ animationState.timeline[index].position = index;
+ }
+ animationState.timeline.sort(function(a, b) {
+ if (a.time == b.time) {
+ return a.position - b.position;
+ }
+ return a.time - b.time;
+ });
+ keyframeBackendInit(animationState.displayEngine, animationState.displayList,
+ keyframes[frame][0]);
+ animationState.requestID = requestAnimationFrame(animateList);
+}
+
+function loopAddProp(action, propName) {
+ var funcStr = "";
+ var prop = action[propName];
+ if ('draw' != propName && isArray(prop)) {
+ funcStr += '[';
+ for (var index = 0; index < prop.length; ++index) {
+ funcStr += loopAddProp(prop, index);
+ if (index + 1 < prop.length) {
+ funcStr += ", ";
+ }
+ }
+ funcStr += ']';
+ return funcStr;
+ }
+ assert("object" != typeof(prop));
+ var useString = "string" == typeof(prop) && isAlpha(prop.charCodeAt(0));
+ if (useString) {
+ funcStr += "'";
+ }
+ funcStr += prop;
+ if (useString) {
+ funcStr += "'";
+ }
+ return funcStr;
+}
+
+function loopOver(rec, timeline) {
+ var funcStr = "";
+ if (rec.for) {
+ funcStr += "for (" + rec.for[0] + "; " + rec.for[1] + "; " + rec.for[2] + ") {\n";
+ }
+ funcStr += " var time = " + ('time' in rec ? rec.time : 0) + ";\n";
+ funcStr += " var duration = " + ('duration' in rec ? rec.duration : 0) + ";\n";
+ funcStr += " var actions = [];\n";
+ var len = rec.actions.length;
+ for (var i = 0; i < len; ++i) {
+ funcStr += " var action" + i + " = {\n";
+ var action = rec.actions[i];
+ for (var p in action) {
+ funcStr += " '" + p + "':";
+ funcStr += loopAddProp(action, p);
+ funcStr += ",\n";
+ }
+ funcStr = funcStr.substring(0, funcStr.length - 2);
+ funcStr += "\n };\n";
+ funcStr += " actions.push(action" + i + ");\n";
+ }
+ funcStr += " timeline.push( { 'time':time, 'duration':duration, 'actions':actions,"
+ + "'finalized':false } );\n";
+ if (rec.for) {
+ funcStr += "}\n";
+ }
+ var func = new Function('rec', 'timeline', funcStr);
+ func(rec, timeline);
+}
+
+function setupPaint() {
+ for (var prop in paints) {
+ flattenPaint(paints[prop]);
+ }
+}
« no previous file with comments | « no previous file | experimental/docs/backend.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698