Public
Edited
May 26, 2023
Insert cell
Insert cell
list = [3, 4];
Insert cell
list2 = [3, [1, 2]];
Insert cell
function findSum (tree) { return treeReduce(x => x, (x, y) => x + findSum(y), tree, 0); }
Insert cell
function treeMap (f, tree) {

if(!(tree instanceof Array)) return f(tree);
else return tree.map(x => treeMap(f, x));
}
Insert cell
function treeReduce (f, join, tree, acc) {

if(!(tree instanceof Array)) return f(tree);
else return tree.reduce((i, n) => join(i, n), acc);
}
Insert cell
function kfTreeMap(f, kfTree) {

let [tag, ...contents] = kfTree;
if(tag === "kf") return f(kfTree);
else if(kfTree instanceof Array) return kfTree.map(kf => kfTreeMap(f, kf));;
}
Insert cell
function kfTreeReduce(f, join, kfTree, acc) {
let [tag, ...contents] = kfTree;
if(tag === "kf") return f(kfTree);
else if(kfTree instanceof Array) return kfTree.reduce((i, n) => join(i, n), acc);
}
Insert cell
offsetMap = (list, offset) => treeMap(x => x + offset, list);
Insert cell
offsetMap([1, [1, 2]], 1);
Insert cell
function offsetList(tree, offset) {

function offsetListHelper(tree, initOffset) {
let result = treeReduce(val => val + initOffset, ([acc, offset], next) => {

let result = offsetListHelper(next, offset);
let computedOffset = 0;
if(result instanceof Array) { let [acc, sum] = result;
result = acc;
computedOffset = sum;
}

let netOffset = findSum(result);

acc.push(result);

return [acc, netOffset];
}, tree, [[], initOffset]);


if(!(result instanceof Array)) return result;
else return result;

}

let result = offsetListHelper(tree, offset);

return (result instanceof Array) ? result[0] : result;

}
Insert cell
offsetList([1, [2, [1]], 1, 1], 0);
Insert cell
function offsetSeqDelays(tree, offset) {
let offsetKeyframe = ([tag, id, attribs, duration], offset = 0) => {
let delayWithOffset = (duration.delay || 0) + offset;
duration.delay = delayWithOffset;
return [[tag, id, attribs, duration], delayWithOffset + duration.duration];
}

let durationSum = (kfTree) => kfTreeReduce(kf => kf[3].delay + kf[3].duration, (acc, next) => acc + next, kfTree, 0);

function offsetListHelper(tree, initOffset) {
let result = kfTreeReduce((kf) => offsetKeyframe(kf, initOffset), ([acc, offset], next) => {

let result = offsetListHelper(next, offset);
let computedOffset = 0;
if(result[0] !== "kf") {
let [acc, sum] = result;
result = acc;
computedOffset = sum;
if(sum == null) console.warn("Couldn’t compute offset");
}

let netOffset = durationSum(result);

acc.push(result);

return [acc, netOffset];
}, tree, [[], initOffset]);


if(!(result instanceof Array)) return result;
else return result;

}

let result = offsetListHelper(tree, offset);

return (result instanceof Array) ? result[0] : result;
}
Insert cell
offsetSeqDelays([["kf", "#id", {}, {delay: 0, duration: 300}], ["kf", "#id", {}, {delay: 10, duration: 10}]], 0);
Insert cell
function normalize(anims, offset = 0) {

let offsetKeyframe = ([tag, id, attribs, duration], offset = 0) => {
let delayWithOffset = (duration.delay || 0) + offset;
duration.delay = delayWithOffset;
return [[tag, id, attribs, duration], delayWithOffset + duration.duration];
}

function offsetSeq(tree, initOffset) {
let [result, sum] = tree.reduce(([acc, offset], next) => {

let [result, sum] = offsetDelays(next, offset);

let netOffset = sum;

acc.push(result);

return [acc, netOffset];
}, [[], initOffset]);

return [["seq", ...result], sum];

};

const offsetGroup = (contents, offset) => {
let grpResults = contents.map(val => offsetDelays(val, offset));
let newAnims = grpResults.map(x => x[0]);
let newOffset = grpResults.map(x => x[1]).reduce((x, y) => Math.max(x, y));
return [["grp", ...newAnims], newOffset];

};

let offsetDelays = (anims, offset) => {
let [tag, ...contents] = anims;

if(tag == "kf") return offsetKeyframe(anims, offset);
else if(tag == "grp") return offsetGroup(contents, offset);
else if(tag == "seq") { return offsetSeq(contents, offset); }
else throw Error("Unknown element passed");

};

let result = offsetDelays(anims, offset);

return result[0];
}
Insert cell
quickReview(normalize(["grp", ["seq",
["kf", "#id", {}, {duration: 20}],
["kf", "#id2", {}, {duration: 20}],
["grp", ["kf", "#id3", {}, {duration: 10}],
["kf", "#id5", {}, {duration: 10}]],
["kf", "#id4", {}, {duration: 10}]],
["kf", "#id8", {}, {duration: 10}]], 10));
Insert cell
function quickReview (kfTree) {

let [tag, ...contents] = kfTree;

if(tag === "kf") return contents[0] + " | Dur: " + contents[2].duration + " | Off: " + contents[2].delay;
else if(tag === "grp") return "{" + contents.map(x => quickReview(x)).join("\n") + "}";
else if(tag === "seq") return "[" + contents.map(x => quickReview(x)).join("\n") + "]";
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more