/* -------------------------- */ /* animationPlugin */ /* -------------------------- */ var animationPlugin = function animationPlugin() { var isPureArray = d => d.reduce((prev, curr) => prev && typeof curr !== 'object' , true) var isDoubleArray = d => (Array.isArray(d) && Array.isArray(d[0]) && d.length === 1 ) var isPureObject = d => (!Array.isArray(d) && typeof d === 'object') var prescalateval = function(k, v) { let w = v if (typeof(v) === "number" && v > 1000) { let sk = __mapper("scales").scales()[k] let skd = sk.domain() let randomlimit = 100 let rn = skd[1] + (0.5 - Math.random()) * randomlimit w = rn } return w } var prescalate = function(k, v) { // v, f, o, da, a var scls = [] let d, r let w = v if (typeof(v) === "number") { // v :: c w = prescalateval(k, v) } if (typeof(v) === "string") { // v :: "c" w = v } if (isPureObject(v)) { // v :: {} w = v } if (Array.isArray(v)) { if (isPureArray(v)) { if (v.length === 1) { // v :: [a] w = [prescalateval(k, v)] } if (v.length > 1) { // v :: [a, b, c] w = d3.range(v.length).map(function(item, idx){ return prescalateval(k, v[item]) }) } } if (isDoubleArray(v)) { // [[ ]] w = v } if (!isPureArray(v) && !isDoubleArray(v)) { w = v } } return w } var scalate = function(v) { // v, f, o, da, a var scls = [] let d, r if (typeof(v) === "number") { // v :: c d = [0, 1] r = [v, v] scls.push(d3.scaleLinear() .domain(d) .range(r)) } if (typeof(v) === "string") { // v :: "c" d = [0, 1] r = [v, v] scls.push(d3.scaleLinear() .domain(d) .range(r)) } if (isPureObject(v)) { // v :: {} let tspoints = [] let pts = [] tspoints = xsfPlugin()(v).tspoints() for (let j=0; j < tspoints.length; j++) { pts[j] = 0 pts[j] = tspoints[j][0] } let d = d3.range(pts.length).map(function(item, idx){ return idx / (pts.length - 1) }) r = pts // ty scls.push(d3.scaleLinear() .domain(d) .range(r)) } if (Array.isArray(v)) { if (isPureArray(v)) { if (v.length === 1) { // v :: [a] d = [0, 1] r = [v[0], v[0]] scls.push = d3.scaleLinear() .domain(d) .range(r) } if (v.length > 1) { // v :: [a, b, c] // d = d3.range(v.length).map(function(item, idx){ d = v.map(function(item, idx){ return idx / (v.length - 1) }) r = v scls.push(d3.scaleLinear() .domain(d) .range(r)) } } if (isDoubleArray(v)) { // [[ ]] let seqScales = scalate(v[0]) // scales of internal array let ns = d3.scaleLinear() // neutral scale .domain([0]) .range([0]) for (let j=0; j prev.concat(scalate(curr)), []) scls = scls.concat(seqscales) } } return scls } // ============================================== var prescalp = function prescalp (formdef) { let p = [] for (let k in formdef) { let v = formdef[k] // k:v p[k] = prescalate(k,v) } return p } var scalp = function scalp (formdef, dt) { let p = [] for (let k in formdef) { let v = formdef[k] // k:v let scls = scalate(v) let c = 0 for (let m = 0; m < scls.length; m++) { c = c + scls[m](dt) // image of time param } p[k] = c } return p } function animationPlugin(params = {}) { return animationPlugin } animationPlugin.render = function(anima = {}) { console.log("animas enter ", anima) for (let i in __mapper('traces').traces) __mapper('traces').traces[i].clear() var starttime // start time var amimas = [] // make array if (!Array.isArray(anima)) animas = [anima] else animas = anima var durations = [] var waits = [] var limits = [] var periods = [] var steps = [] var ts = [] var traces = [] let timeunits = __mapper('config').animation.timeunits // abstract life span var slots = [] // time step generate slots for (let i= 0; i < animas.length; i++) { durations[i] = __mapper('config').animation.duration if ((typeof(animas[i].tt) !== "undefined") && (animas[i].tt.td !== undefined)) { durations[i] = animas[i].tt.td } } for (let i= 0; i < animas.length; i++) { waits[i] = durations[i] * __mapper('config').animation.wait /timeunits limits[i] = durations[i] * __mapper('config').animation.limit /timeunits steps[i] = durations[i] * __mapper('config').animation.step /timeunits periods[i] = __mapper('config').animation.periods window[i] = false } for (let i= 0; i < animas.length; i++) { let timeinverse = false // time if (typeof(animas[i].tt) !== 'undefined') { if ((Math.sign(animas[i].tt.t0) === -1) || (Math.sign(animas[i].tt.t1) === -1)) timeinverse = true waits[i] = durations[i] * (Math.abs(animas[i].tt.t0) || 0) / timeunits limits[i] = durations[i] * (Math.abs(animas[i].tt.t1) || timeunits) / timeunits // steps[i] = durations[i] * (Math.abs(animas[i].tt.t2) || 1) / timeunits // get length of a step steps[i] = Math.abs(animas[i].tt.t2) || 1 periods[i] = Math.abs(animas[i].tt.t3) || 1 window[i] = (animas[i].tt.tw) ? true : false } let d = (window[i] === false) ? [waits[i], limits[i]] : // time contration [0, durations[i]] // time window let r = (timeinverse === false) ? [0, 1] : [1, 0] ts[i] = d3.scaleLinear() // scale of life .domain(d) .range(r) for (let k in animas[i]) { // your genetic marks let v = animas[i][k] // what they are worth // trace if (k === "hc" && v > 0) { if (__mapper('traces').traces[i] === undefined) __mapper('traces').traces[i] = tracesPlugin("animatrace_" + i) __mapper('traces').traces[i].hc(v) } if (k === "hs" && v > 0) { if (__mapper('traces').traces[i] === undefined) __mapper('traces').traces[i] = tracesPlugin("animatrace_" + i) var color = __mapper("config").colors.scale let stroke = color(v / 1000) // [0,1] __mapper('traces').traces[i].hs(stroke) } } } let maxlimit = Math.max(...limits) // all the animas together living time // living var animation = function(elapsed) { // called by timer if (starttime == undefined) starttime = elapsed for (let i= 0; i < animas.length; i++) { // i anima let t_elapsed = elapsed - starttime // ticks in animation let elan = durations[i] // limits[i] - waits[i] // let elapsedInPeriod = t_elapsed % periods[i] // elapsed ticks in period let elapsedInPeriod = (t_elapsed % ( elan / periods[i])) * periods[i] let dt = ts[i](elapsedInPeriod) // time in period let thisstep = Math.round(t_elapsed / steps[i]) // this step if (slots[i] == undefined) slots[i] = [] if ((waits[i] <= t_elapsed) && (t_elapsed <= limits[i])) { if (slots[i][thisstep] !== 1) { let f = scalp(animas[i], dt) // ***************** let params = Object.assign({}, f, {"layer": "xsf", "id": f.id || 'xsf' + i}) // keep them alone __mapper().xsf(params).render() if (params.hc >= 1 && __mapper('traces') && __mapper('traces').traces[i]) { __mapper('traces').traces[i].addstep([f.tx, f.ty]) __mapper('traces').traces[i].render() } slots[i][thisstep] = 1 } } if (elapsed > maxlimit) { // stop when all animas have spired if (__mapper("tim")) __mapper("tim").timer.stop() } } } animas = animas.map(d => prescalp(d)) // console.log("animas post", JSON.stringify(animas[0], null, 2)) console.log("animas post",animas) if (__mapper('consol')) __mapper('consol').render(animas) __mapper({"tim": Object.assign(__mapper().tim, { 'fn': animation, 'wait': 0, 'timer': d3.timer(animation, 0), 'started': true, 'ticking': true, }) }) } return animationPlugin } ;