runs some sample animations side by side in canvas and svg
TBR=fmalita@chromium.org Review URL: https://codereview.chromium.org/1342523002
This commit is contained in:
parent
73d882e13f
commit
3257c12220
314
experimental/docs/animationCommon.js
Normal file
314
experimental/docs/animationCommon.js
Normal file
@ -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]);
|
||||
}
|
||||
}
|
44
experimental/docs/backend.js
Normal file
44
experimental/docs/backend.js
Normal file
@ -0,0 +1,44 @@
|
||||
function displayBackend(displayEngine, displayList) {
|
||||
switch (displayEngine) {
|
||||
case 'all':
|
||||
displayCanvas(displayList);
|
||||
displaySvg(displayList);
|
||||
break;
|
||||
case 'Canvas':
|
||||
displayCanvas(displayList);
|
||||
break;
|
||||
case 'SVG':
|
||||
displaySvg(displayList);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
function keyframeBackendInit(displayEngine, displayList, first) {
|
||||
switch (displayEngine) {
|
||||
case 'all':
|
||||
case 'Canvas':
|
||||
keyframeCanvasInit(displayList, first);
|
||||
break;
|
||||
case 'SVG':
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
function setupBackend(displayEngine) {
|
||||
switch (displayEngine) {
|
||||
case 'all':
|
||||
case 'Canvas':
|
||||
setupCanvas();
|
||||
setupSvg();
|
||||
break;
|
||||
case 'SVG':
|
||||
setupSvg();
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
167
experimental/docs/canvasBackend.js
Normal file
167
experimental/docs/canvasBackend.js
Normal file
@ -0,0 +1,167 @@
|
||||
var canvas;
|
||||
var ctx;
|
||||
var canvasGradients = {};
|
||||
|
||||
function canvas_rbga(color) {
|
||||
var a = canvas_opacity(color);
|
||||
var r = (color >> 16) & 0xFF;
|
||||
var g = (color >> 8) & 0xFF;
|
||||
var b = (color >> 0) & 0xFF;
|
||||
return "rgba(" + r + "," + g + "," + b + "," + a + ")";
|
||||
}
|
||||
|
||||
function canvas_opacity(color) {
|
||||
var a = (color >> 24) & 0xFF;
|
||||
return a / 255.;
|
||||
}
|
||||
|
||||
function displayCanvas(displayList) {
|
||||
if (displayList.clear) {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
for (var index = 0; index < displayList.length; ++index) {
|
||||
drawToCanvas(displayList[index]);
|
||||
}
|
||||
}
|
||||
|
||||
function drawToCanvas(action) {
|
||||
ctx.save();
|
||||
var paint = paintToCanvas(action.paint);
|
||||
var draw = action.draw;
|
||||
if ('string' == typeof(draw)) {
|
||||
draw = (new Function("return " + draw))();
|
||||
}
|
||||
if (isArray(draw)) {
|
||||
assert(draw.length > 0);
|
||||
var picture = 'draw' in draw[0];
|
||||
if (picture) {
|
||||
for (var index = 0; index < draw.length; ++index) {
|
||||
drawToCanvas(draw[index]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ctx.beginPath();
|
||||
for (var index = 0; index < draw.length; ++index) {
|
||||
for (var prop in draw[index]) {
|
||||
var v = draw[index][prop];
|
||||
switch (prop) {
|
||||
case 'arcTo':
|
||||
ctx.arcTo(v[0], v[1], v[2], v[3], v[4]);
|
||||
break;
|
||||
case 'close':
|
||||
ctx.closePath();
|
||||
break;
|
||||
case 'cubic':
|
||||
ctx.moveTo(v[0], v[1]);
|
||||
ctx.bezierCurveTo(v[2], v[3], v[4], v[5], v[6], v[7]);
|
||||
break;
|
||||
case 'line':
|
||||
ctx.moveTo(v[0], v[1]);
|
||||
ctx.lineTo(v[2], v[3]);
|
||||
break;
|
||||
case 'quad':
|
||||
ctx.moveTo(v[0], v[1]);
|
||||
ctx.quadraticCurveTo(v[2], v[3], v[4], v[5]);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ('fill' == paint.style) {
|
||||
ctx.fill();
|
||||
} else {
|
||||
assert('stroke' == paint.style);
|
||||
ctx.stroke();
|
||||
}
|
||||
} else {
|
||||
assert('string' in draw);
|
||||
if ('fill' == paint.style) {
|
||||
ctx.fillText(draw.string, draw.x, draw.y);
|
||||
} else {
|
||||
assert('stroke' == paint.style);
|
||||
ctx.strokeText(draw.string, draw.x, draw.y);
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function keyframeCanvasInit(displayList, first) {
|
||||
if ('canvas' in first && 'clear' == first.canvas) {
|
||||
displayList.clear = true;
|
||||
}
|
||||
}
|
||||
|
||||
function paintToCanvas(paint) {
|
||||
var color;
|
||||
var inPicture = 'string' == typeof(paint);
|
||||
if (inPicture) {
|
||||
paint = (new Function("return " + paint))();
|
||||
assert('object' == typeof(paint) && !isArray(paint));
|
||||
}
|
||||
if ('gradient' in paint) {
|
||||
var gradient = paint.gradient.split('.');
|
||||
var gradName = gradient[1];
|
||||
if (!canvasGradients[gradName]) {
|
||||
var g = window[gradient[0]][gradient[1]];
|
||||
var grad = ctx.createRadialGradient(g.cx, g.cy, 0, g.cx, g.cy, g.r);
|
||||
var stopLen = g.stops.length;
|
||||
for (var index = 0; index < stopLen; ++index) {
|
||||
var stop = g.stops[index];
|
||||
var color = canvas_rbga(stop.color);
|
||||
grad.addColorStop(index, color);
|
||||
}
|
||||
canvasGradients[gradName] = grad;
|
||||
}
|
||||
color = canvasGradients[gradName];
|
||||
if (!inPicture) {
|
||||
ctx.globalAlpha = canvas_opacity(paint.color);
|
||||
}
|
||||
} else {
|
||||
color = canvas_rbga(paint.color);
|
||||
}
|
||||
if ('fill' == paint.style) {
|
||||
ctx.fillStyle = color;
|
||||
} else if ('stroke' == paint.style) {
|
||||
ctx.strokeStyle = color;
|
||||
} else {
|
||||
ctx.globalAlpha = canvas_opacity(paint.color);
|
||||
}
|
||||
if ('strokeWidth' in paint) {
|
||||
ctx.lineWidth = paint.strokeWidth;
|
||||
}
|
||||
if ('typeface' in paint) {
|
||||
var typeface = typefaces[paint.typeface];
|
||||
var font = typeface.style;
|
||||
if ('textSize' in paint) {
|
||||
font += " " + paint.textSize;
|
||||
}
|
||||
if ('family' in typeface) {
|
||||
font += " " + typeface.family;
|
||||
}
|
||||
ctx.font = font;
|
||||
if ('textAlign' in paint) {
|
||||
ctx.textAlign = paint.textAlign;
|
||||
}
|
||||
if ('textBaseline' in paint) {
|
||||
ctx.textBaseline = paint.textBaseline;
|
||||
}
|
||||
}
|
||||
return paint;
|
||||
}
|
||||
|
||||
function setupCanvas() {
|
||||
canvas = document.getElementById("canvas");
|
||||
ctx = canvas ? canvas.getContext("2d") : null;
|
||||
assert(ctx);
|
||||
var resScale = window.devicePixelRatio ? window.devicePixelRatio : 1;
|
||||
var unscaledWidth = canvas.width;
|
||||
var unscaledHeight = canvas.height;
|
||||
canvas.width = unscaledWidth * resScale;
|
||||
canvas.height = unscaledHeight * resScale;
|
||||
canvas.style.width = unscaledWidth + 'px';
|
||||
canvas.style.height = unscaledHeight + 'px';
|
||||
if (resScale != 1) {
|
||||
ctx.scale(resScale, resScale);
|
||||
}
|
||||
}
|
564
experimental/docs/exampleSlides.js
Normal file
564
experimental/docs/exampleSlides.js
Normal file
@ -0,0 +1,564 @@
|
||||
var circle = {
|
||||
"center":{ "x":200, "y":200 },
|
||||
"radius":100
|
||||
}
|
||||
|
||||
var gradients = {
|
||||
"grad1": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,0,0,255) },
|
||||
{ "offset":1, "color": argb( 0,0,0,255) }
|
||||
]
|
||||
},
|
||||
"grad2": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,0,255,0) },
|
||||
{ "offset":1, "color": argb( 0,0,255,0) }
|
||||
]
|
||||
},
|
||||
"grad3": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,255,0,0) },
|
||||
{ "offset":1, "color": argb( 0,255,0,0) }
|
||||
]
|
||||
},
|
||||
"grad4": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,192,63,192) },
|
||||
{ "offset":1, "color": argb( 0,192,63,192) }
|
||||
]
|
||||
},
|
||||
"grad5": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,127,127,0) },
|
||||
{ "offset":1, "color": argb( 0,127,127,0) }
|
||||
]
|
||||
},
|
||||
"grad6": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,127,0,127) },
|
||||
{ "offset":1, "color": argb( 0,127,0,127) }
|
||||
]
|
||||
},
|
||||
"grad7": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,0,127,127) },
|
||||
{ "offset":1, "color": argb( 0,0,127,127) }
|
||||
]
|
||||
},
|
||||
"grad8": { "cx":200, "cy":200, "r":300,
|
||||
"stops": [
|
||||
{ "offset":0, "color": argb(76,63,192,63) },
|
||||
{ "offset":1, "color": argb( 0,63,192,63) }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var paths = {
|
||||
"cubicSegment1": [
|
||||
{ "cubic": [ 200,200, 200,200, 200,200, 200,200 ] }
|
||||
],
|
||||
"cubicSegment2": [
|
||||
{ "cubic": [ 200,200, 250,200, 300,200, 300,100 ] }
|
||||
],
|
||||
"curveSegment1": [
|
||||
{ "cubic": [ 200,200, 250,200, 300,150, 300,100 ] }
|
||||
],
|
||||
"curveSegment2": [
|
||||
{ "cubic": [ 200,200, 250,200, 300,150, 200,100 ] }
|
||||
],
|
||||
"curveSegment3": [
|
||||
{ "cubic": [ 200,200, 350,200, 250,-150, 170,300 ] }
|
||||
],
|
||||
"diagSegment": [
|
||||
{ "line": [ 200,200, 100,100 ] }
|
||||
],
|
||||
"horzSegment": [
|
||||
{ "line": [ 200,200, 341.4,200 ] }
|
||||
],
|
||||
"lineSegment": [
|
||||
{ "line": [ 200,200, 200 + circle.radius * Math.cos(-22.5 * Math.PI / 180),
|
||||
200 + circle.radius * Math.sin(-22.5 * Math.PI / 180) ] }
|
||||
],
|
||||
"span1": [
|
||||
{ "quad": [ 200,200, 300,300, 200,300 ] }
|
||||
],
|
||||
"span2": [
|
||||
{ "cubic": [ 200,200, 100,300, 100,400, 200,300 ] }
|
||||
],
|
||||
"span3": [
|
||||
{ "cubic": [ 200,200, 300,100, 100,400, 300,200 ] }
|
||||
],
|
||||
"span4": [
|
||||
{ "quad": [ 200,200, 300,300, 400,300 ] }
|
||||
],
|
||||
"span5": [
|
||||
{ "quad": [ 200,200, 280,320, 200,400 ] }
|
||||
],
|
||||
"span6": [
|
||||
{ "quad": [ 200,200, 60,340, 100,400 ] }
|
||||
],
|
||||
"vertSegment": [
|
||||
{ "line": [ 200,200, 200,341.4 ] }
|
||||
],
|
||||
"wedge1": [
|
||||
{ "line": [ 200,200, 500,500 ] },
|
||||
{ "arcTo": [ 375.74,624.36, 200,624.26, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedge2": [
|
||||
{ "line": [ 200,200, 200,624.26 ] },
|
||||
{ "arcTo": [ 24.265,624.26, -100,500, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedge3": [
|
||||
{ "line": [ 200,200, 500,-100 ] },
|
||||
{ "arcTo": [ 1138.22,537.70, 240,622.5, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedge4": [
|
||||
{ "line": [ 200,200, 500,500 ] },
|
||||
{ "arcTo": [ 530.79,438.42, 579.47,389.74, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedge5": [
|
||||
{ "line": [ 200,200, 389.74,579.47 ] },
|
||||
{ "arcTo": [ 284.94,563.441, 200,500, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedge6": [
|
||||
{ "line": [ 200,200, 10.26,579.47 ] },
|
||||
{ "arcTo": [ -51.318,548.68, -100,500, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY1": [
|
||||
{ "line": [ 200,200, 500,-100 ] },
|
||||
{ "arcTo": [ 624.26,24.265, 624.26,200, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY2": [
|
||||
{ "line": [ 200,200, 200,-175.74 ] },
|
||||
{ "arcTo": [ 364.83,-196.61, 500,-100, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY3": [
|
||||
{ "line": [ 200,200, -100,-100 ] },
|
||||
{ "arcTo": [ 35.170,-196.61, 200,-175.74, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY4": [
|
||||
{ "line": [ 200,200, -175.74,200 ] },
|
||||
{ "arcTo": [ -196.61,35.170, -100,-100, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY5": [
|
||||
{ "line": [ 200,200, -100,500 ] },
|
||||
{ "arcTo": [ -196.61,364.83, -175.74,200, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY6": [
|
||||
{ "line": [ 200,200, -100,500 ] },
|
||||
{ "arcTo": [ 75.735,500, 200,624.26, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY7": [
|
||||
{ "line": [ 200,200, 200,624.26 ] },
|
||||
{ "arcTo": [ 324.26,500, 500,500, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"wedgeXY8": [
|
||||
{ "line": [ 200,200, 500,500 ] },
|
||||
{ "arcTo": [ 500,324.26, 624.26,200, 424.26 ] },
|
||||
{ "close": null }
|
||||
],
|
||||
"xaxis": [
|
||||
{ "line": [ 100,200, 300,200 ] }
|
||||
],
|
||||
"yaxis": [
|
||||
{ "line": [ 200,100, 200,300 ] }
|
||||
]
|
||||
};
|
||||
|
||||
var text = {
|
||||
"curve1d1": {
|
||||
"string":"Some curves initially occupy", "x":400, "y":200
|
||||
},
|
||||
"curve1d2": {
|
||||
"string":"one-dimensional sectors, then diverge.", "x":400, "y":240
|
||||
},
|
||||
"curveMultiple1": {
|
||||
"string":"A curve span may cover more", "x":400, "y":200
|
||||
},
|
||||
"curveMultiple2": {
|
||||
"string":"than one sector.", "x":400, "y":240
|
||||
},
|
||||
"line1DDest1": {
|
||||
"string":"Some lines occupy one-dimensional", "x":400, "y":200
|
||||
},
|
||||
"line1DDest2": {
|
||||
"string":"sectors.", "x":400, "y":240
|
||||
},
|
||||
"lineSingle": {
|
||||
"string":"Line spans are contained by a single sector.", "x":400, "y":200
|
||||
},
|
||||
"sector1": {
|
||||
"string":"A sector is a wedge of a circle", "x":400, "y":200
|
||||
},
|
||||
"sector2": {
|
||||
"string":"containing a range of points.", "x":400, "y":240
|
||||
},
|
||||
"sectorXY1": {
|
||||
"string":"X > 0 Y < 0 -Y < X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY2": {
|
||||
"string":"X > 0 Y < 0 -Y > X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY3": {
|
||||
"string":"X < 0 Y < 0 Y < X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY4": {
|
||||
"string":"X < 0 Y < 0 Y > X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY5": {
|
||||
"string":"X < 0 Y > 0 -Y > X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY6": {
|
||||
"string":"X < 0 Y > 0 -Y < X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY7": {
|
||||
"string":"X > 0 Y > 0 Y > X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY8": {
|
||||
"string":"X > 0 Y > 0 Y < X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY9": {
|
||||
"string":"X > 0 Y == 0", "x":500, "y":460
|
||||
},
|
||||
"sectorXY10": {
|
||||
"string":"Y > 0 0 == X", "x":500, "y":460
|
||||
},
|
||||
"sectorXY11": {
|
||||
"string":"X < 0 Y == X", "x":500, "y":460
|
||||
},
|
||||
"sectorXYA": {
|
||||
"string":"X > 0 Y > 0 Y < X", "x":500, "y":310
|
||||
},
|
||||
"sectorXYB": {
|
||||
"string":"X < 0 Y > 0 -Y < X", "x":500, "y":360
|
||||
},
|
||||
"sectorXYC": {
|
||||
"string":"X < 0 Y < 0 Y < X", "x":500, "y":410
|
||||
},
|
||||
"spanWedge": {
|
||||
"string":"All spans are contained by a wedge", "x":400, "y":200
|
||||
},
|
||||
"trivialWedge1": {
|
||||
"string":"Wedges that don't overlap can be", "x":400, "y":200
|
||||
},
|
||||
"trivialWedge2": {
|
||||
"string":"easily sorted.", "x":400, "y":240
|
||||
},
|
||||
"xaxis1": {
|
||||
"string":"-X", "x":100, "y":220
|
||||
},
|
||||
"xaxis2": {
|
||||
"string":"+X", "x":300, "y":220
|
||||
},
|
||||
"yaxis1": {
|
||||
"string":"-Y", "x":205, "y":100
|
||||
},
|
||||
"yaxis2": {
|
||||
"string":"+Y", "x":205, "y":300
|
||||
}
|
||||
};
|
||||
|
||||
var typefaces = {
|
||||
"description": { "style":"normal", "family":"Helvetica,Arial" }
|
||||
};
|
||||
|
||||
var paints = {
|
||||
"axisStroke": { "style":"stroke", "color":rgb(191,191,191) },
|
||||
"axisTextDesc": { "paint":"textBase", "color":rgb(191,191,191) },
|
||||
"axisTextRight": { "paint":"axisTextDesc", "textAlign":"right" },
|
||||
"axisTextTop": { "paint":"axisTextDesc", "textBaseline":"hanging" },
|
||||
"diagSegment": { "style":"stroke", "color":rgb(127,63,127), "strokeWidth":2 },
|
||||
"gradient1": { "style":"fill", "gradient":"gradients.grad1", "color":alpha(255) },
|
||||
"gradient2": { "paint":"gradient1", "gradient":"gradients.grad2" },
|
||||
"gradient3": { "paint":"gradient1", "gradient":"gradients.grad3" },
|
||||
"gradient4": { "paint":"gradient1", "gradient":"gradients.grad4" },
|
||||
"gradient5": { "paint":"gradient1", "gradient":"gradients.grad5" },
|
||||
"gradient6": { "paint":"gradient1", "gradient":"gradients.grad6" },
|
||||
"gradient7": { "paint":"gradient1", "gradient":"gradients.grad7" },
|
||||
"gradient8": { "paint":"gradient1", "gradient":"gradients.grad8" },
|
||||
"horzSegment": { "paint":"diagSegment", "color":rgb(192,92,31) },
|
||||
"picture": { "color":alpha(255) },
|
||||
"sectorADesc": { "paint":"textBase", "color":rgb(0,0,255) },
|
||||
"sectorBDesc": { "paint":"textBase", "color":rgb(0,127,0) },
|
||||
"sectorCDesc": { "paint":"textBase", "color":rgb(255,0,0) },
|
||||
"sectorXY1": { "paint":"textBase", "color":rgb(192,63,192) },
|
||||
"sectorXY2": { "paint":"textBase", "color":rgb(127,127,0) },
|
||||
"sectorXY3": { "paint":"textBase", "color":rgb(255,0,0) },
|
||||
"sectorXY4": { "paint":"textBase", "color":rgb(127,0,127) },
|
||||
"sectorXY5": { "paint":"textBase", "color":rgb(0,127,127) },
|
||||
"sectorXY6": { "paint":"textBase", "color":rgb(0,127,0) },
|
||||
"sectorXY7": { "paint":"textBase", "color":rgb(63,192,63) },
|
||||
"sectorXY8": { "paint":"textBase", "color":rgb(0,0,255) },
|
||||
"sectorXY9": { "paint":"textBase", "color":rgb(192,92,31) },
|
||||
"sectorXY10": { "paint":"textBase", "color":rgb(31,92,192) },
|
||||
"sectorXY11": { "paint":"textBase", "color":rgb(127,63,127) },
|
||||
|
||||
"stroke": { "style":"stroke", "color":rgb(0,0,0) },
|
||||
"textBase": { "style":"fill", "color":rgb(0,0,0), "typeface":"description",
|
||||
"textSize":"1.3rem" },
|
||||
"vertSegment": { "paint":"diagSegment", "color":rgb(31,92,192) },
|
||||
};
|
||||
|
||||
var pictures = {
|
||||
"curve1DDestText": [
|
||||
{ "draw":"text.curve1d1", "paint":"paints.textBase" },
|
||||
{ "draw":"text.curve1d2", "paint":"paints.textBase" }
|
||||
],
|
||||
"curveMultipleText": [
|
||||
{ "draw":"text.curveMultiple1", "paint":"paints.textBase" },
|
||||
{ "draw":"text.curveMultiple2", "paint":"paints.textBase" }
|
||||
],
|
||||
"line1DDestText": [
|
||||
{ "draw":"text.line1DDest1", "paint":"paints.textBase" },
|
||||
{ "draw":"text.line1DDest2", "paint":"paints.textBase" }
|
||||
],
|
||||
"sectorXYA": [
|
||||
{ "draw":"text.sectorXYA", "paint":"paints.sectorADesc" },
|
||||
{ "draw":"paths.wedgeXY8", "paint":"paints.gradient1" }
|
||||
],
|
||||
"sectorXYB": [
|
||||
{ "draw":"text.sectorXYB", "paint":"paints.sectorBDesc" },
|
||||
{ "draw":"paths.wedgeXY6", "paint":"paints.gradient2" }
|
||||
],
|
||||
"sectorXYC": [
|
||||
{ "draw":"text.sectorXYC", "paint":"paints.sectorCDesc" },
|
||||
{ "draw":"paths.wedgeXY3", "paint":"paints.gradient3" }
|
||||
],
|
||||
"sectorText": [
|
||||
{ "draw":"text.sector1", "paint":"paints.textBase" },
|
||||
{ "draw":"text.sector2", "paint":"paints.textBase" }
|
||||
],
|
||||
"trivialWedgeSpans": [
|
||||
{ "draw":"paths.span4", "paint":"paints.stroke" },
|
||||
{ "draw":"paths.wedge4", "paint":"paints.gradient4" },
|
||||
{ "draw":"paths.span5", "paint":"paints.stroke" },
|
||||
{ "draw":"paths.wedge5", "paint":"paints.gradient5" },
|
||||
{ "draw":"paths.span6", "paint":"paints.stroke" },
|
||||
{ "draw":"paths.wedge6", "paint":"paints.gradient6" }
|
||||
],
|
||||
"trivialWedgeText": [
|
||||
{ "draw":"text.trivialWedge1", "paint":"paints.textBase" },
|
||||
{ "draw":"text.trivialWedge2", "paint":"paints.textBase" }
|
||||
],
|
||||
"xaxis": [
|
||||
{ "draw":"paths.xaxis", "paint":"paints.axisStroke" },
|
||||
{ "draw":"text.xaxis1", "paint":"paints.axisTextDesc" },
|
||||
{ "draw":"text.xaxis2", "paint":"paints.axisTextRight" }
|
||||
],
|
||||
"yaxis": [
|
||||
{ "draw":"paths.yaxis", "paint":"paints.axisStroke" },
|
||||
{ "draw":"text.yaxis1", "paint":"paints.axisTextTop" },
|
||||
{ "draw":"text.yaxis2", "paint":"paints.axisTextDesc" }
|
||||
],
|
||||
"axes": [
|
||||
{ "draw":"pictures.xaxis", "paint":"paints.picture" },
|
||||
{ "draw":"pictures.yaxis", "paint":"paints.picture" }
|
||||
]
|
||||
};
|
||||
|
||||
var gradientLookup = [
|
||||
0, 4, 5, 3, 6, 7, 2, 8, 1
|
||||
];
|
||||
|
||||
var keyframes = {
|
||||
"_default": [
|
||||
{ "actions": [
|
||||
{ "range":[0,255], "paint":"paints.picture", "target":"paint.color",
|
||||
"params":"target", "formula":"alpha(value, params)" }
|
||||
]}
|
||||
],
|
||||
"keyframe1": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"text.spanWedge", "paint":"paints.textBase" }
|
||||
]},
|
||||
{ "time":1000, "duration":1000, "actions": [
|
||||
{ "ref":"span1", "draw":"paths.span1", "paint":"paints.stroke" }
|
||||
]},
|
||||
{ "time":1500, "duration":1500, "actions": [
|
||||
{ "ref":"wedge1", "draw":"paths.wedge1", "paint":"paints.gradient1" }
|
||||
]},
|
||||
{ "time":3500, "duration": 500, "actions": [
|
||||
{ "ref":"span1", "range":[255,0] },
|
||||
{ "ref":"wedge1", "range":[255,0] }
|
||||
]},
|
||||
{ "time":4000, "duration":1000, "actions": [
|
||||
{ "ref":"span2", "draw":"paths.span2", "paint":"paints.stroke" }
|
||||
]},
|
||||
{ "time":4500, "duration":1500, "actions": [
|
||||
{ "ref":"wedge2", "draw":"paths.wedge2", "paint":"paints.gradient2" }
|
||||
]},
|
||||
{ "time":6500, "duration": 500, "actions": [
|
||||
{ "ref":"span2", "range":[255,0] },
|
||||
{ "ref":"wedge2", "range":[255,0] }
|
||||
]},
|
||||
{ "time":7000, "duration":1000, "actions": [
|
||||
{ "draw":"paths.span3", "paint":"paints.stroke" }
|
||||
]},
|
||||
{ "time":7500, "duration":1500, "actions": [
|
||||
{ "draw":"paths.wedge3", "paint":"paints.gradient3" }
|
||||
]}
|
||||
],
|
||||
"keyframe2": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"pictures.trivialWedgeText", "paint":"paints.picture" }
|
||||
]},
|
||||
{ "time":2000, "duration":1500, "actions": [
|
||||
{ "draw":"pictures.trivialWedgeSpans", "paint":"paints.picture" }
|
||||
]}
|
||||
],
|
||||
"keyframe3": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"pictures.sectorText" },
|
||||
{ "draw":"pictures.xaxis" }
|
||||
]},
|
||||
{ "time": 500, "duration":1000, "actions": [
|
||||
{ "draw":"pictures.yaxis" }
|
||||
]},
|
||||
{ "time":2000, "duration":1500, "actions": [
|
||||
{ "draw":"pictures.sectorXYA" }
|
||||
]},
|
||||
{ "time":3000, "duration":1500, "actions": [
|
||||
{ "draw":"pictures.sectorXYB" }
|
||||
]},
|
||||
{ "time":4000, "duration":1500, "actions": [
|
||||
{ "draw":"pictures.sectorXYC" }
|
||||
]}
|
||||
],
|
||||
"keyframe4": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"text.lineSingle", "paint":"paints.textBase" },
|
||||
{ "draw":"pictures.axes" }
|
||||
]},
|
||||
{ "time":1000, "duration":1000, "actions": [
|
||||
{ "ref":"line", "draw":"paths.lineSegment", "paint":"paints.stroke" }
|
||||
]},
|
||||
{ "time":1850, "duration":1000, "actions": [
|
||||
{ "ref":"sectorXY1", "draw":"text.sectorXY1", "paint":"paints.sectorXY1" },
|
||||
{ "ref":"sectorXY1", "target":"draw.y", "formula":260 },
|
||||
{ "ref":"wedgeXY1", "draw":"paths.wedgeXY1", "paint":"paints.gradient4" }
|
||||
]},
|
||||
{ "time":3000, "duration":4000, "actions": [
|
||||
{ "ref":"line", "target":"draw[0].line[2]",
|
||||
"range":[-22.5 * Math.PI / 180, (-22.5 - 360) * Math.PI / 180], "params":"circle",
|
||||
"formula":"params.center.x + params.radius * Math.cos(value)"
|
||||
},
|
||||
{ "ref":"line", "target":"draw[0].line[3]",
|
||||
"range":[-22.5 * Math.PI / 180, (-22.5 - 360) * Math.PI / 180], "params":"circle",
|
||||
"formula":"params.center.y + params.radius * Math.sin(value)"
|
||||
}
|
||||
]},
|
||||
{ "for":["i=2", "i<=8", "++i"], "time":"2250 + 500 * i", "duration":100, "actions": [
|
||||
{ "ref":"'sectorXY' + i", "draw":"'text.sectorXY' + i",
|
||||
"paint":"'paints.sectorXY' + i" },
|
||||
{ "ref":"'sectorXY' + i", "target":"draw.y", "formula":260 },
|
||||
{ "ref":"'wedgeXY' + i", "draw":"'paths.wedgeXY' + i",
|
||||
"paint":"'paints.gradient' + gradientLookup[i]" },
|
||||
{ "ref":"'sectorXY' + (i - 1)", "range":[255,0] },
|
||||
{ "ref":"'wedgeXY' + (i - 1)", "range":[255,0] }
|
||||
]},
|
||||
{ "time":2250 + 500 * 9, "duration":100, "actions": [
|
||||
{ "ref":"sectorXY1" },
|
||||
{ "ref":"wedgeXY1" },
|
||||
{ "ref":"sectorXY8", "range":[255,0] },
|
||||
{ "ref":"wedgeXY8", "range":[255,0] }
|
||||
]}
|
||||
],
|
||||
"keyframe5": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"pictures.curveMultipleText" },
|
||||
{ "draw":"pictures.axes" }
|
||||
]},
|
||||
{ "time":1000, "duration":1000, "actions": [
|
||||
{ "ref":"curve", "draw":"paths.curveSegment1", "paint":"paints.stroke" }
|
||||
]},
|
||||
{ "time":2000, "duration":1000, "actions": [
|
||||
{ "draw":"text.sectorXY1", "paint":"paints.sectorXY1",
|
||||
"target":"draw.y", "formula":260 + 1 * 25},
|
||||
{ "draw":"paths.wedgeXY1", "paint":"paints.gradient4" }
|
||||
]},
|
||||
{ "time":3000, "duration":1000, "actions": [
|
||||
{ "ref":"curve", "range":[0,1], "target":"draw",
|
||||
"params":["paths.curveSegment1","paths.curveSegment2"],
|
||||
"formula":"interp_paths(value, params)"
|
||||
}
|
||||
]},
|
||||
{ "time":4000, "duration":1000, "actions": [
|
||||
{ "draw":"text.sectorXY2", "paint":"paints.sectorXY2",
|
||||
"target":"draw.y", "formula":260 + 2 * 25},
|
||||
{ "draw":"paths.wedgeXY2", "paint":"paints.gradient5" }
|
||||
]},
|
||||
{ "time":5000, "duration":1000, "actions": [
|
||||
{ "ref":"curve", "range":[0,1], "target":"draw",
|
||||
"params":["paths.curveSegment2","paths.curveSegment3"],
|
||||
"formula":"interp_paths(value, params)"
|
||||
}
|
||||
]},
|
||||
{ "for":["i=3", "i<=6", "++i"], "time":"6000", "actions": [
|
||||
{ "ref":"'text' + i", "draw":"'text.sectorXY' + i", "paint":"'paints.sectorXY' + i",
|
||||
"target":"draw.y", "formula":"260 + i * 25" },
|
||||
]},
|
||||
{ "for":["i=3", "i<=6", "++i"], "time":"6000", "duration":1000, "actions": [
|
||||
{ "ref":"'text' + i" },
|
||||
]},
|
||||
{ "time":6000, "duration":1000, "actions": [
|
||||
{ "draw":"paths.wedgeXY3", "paint":"paints.gradient3" },
|
||||
{ "draw":"paths.wedgeXY4", "paint":"paints.gradient6" },
|
||||
{ "draw":"paths.wedgeXY5", "paint":"paints.gradient7" },
|
||||
{ "draw":"paths.wedgeXY6", "paint":"paints.gradient2" },
|
||||
]}
|
||||
],
|
||||
"keyframe6": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"pictures.line1DDestText" },
|
||||
{ "draw":"pictures.axes" }
|
||||
]},
|
||||
{ "time":2000, "duration":1000, "actions": [
|
||||
{ "ref":"xy9", "draw":"text.sectorXY9", "paint":"paints.sectorXY9" },
|
||||
{ "ref":"xy9", "target":"draw.y", "formula":260 + 25},
|
||||
{ "draw":"paths.horzSegment", "paint":"paints.horzSegment" }
|
||||
]},
|
||||
{ "time":3000, "duration":1000, "actions": [
|
||||
{ "ref":"xy10", "draw":"text.sectorXY10", "paint":"paints.sectorXY10" },
|
||||
{ "ref":"xy10", "target":"draw.y", "formula":260 + 50 },
|
||||
{ "draw":"paths.vertSegment", "paint":"paints.vertSegment" }
|
||||
]},
|
||||
{ "time":4000, "duration":1000, "actions": [
|
||||
{ "ref":"xy11", "draw":"text.sectorXY11", "paint":"paints.sectorXY11" },
|
||||
{ "ref":"xy11", "target":"draw.y", "formula":260 + 75 },
|
||||
{ "draw":"paths.diagSegment", "paint":"paints.diagSegment" }
|
||||
]}
|
||||
],
|
||||
"keyframe7": [
|
||||
{ "time": 0, "duration":1000, "canvas":"clear", "actions": [
|
||||
{ "draw":"pictures.curve1DDestText" },
|
||||
{ "draw":"pictures.axes" }
|
||||
]},
|
||||
{ "time":2000, "duration":1000, "actions": [
|
||||
{ "ref":"cubic", "draw":"paths.cubicSegment1", "paint":"paints.stroke" },
|
||||
{ "ref":"cubic", "range":[0,1], "target":"draw",
|
||||
"params":"paths.cubicSegment2", "formula":"path_partial(value, params)" },
|
||||
{ "ref":"xy9", "draw":"text.sectorXY9", "paint":"paints.sectorXY9" },
|
||||
{ "ref":"xy9", "target":"draw.y", "formula":260 + 25},
|
||||
{ "draw":"paths.horzSegment", "paint":"paints.horzSegment" }
|
||||
]},
|
||||
{ "time":3000, "duration":1000, "actions": [
|
||||
{ "ref":"xy1", "draw":"text.sectorXY1", "paint":"paints.sectorXY1" },
|
||||
{ "ref":"xy1", "target":"draw.y", "formula":260 + 60},
|
||||
{ "draw":"paths.wedgeXY1", "paint":"paints.gradient4" }
|
||||
]},
|
||||
]
|
||||
};
|
84
experimental/docs/interpolatorFunctions.js
Normal file
84
experimental/docs/interpolatorFunctions.js
Normal file
@ -0,0 +1,84 @@
|
||||
function interp(A, B, t) {
|
||||
return A + (B - A) * t;
|
||||
}
|
||||
|
||||
function interp_cubic_coords(x1, x2, x3, x4, t)
|
||||
{
|
||||
var ab = interp(x1, x2, t);
|
||||
var bc = interp(x2, x3, t);
|
||||
var cd = interp(x3, x4, t);
|
||||
var abc = interp(ab, bc, t);
|
||||
var bcd = interp(bc, cd, t);
|
||||
var abcd = interp(abc, bcd, t);
|
||||
return abcd;
|
||||
}
|
||||
|
||||
// FIXME : only works for path with single cubic
|
||||
function path_partial(value, path) {
|
||||
assert(isArray(path));
|
||||
var out = [];
|
||||
for (var cIndex = 0; cIndex < path.length; ++cIndex) {
|
||||
out[cIndex] = {};
|
||||
var curveKey = Object.keys(path[cIndex])[0];
|
||||
var curve = path[cIndex][curveKey];
|
||||
var outArray;
|
||||
switch (curveKey) {
|
||||
case "cubic":
|
||||
var x1 = curve[0], y1 = curve[1], x2 = curve[2], y2 = curve[3];
|
||||
var x3 = curve[4], y3 = curve[5], x4 = curve[6], y4 = curve[7];
|
||||
var t1 = 0, t2 = value;
|
||||
var ax = interp_cubic_coords(x1, x2, x3, x4, t1);
|
||||
var ay = interp_cubic_coords(y1, y2, y3, y4, t1);
|
||||
var ex = interp_cubic_coords(x1, x2, x3, x4, (t1*2+t2)/3);
|
||||
var ey = interp_cubic_coords(y1, y2, y3, y4, (t1*2+t2)/3);
|
||||
var fx = interp_cubic_coords(x1, x2, x3, x4, (t1+t2*2)/3);
|
||||
var fy = interp_cubic_coords(y1, y2, y3, y4, (t1+t2*2)/3);
|
||||
var dx = interp_cubic_coords(x1, x2, x3, x4, t2);
|
||||
var dy = interp_cubic_coords(y1, y2, y3, y4, t2);
|
||||
var mx = ex * 27 - ax * 8 - dx;
|
||||
var my = ey * 27 - ay * 8 - dy;
|
||||
var nx = fx * 27 - ax - dx * 8;
|
||||
var ny = fy * 27 - ay - dy * 8;
|
||||
var bx = (mx * 2 - nx) / 18;
|
||||
var by = (my * 2 - ny) / 18;
|
||||
var cx = (nx * 2 - mx) / 18;
|
||||
var cy = (ny * 2 - my) / 18;
|
||||
outArray = [
|
||||
ax, ay, bx, by, cx, cy, dx, dy
|
||||
];
|
||||
break;
|
||||
default:
|
||||
assert(0); // unimplemented
|
||||
}
|
||||
out[cIndex][curveKey] = outArray;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function interp_paths(value, paths) {
|
||||
assert(isArray(paths));
|
||||
assert(paths.length == 2);
|
||||
var curves0 = paths[0];
|
||||
assert(isArray(curves0));
|
||||
var curves1 = paths[1];
|
||||
assert(isArray(curves1));
|
||||
assert(curves0.length == curves1.length);
|
||||
var out = [];
|
||||
for (var cIndex = 0; cIndex < curves0.length; ++cIndex) {
|
||||
out[cIndex] = {};
|
||||
var curve0Key = Object.keys(curves0[cIndex])[0];
|
||||
var curve1Key = Object.keys(curves1[cIndex])[0];
|
||||
assert(curve0Key == curve1Key);
|
||||
var curve0 = curves0[cIndex][curve0Key];
|
||||
var curve1 = curves1[cIndex][curve1Key];
|
||||
assert(isArray(curve0));
|
||||
assert(isArray(curve1));
|
||||
assert(curve0.length == curve1.length);
|
||||
var outArray = [];
|
||||
for (var i = 0; i < curve1.length; ++i) {
|
||||
outArray[i] = curve0[i] + (curve1[i] - curve0[i]) * value;
|
||||
}
|
||||
out[cIndex][curve0Key] = outArray;
|
||||
}
|
||||
return out;
|
||||
}
|
41
experimental/docs/jsonbaseddoc.htm
Normal file
41
experimental/docs/jsonbaseddoc.htm
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<script src="utilities.js"></script>
|
||||
|
||||
<script src="animationCommon.js"></script>
|
||||
<script src="backend.js"></script>
|
||||
<script src="canvasBackend.js"></script>
|
||||
<script src="exampleSlides.js"></script>
|
||||
<script src="interpolatorFunctions.js"></script>
|
||||
<script src="svgBackend.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
var frame = 1;
|
||||
|
||||
function keypress() {
|
||||
init('all', 'keyframe' + frame);
|
||||
if (++frame > 7) {
|
||||
frame = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function onload() {
|
||||
init('all', 'keyframe6');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onLoad="onload()" onKeypress="keypress()">
|
||||
|
||||
<canvas id="canvas" width="770" height="500" ></canvas>
|
||||
|
||||
<svg id="svg" width="770" height="500"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" />
|
||||
|
||||
</body>
|
||||
</html>
|
246
experimental/docs/svgBackend.js
Normal file
246
experimental/docs/svgBackend.js
Normal file
@ -0,0 +1,246 @@
|
||||
var svgCache;
|
||||
var svgDefs;
|
||||
var svgGradients;
|
||||
var svgNS = "http://www.w3.org/2000/svg";
|
||||
var svgRoot;
|
||||
|
||||
function displaySvg(displayList) {
|
||||
for (var index = 0; index < displayList.length; ++index) {
|
||||
drawToSvg(displayList[index]);
|
||||
}
|
||||
}
|
||||
|
||||
function drawToSvg(display) {
|
||||
assert('string' == typeof(display.ref));
|
||||
var cache;
|
||||
if (display.ref in svgCache) {
|
||||
cache = svgCache[display.ref];
|
||||
if (display.drawDirty) {
|
||||
switch (cache.spec) {
|
||||
case "paths":
|
||||
svgSetPathData(cache.element, display.draw);
|
||||
break;
|
||||
case "pictures":
|
||||
svgSetPictureData(cache.element, display.draw);
|
||||
break;
|
||||
case "text":
|
||||
svgCreateText(cache.element, display.draw);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cache = {};
|
||||
cache.action = display;
|
||||
cache.spec = display.drawSpec;
|
||||
var dot = cache.spec.indexOf(".");
|
||||
if (dot > 0) {
|
||||
cache.spec = cache.spec.substring(0, dot);
|
||||
}
|
||||
switch (cache.spec) {
|
||||
case "paths":
|
||||
cache.element = svgCreatePath(display.ref, display.draw);
|
||||
break;
|
||||
case "pictures":
|
||||
cache.element = svgCreatePicture(display.ref, display.draw);
|
||||
break;
|
||||
case "text":
|
||||
cache.element = svgCreateText(display.ref, display.draw);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
display.drawDirty = false;
|
||||
if (display.paintDirty) {
|
||||
svgSetPaintData(cache.element, display.paint);
|
||||
var opacity = svg_opacity(display.paint.color);
|
||||
cache.element.setAttribute("fill-opacity", opacity);
|
||||
cache.element.setAttribute("stroke-opacity", opacity);
|
||||
display.paintDirty = false;
|
||||
}
|
||||
assert('object' == typeof(cache));
|
||||
if (!(display.ref in svgCache)) {
|
||||
svgRoot.appendChild(cache.element);
|
||||
svgCache[display.ref] = cache;
|
||||
}
|
||||
}
|
||||
|
||||
function setupSvg() {
|
||||
svgCache = { "paths":{}, "pictures":{}, "text":{} };
|
||||
svgDefs = document.createElementNS(svgNS, "defs");
|
||||
svgGradients = {};
|
||||
svgRoot = document.getElementById("svg");
|
||||
while (svgRoot.lastChild) {
|
||||
svgRoot.removeChild(svgRoot.lastChild);
|
||||
}
|
||||
svgRoot.appendChild(svgDefs);
|
||||
}
|
||||
|
||||
function svg_rbg(color) {
|
||||
return "rgb(" + ((color >> 16) & 0xFF)
|
||||
+ "," + ((color >> 8) & 0xFF)
|
||||
+ "," + ((color >> 0) & 0xFF) + ")";
|
||||
}
|
||||
|
||||
function svg_opacity(color) {
|
||||
return ((color >> 24) & 0xFF) / 255.0;
|
||||
}
|
||||
|
||||
function svgCreatePath(key, path) {
|
||||
var svgPath = document.createElementNS(svgNS, "path");
|
||||
svgPath.setAttribute("id", key);
|
||||
svgSetPathData(svgPath, path);
|
||||
return svgPath;
|
||||
}
|
||||
|
||||
function svgCreatePicture(key, picture) {
|
||||
var svgPicture = document.createElementNS(svgNS, "g");
|
||||
svgPicture.setAttribute("id", key);
|
||||
svgSetPictureData(svgPicture, picture);
|
||||
return svgPicture;
|
||||
}
|
||||
|
||||
function svgCreateRadialGradient(key) {
|
||||
var g = gradients[key];
|
||||
var e = document.createElementNS(svgNS, "radialGradient");
|
||||
e.setAttribute("id", key);
|
||||
e.setAttribute("cx", g.cx);
|
||||
e.setAttribute("cy", g.cy);
|
||||
e.setAttribute("r", g.r);
|
||||
e.setAttribute("gradientUnits", "userSpaceOnUse");
|
||||
var stopLen = g.stops.length;
|
||||
for (var index = 0; index < stopLen; ++index) {
|
||||
var stop = g.stops[index];
|
||||
var color = svg_rbg(stop.color);
|
||||
var s = document.createElementNS(svgNS, 'stop');
|
||||
s.setAttribute("offset", stop.offset);
|
||||
var style = "stop-color:" + svg_rbg(stop.color) + "; stop-opacity:"
|
||||
+ svg_opacity(stop.color);
|
||||
s.setAttribute("style", style);
|
||||
e.appendChild(s);
|
||||
}
|
||||
svgGradients[key] = e;
|
||||
svgDefs.appendChild(e);
|
||||
}
|
||||
|
||||
function svgCreateText(key, text) {
|
||||
var svgText = document.createElementNS(svgNS, "text");
|
||||
svgText.setAttribute("id", key);
|
||||
var textNode = document.createTextNode(text.string);
|
||||
svgText.appendChild(textNode);
|
||||
svgSetTextData(svgText, text);
|
||||
return svgText;
|
||||
}
|
||||
|
||||
function svgSetPathData(svgPath, path) {
|
||||
var dString = "";
|
||||
for (var cIndex = 0; cIndex < path.length; ++cIndex) {
|
||||
var curveKey = Object.keys(path[cIndex])[0];
|
||||
var v = path[cIndex][curveKey];
|
||||
switch (curveKey) {
|
||||
case 'arcTo':
|
||||
var clockwise = 1; // to do; work in general case
|
||||
dString += " A" + v[4] + "," + v[4] + " 0 0," + clockwise + " "
|
||||
+ v[2] + "," + v[3];
|
||||
break;
|
||||
case 'close':
|
||||
dString += " z";
|
||||
break;
|
||||
case 'cubic':
|
||||
dString += " M" + v[0] + "," + v[1];
|
||||
dString += " C" + v[2] + "," + v[3]
|
||||
+ " " + v[4] + "," + v[5]
|
||||
+ " " + v[6] + "," + v[7];
|
||||
break;
|
||||
case 'line':
|
||||
dString += " M" + v[0] + "," + v[1];
|
||||
dString += " L" + v[2] + "," + v[3];
|
||||
break;
|
||||
case 'quad':
|
||||
dString += " M" + v[0] + "," + v[1];
|
||||
dString += " Q" + v[2] + "," + v[3]
|
||||
+ " " + v[4] + "," + v[5];
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
svgPath.setAttribute("d", dString);
|
||||
}
|
||||
|
||||
function svgSetPaintData(svgElement, paint) {
|
||||
var color;
|
||||
var inPicture = 'string' == typeof(paint);
|
||||
if (inPicture) {
|
||||
paint = (new Function("return " + paint))();
|
||||
assert('object' == typeof(paint) && !isArray(paint));
|
||||
}
|
||||
if ('gradient' in paint) {
|
||||
var gradient = paint.gradient.split('.');
|
||||
var gradName = gradient[1];
|
||||
if (!svgGradients[gradName]) {
|
||||
svgCreateRadialGradient(gradName);
|
||||
}
|
||||
color = "url(#" + gradName + ")";
|
||||
} else {
|
||||
color = svg_rbg(paint.color);
|
||||
}
|
||||
svgElement.setAttribute("fill", 'fill' == paint.style ? color : "none");
|
||||
if ('stroke' == paint.style) {
|
||||
svgElement.setAttribute("stroke", color);
|
||||
}
|
||||
if ('strokeWidth' in paint) {
|
||||
svgElement.setAttribute("stroke-width", paint.strokeWidth);
|
||||
}
|
||||
if ('typeface' in paint) {
|
||||
var typeface = typefaces[paint.typeface];
|
||||
var font = typeface.style;
|
||||
if ('textSize' in paint) {
|
||||
svgElement.setAttribute("font-size", paint.textSize);
|
||||
}
|
||||
if ('family' in typeface) {
|
||||
svgElement.setAttribute("font-family", typeface.family);
|
||||
}
|
||||
if ('textAlign' in paint) {
|
||||
svgElement.setAttribute("text-anchor", paint.textAlign == "right" ? "end" : assert(0));
|
||||
}
|
||||
if ('textBaseline' in paint) {
|
||||
svgElement.setAttribute("alignment-baseline", paint.textBaseline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function svgSetPictureData(svgPicture, picture) {
|
||||
while (svgPicture.lastChild) {
|
||||
svgPicture.removeChild(svgPicture.lastChild);
|
||||
}
|
||||
for (var index = 0; index < picture.length; ++index) {
|
||||
var entry = picture[index];
|
||||
var drawObj = (new Function("return " + entry.draw))();
|
||||
var drawSpec = entry.draw.split('.');
|
||||
var svgElement;
|
||||
switch (drawSpec[0]) {
|
||||
case 'paths':
|
||||
svgElement = svgCreatePath(drawSpec[1], drawObj);
|
||||
break;
|
||||
case 'pictures':
|
||||
svgElement = svgCreatePicture(drawSpec[1], drawObj);
|
||||
break;
|
||||
case 'text':
|
||||
svgElement = svgCreateText(drawSpec[1], drawObj);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
var paintObj = (new Function("return " + entry.paint))();
|
||||
svgSetPaintData(svgElement, paintObj);
|
||||
svgPicture.appendChild(svgElement);
|
||||
}
|
||||
}
|
||||
|
||||
function svgSetTextData(svgElement, text) {
|
||||
svgElement.setAttribute('x', text.x);
|
||||
svgElement.setAttribute('y', text.y);
|
||||
}
|
1712
experimental/docs/svgbaseddoc.htm
Normal file
1712
experimental/docs/svgbaseddoc.htm
Normal file
File diff suppressed because it is too large
Load Diff
24
experimental/docs/utilities.js
Normal file
24
experimental/docs/utilities.js
Normal file
@ -0,0 +1,24 @@
|
||||
function alpha(value, color) {
|
||||
return value << 24 | (color & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
function argb(a, r, g, b) {
|
||||
return a << 24 | r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
function assert(condition) {
|
||||
if (!condition) debugger;
|
||||
}
|
||||
|
||||
function isAlpha(code) {
|
||||
return (code > 64 && code < 91) // upper alpha (A-Z)
|
||||
|| (code > 96 && code < 123); // lower alpha (a-z)
|
||||
}
|
||||
|
||||
function isArray(a) {
|
||||
return a.constructor === Array;
|
||||
}
|
||||
|
||||
function rgb(r, g, b) {
|
||||
return 0xFF << 24 | r << 16 | g << 8 | b;
|
||||
}
|
Loading…
Reference in New Issue
Block a user