D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
sifbuilder
Full window
Github gist
the big listener, irritating game but needed template to probe #d3js transitions coordinating through unwired #redux store
<html> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <head></head> <body> <div id="container"></div> <script src="https://d3js.org/d3.v4.0.0-alpha.44.min.js"></script> <script> /* */ /* d3rings-actions-court.js */ /* */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsActionsCourt = global.d3ringsActionsCourt || {}))); }(this, function (exports) { 'use strict'; // ____________________ keyMirror // https://github.com/STRML/keyMirror var keyMirror = function(obj, prefix) { var ret = {}; var key; if (!(obj instanceof Object && !Array.isArray(obj))) { throw new Error('keyMirror(...): Argument must be an object.'); } for (key in obj) { if (obj.hasOwnProperty(key)) { ret[key] = prefix + key; } } return ret; }; // ____________________ action TYPES var cttsCourt = { FETCH_RECORDS: '', KEYB_DISPATCH: '', PROCESS_KEYB_KEYS: '', RELEASE_KEYBKEY: '', RESET_KEYS_EVENTS: '', RESIZE_HEIGHT: '', RESIZE_WIDTH: '', SET_KEYBKEY: '', SET_MODE: '', SET_NOTICE: '', SET_VIEW: '', START_KEYS_EVENTS: '', START_KEYBKEY_EVENTS: '', UPDATE_MOUSE_POS: '', } var ActionTypes = keyMirror(cttsCourt, '') // ____________________ actions COURT var ActionCreators = { resizeHeight(payload) { return { type: ActionTypes.RESIZE_HEIGHT, payload: payload } }, resizeWidth(payload) { return { type: ActionTypes.RESIZE_WIDTH, payload: payload } }, releaseKeybKey(e) { return { type: ActionTypes.RELEASE_KEYBKEY, keyCode: e.keyCode, } }, setKeybKey(e) { return { type: ActionTypes.SET_KEYBKEY, keyCode: e.keyCode, } }, processKeybKeys(payload) { return { type: ActionTypes.PROCESS_KEYB_KEYS, // processKeybKeys payload: payload, } }, setMode(payload) { return { type: ActionTypes.SET_MODE, // setMode payload: payload, } }, setNotice(notice) { return { type: ActionTypes.SET_NOTICE, notice: notice, } }, setView(payload) { return { type: ActionTypes.SET_VIEW, payload: payload, } }, startKeybKeyEvents() { return { type: ActionTypes.START_KEYBKEY_EVENTS // startKeybKeyEvents } }, updateMousePos(svg) { return { type: ActionTypes.UPDATE_MOUSE_POS, svg: svg, } }, } exports.ActionTypes = ActionTypes; exports.ActionCreators = ActionCreators; })); /* */ /* d3rings-actions-debug.js */ /* */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsActionsDebug = global.d3ringsActionsDebug || {}))); }(this, function (exports) { 'use strict'; // ____________________ keyMirror // https://github.com/STRML/keyMirror var keyMirror = function(obj, prefix) { var ret = {}; var key; if (!(obj instanceof Object && !Array.isArray(obj))) { throw new Error('keyMirror(...): Argument must be an object.'); } for (key in obj) { if (obj.hasOwnProperty(key)) { ret[key] = prefix + key; } } return ret; } // ____________________ action TYPES var cttsDebug = { SET_DEBUGMODE: '', SET_FPS: '', SWITCH_DEBUGMODE: '', } var ActionTypes = keyMirror(cttsDebug, '') // ____________________ actions DEBUG var ActionCreators = { setDebugMode(debugMode) { return { type: ActionTypes.SET_DEBUG_MODE, debugMode: debugMode, } }, setFps(fps) { return { type: ActionTypes.SET_FPS, fps: fps, } }, switchDebugMode(payload) { return { type: ActionTypes.SWITCH_DEBUGMODE, payload: payload, }; }, } exports.ActionTypes = ActionTypes exports.ActionCreators = ActionCreators })); /* */ /* d3rings-actions.js */ /* */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsActionsLanes = global.d3ringsActionsLanes || {}))); }(this, function (exports) { 'use strict'; // ____________________ keyMirror // https://github.com/STRML/keyMirror var keyMirror = function(obj, prefix) { var ret = {}; var key; if (!(obj instanceof Object && !Array.isArray(obj))) { throw new Error('keyMirror(...): Argument must be an object.'); } for (key in obj) { if (obj.hasOwnProperty(key)) { ret[key] = prefix + key; } } return ret; } var cttsLanes = { DELETE_LANE: '', SET_LANE: '', SET_LANES: '', SET_MESSAGES: '', SET_RECORDS: '', SET_RECORDS_COLLECTION: '', SET_RECORDS_FETCHED: '', UPDATE_MESSAGES: '', WALK_DOWN_RECORDS: '', WALK_UP_RECORDS: '', } var ActionTypes = keyMirror(cttsLanes, '') // ____________________ actions LANES var ActionCreators = { decreaseCursorLow() { return { type: ActionTypes.DECREASE_CURSOR_LOW, } }, decreaseCursorHigh() { return { type: ActionTypes.DECREASE_CURSOR_HIGH, } }, deleteLane(lane) { return { type: ActionTypes.DELETE_LANE, lane: lane, } }, setRecordsFetched(areRecordsFetched) { return { type: ActionTypes.SET_RECORDS_FETCHED, areRecordsFetched: areRecordsFetched, } }, setRecords(argObj) { // SET_RECORDS return { type: ActionTypes.SET_RECORDS, itemSpan: argObj.itemSpan, mode: argObj.currentMode, } }, setRecordsCollection(obj) { // SET_RECORDS_COLLECTION return { type: ActionTypes.SET_RECORDS_COLLECTION, recordsCollection: obj.recordsCollection } }, setLane(lane) { return { type: ActionTypes.SET_LANE, lane: lane, } }, setLanes(lanes) { return { type: ActionTypes.SET_LANES, lanes: lanes, } }, setMessages(messages) { return { type: ActionTypes.SET_MESSAGES, messages: messages, } }, updateMessages(messages) { return { type: ActionTypes.UPDATE_MESSAGES, cursorLow: cursorLow, cursorHigh: cursorHigh, } }, walkDownRecords(payload) { // WALK_DOWN_RECORDS return { type: ActionTypes.WALK_DOWN_RECORDS, payload: payload, } }, walkUpRecords(payload) { // WALK_UP_RECORDS return { type: ActionTypes.WALK_UP_RECORDS, payload: payload, } }, } exports.ActionTypes = ActionTypes exports.ActionCreators = ActionCreators })); /* */ /* d3rings-actions-particles.js */ /* */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsActionsParticles = global.d3ringsActionsParticles || {}))); }(this, function (exports) { 'use strict'; // ____________________ keyMirror // https://github.com/STRML/keyMirror var keyMirror = function(obj, prefix) { var ret = {}; var key; if (!(obj instanceof Object && !Array.isArray(obj))) { throw new Error('keyMirror(...): Argument must be an object.'); } for (key in obj) { if (obj.hasOwnProperty(key)) { ret[key] = prefix + key; } } return ret; } var cttsParticles = { CREATE_PARTICLES: '', INTRODUCE_PARTICLES: '', START_PARTICLES: '', START_TICKER: '', STOP_PARTICLES: '', STOP_TICKER: '', TICK_PARTICLES: '', } var ActionTypes = keyMirror(cttsParticles, '') // ____________________ actions PARTICLES var ActionCreators = { createParticles(obj) { var action = { type: ActionTypes.CREATE_PARTICLES, // createParticles particlesPerTick: obj.particlesPerTick, x: obj.x, y: obj.y, randNormal: obj.randNormal, randNormal2: obj.randNormal2, xInit: obj.xInit, xEnd: obj.xEnd, lanes: obj.lanes, particlesGenerating: obj.particlesGenerating, currentView: obj.currentView, } return action }, introduceParticles(obj) { return { type: ActionTypes.INTRODUCE_PARTICLES, // introduceParticles particlesPerTick: obj.particlesPerTick, x: obj.x, y: obj.y, randNormal: obj.randNormal, randNormal2: obj.randNormal2, xInit: obj.xInit, xEnd: obj.xEnd, lanes: obj.lanes, particlesGenerating: obj.particlesGenerating, currentView: obj.currentView, } }, startParticles() { return { type: ActionTypes.START_PARTICLES } }, startTicker() { return { type: ActionTypes.START_TICKER }; }, stopTicker() { return { type: ActionTypes.STOP_TICKER }; }, stopParticles() { return { type: ActionTypes.STOP_PARTICLES } }, tickParticles(arg) { return { type: ActionTypes.TICK_PARTICLES, // tickParticles width: arg.width, height: arg.height, gravity: arg.gravity, lanes: arg.lanes, } }, } exports.ActionTypes = ActionTypes exports.ActionCreators = ActionCreators })); /* */ /* d3rings-actions-whirls.js */ /* */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsActionsWhirls = global.d3ringsActionsWhirls || {}))); }(this, function (exports) { 'use strict'; // ____________________ keyMirror // https://github.com/STRML/keyMirror var keyMirror = function(obj, prefix) { var ret = {}; var key; if (!(obj instanceof Object && !Array.isArray(obj))) { throw new Error('keyMirror(...): Argument must be an object.'); } for (key in obj) { if (obj.hasOwnProperty(key)) { ret[key] = prefix + key; } } return ret; } var consts = { DELETE_RANG: '', INIT_RANGS: '', SET_DURATION: '', SET_RANG: '', SET_RANGS: '', STOP_RANGS: '', UPDATE_RANGS_DURATION: '', UPDATE_RANGS_NUMBER: '', INTRODUCE_RINGS: '', CREATE_RINGS: '', DELETE_RING: '', START_RINGS: '', START_RINGS_TICKER: '', STOP_RINGS: '', STOP_TICKER: '', TICK_RING: '', TICK_RINGS: '', } var ActionTypes = keyMirror(consts, '') // ____________________ actions RANGS var ActionCreators = { deleteRang(rang) { return { type: ActionTypes.DELETE_RANG, rang: rang, } }, startRangs() { return { type: ActionTypes.INIT_RANGS, startRangs: true, } }, setDuration(duration) { return { type: ActionTypes.SET_DURATION, duration: duration, } }, stopRangs() { return { type: ActionTypes.STOP_RANGS } }, setRang(rang) { return { type: ActionTypes.SET_RANG, rang: rang, } }, setRangs(rangs) { return { type: ActionTypes.SET_RANGS, rangs: rangs, } }, updateRangsDuration(obj) { return { type: ActionTypes.UPDATE_RANGS_DURATION, rangsAlways: obj.rangsAlways, rangsHitsIndex: obj.rangsHitsIndex, } }, updateRangsNumber(obj) { return { type: ActionTypes.UPDATE_RANGS_NUMBER, rangsAlways: obj.rangsAlways, rangsHitsIndex: obj.rangsHitsIndex, } }, introduceRings(obj) { return { type: ActionTypes.INTRODUCE_RINGS, // introduceRings ringsPerTick: obj.ringsPerTick, x: obj.x, y: obj.y, randNormal: obj.randNormal, randNormal2: obj.randNormal2, xInit: obj.xInit, xEnd: obj.xEnd, rangs: obj.rangs, ringsGenerating: obj.ringsGenerating, } }, createRings(obj) { return { type: ActionTypes.CREATE_RINGS, // createRings ringsPerTick: obj.ringsPerTick, x: obj.x, y: obj.y, r: obj.r, randNormal: obj.randNormal, randNormal2: obj.randNormal2, rangs: obj.rangs, ringsGenerating: obj.ringsGenerating, } }, deleteRing(ring) { return { type: ActionTypes.DELETE_RING, ring: ring, } }, startRings() { return { type: ActionTypes.START_RINGS } }, startRingsTicker() { return { type: ActionTypes.START_RINGS_TICKER }; }, stopRingsTicker() { return { type: ActionTypes.STOP_RINGS_TICKER }; }, tickRing(arg) { return { type: ActionTypes.TICK_RING, // tickRing ring: { id: arg.id, rid: arg.rid, cx: arg.cx, cy: arg.cy, r0: arg.r0, r: arg.r, vector: arg.vector, t: arg.t, tn: arg.tn, rang: arg.rang, } } }, stopRings() { return { type: ActionTypes.STOP_RINGS } }, } exports.ActionTypes = ActionTypes exports.ActionCreators = ActionCreators })); /* */ /* d3rings-actions.js */ /* */ if (typeof require === "function") { var d3ringsActionsCourt = require('./d3rings-actions-court.js') var d3ringsActionsDebug = require('./d3rings-actions-debug.js') var d3ringsActionsLanes = require('./d3rings-actions-lanes.js') var d3ringsActionsParticles = require('./d3rings-actions-particles.js') var d3ringsActionsWhirls = require('./d3rings-actions-whirls.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsActions = global.d3ringsActions || {}))); }(this, function (exports) { 'use strict'; // ____________________ merge_objects function merge_objects(ctt1,ctt2){ var i, obj = {} for (i = 0; i < arguments.length; i++) { Object.assign(obj, arguments[i]) } return obj; } var ActionTypes = merge_objects( d3ringsActionsCourt.ActionTypes, d3ringsActionsDebug.ActionTypes, d3ringsActionsLanes.ActionTypes, d3ringsActionsParticles.ActionTypes, d3ringsActionsWhirls.ActionTypes ) var ActionCreators = merge_objects( d3ringsActionsCourt.ActionCreators, d3ringsActionsDebug.ActionCreators, d3ringsActionsLanes.ActionCreators, d3ringsActionsParticles.ActionCreators, d3ringsActionsWhirls.ActionCreators ) exports.ActionTypes = ActionTypes; exports.ActionCreators = ActionCreators; })); /* */ /* d3rings-controls.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsControls = global.d3ringsControls || {}))); }(this, function (exports) { 'use strict'; /* ------------- */ /* timeControls */ /* ------------- */ function timeControls(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } // ____________________ timer function timer() {} // ____________________ start timer.start = function start() { var started = false var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { // listeners[i]() } return timer } // ____________________ subscribe timer.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) d3.timer(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return timer } /* ------------- */ /* stepControls */ /* ------------- */ function stepControls(payload) { var store = payload.store var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } // ____________________ stepper function stepper() {} // ____________________ start stepper.start = function start() { var periodFactor = store.getState().reducerConfig.periodFactor var beatTime = store.getState().reducerConfig.beatTime var periodTime = periodFactor * beatTime // items added var itemSpan = store.getState().reducerConfig.itemSpan var tickspan = store.getState().reducerConfig.tickspan var vLow = store.getState().reducerLanes.messagesCursorLow var vHigh = store.getState().reducerLanes.messagesCursorHigh var tickfn = setInterval(function() { var currentMode = store.getState().reducerCourt.currentMode var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i]() } }, periodTime) return stepper } // ____________________ subscribe stepper.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) // return stepper return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return stepper } /* ------------- */ /* tickControls */ /* ------------- */ function tickControls(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } // ____________________ ticker function ticker() {} // ____________________ start ticker.start = function start() { var started = false var main = function(timestamp) { window.requestAnimationFrame(main) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i]() } } if (!started) { started = true main() } return ticker } // ____________________ subscribe ticker.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return ticker } /* ------------- */ /* mouseDownControls */ /* ------------- */ function mouseDownControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('mousedown', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) // return controlApi return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* touchStartControls */ /* ------------- */ function touchStartControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('touchstart', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) // return controlApi return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* mouseMoveControls */ /* ------------- */ function mouseMoveControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('mousemove', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* touchMoveControls */ /* ------------- */ function touchMoveControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('touchmove', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* mouseUpControls */ /* ------------- */ function mouseUpControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('mouseup', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) // return controlApi return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* touchEndControls */ /* ------------- */ function touchEndControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('touchend', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* mouseLeaveControls */ /* ------------- */ function mouseLeaveControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('mouseleave', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) // return controlApi return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* mouseEnterControls */ /* ------------- */ function mouseEnterControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } function controlAction(svg) { var e = d3.event pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](svg) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start(svg) { svg.on('mouseenter', function() {controlAction(this)}) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* keyDownControl */ /* ------------- */ function keyDownControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } var controlAction = function controlAction(e) { pauseEvent(e) var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](e) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start() { document.addEventListener("keydown", controlAction, false) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) // return controlApi return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* keyReleaseControl */ /* ------------- */ function keyReleaseControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } var controlAction = function controlAction(e) { pauseEvent(e); var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i](e) } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start() { document.addEventListener("keyup", controlAction, false) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } /* ------------- */ /* keyPressControl */ /* ------------- */ function keyPressControl(payload) { var currentListeners = [] var nextListeners = currentListeners // ____________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } function pauseEvent(e){ if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble=true; e.returnValue=false; return false; } var controlAction = function controlAction(e) { pauseEvent(e); var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i]() } } // ____________________ controlApi function controlApi() {} // ____________________ start controlApi.start = function start() { document.addEventListener("keypress", controlAction, false) return controlApi } // ____________________ subscribe controlApi.subscribe = function subscribe (listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } return controlApi } exports.keyDownControl = keyDownControl exports.keyReleaseControl = keyReleaseControl exports.mouseDownControl = mouseDownControl exports.touchStartControl = touchStartControl exports.mouseMoveControl = mouseMoveControl exports.touchMoveControl = touchMoveControl exports.mouseUpControl = mouseUpControl exports.touchEndControl = touchEndControl exports.mouseLeaveControl = mouseLeaveControl exports.mouseEnterControl = mouseEnterControl exports.stepControls = stepControls exports.tickControls = tickControls exports.timeControls = timeControls })); /* */ /* d3rings-reducer-config.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsActions = require('./d3rings-actions.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducerConfig = global.d3ringsReducerConfig || {}))); }(this, function (exports) { 'use strict'; // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ CONFIG var initialStateConfig = { modes: {autoMode: 'autoMode', walkMode: 'walkMode'}, modeLabels: {autoMode: 'auto', walkMode: 'walk'}, views: ['lanesView', 'ringsView'], gravity: 0.5, randNormal: d3.randomNormal(1.3, 2), randNormal2: d3.randomNormal(0.5, 1.8), containerElem: '#container', containerId: 'svgid', tickspan: 60, beatTime: 500, fadeFactor: 3, // times beat - fade items periodFactor: 4, // times beat - add items ringDefaultRadio: 6.33, vstep: 50, itemSpan: 6, itemProps: ['to', 'from'], itemVal: 'msg', recordsCollection_000: [ {id: "1", from: "customer", to: "barrista1", msg: "place order"}, {id: "2", from: "barrista1", to: "register", msg: "enter order"}, {id: "3", from: "register", to: "barrista1", msg: "give total"}, {id: "4", from: "barrista1", to: "barrista1", msg: "get cup making sure that it is fine for purpose"}, {id: "5", from: "barrista1", to: "barrista2", msg: "give cup"}, {id: "6", from: "barrista1", to: "customer", msg: "request money"}, {id: "7", from: "customer", to: "barrista1", msg: "pay order"}, {id: "8", from: "barrista2", to: "barrista2", msg: "get chai mix"}, {id: "9", from: "barrista2", to: "barrista2", msg: "add flavor"}, {id: "10", from: "barrista2", to: "barrista2", msg: "add milk"}, {id: "11", from: "barrista2", to: "barrista2", msg: "add ice"}, {id: "12", from: "barrista2", to: "barrista2", msg: "swirl"}, {id: "13", from: "barrista2", to: "customer", msg: "give tasty beverage"}, {id: "14", from: "customer", to: "tasty beverage", msg: "sip"}, {id: "15", from: "tasty beverage", to: "customer", msg: "burn"}, {id: "16", from: "customer", to: "customer", msg: "cry"}, {id: "17", from: "customer", to: "manager", msg: "complain"}, {id: "18", from: "manager", to: "barrista1", msg: "fire"}, {id: "19", from: "manager", to: "barrista2", msg: "fire"}, ], recordsCollection: [ {id: "1", from: "app", to: "store", msg: "create store"}, {id: "2", from: "store", to: "store", msg: "subscribe lanes listener"}, {id: "3", from: "store", to: "store", msg: "subscribe particles listener"}, {id: "4", from: "app", to: "app", msg: "start kbd controller"}, {id: "5", from: "app", to: "app", msg: "start mouse controller"}, {id: "6", from: "ticker", to: "ticker", msg: "subscribe tickParticles"}, {id: "7", from: "ticker", to: "ticker", msg: "subscribe setRecords"}, {id: "8", from: "ticker", to: "ticker", msg: "start auto"}, {id: "9", from: "store", to: "reducer", msg: "dispatch setRecords action"}, {id: "10", from: "reducer", to: "reducer", msg: "apply action logic"}, {id: "11", from: "reducer", to: "store", msg: "return new state"}, {id: "12", from: "ticker", to: "ticker", msg: "run listeners"}, {id: "13", from: "renderer", to: "UI", msg: "render lanes"}, {id: "14", from: "UI", to: "app", msg: "trigger left arrow event"}, {id: "15", from: "store", to: "reducer", msg: "dispatch setMode action"}, {id: "16", from: "reducer", to: "reducer", msg: "run action"}, {id: "17", from: "reducer", to: "store", msg: "return new state"}, {id: "18", from: "ticker", to: "ticker", msg: "run listeners"}, {id: "19", from: "UI", to: "app", msg: "send down arrow event"}, {id: "20", from: "store", to: "reducer", msg: "dispatch setRecods action"}, {id: "21", from: "reducer", to: "reducer", msg: "run action and get record"}, {id: "22", from: "reducer", to: "reducer", msg: "return new set"}, {id: "23", from: "ticker", to: "ticker", msg: "run listeners"}, {id: "24", from: "renderer", to: "UI", msg: "render lanes"}, {id: "25", from: "UI", to: "app", msg: "send right arrow event"}, {id: "26", from: "store", to: "reducer", msg: "dispatch setMode action"}, {id: "27", from: "reducer", to: "reducer", msg: "run action"}, {id: "28", from: "reducer", to: "reducer", msg: "return new mode auto"}, {id: "29", from: "ticker", to: "ticker", msg: "run listeners with new state"}, {id: "30", from: "renderer", to: "UI", msg: "render auto lanes"}, {id: "31", from: "store", to: "reducer", msg: "dispatch createParticles action"}, {id: "32", from: "reducer", to: "reducer", msg: "run action"}, {id: "33", from: "reducer", to: "store", msg: "return new state with particles"}, {id: "34", from: "ticker", to: "ticker", msg: "run particles listeners"}, {id: "35", from: "renderer", to: "UI", msg: "render particles"}, ], } function reducerConfig(state = initialStateConfig, action) { if (action == null) return state var ActionTypes = d3ringsActions.ActionTypes switch (action.type) { default: return state; } } exports.reducerConfig = reducerConfig; })); /* */ /* d3rings-reducer.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsActions = require('./d3rings-actions-court.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducerCourt = global.d3ringsReducerCourt || {}))); }(this, function (exports) { 'use strict'; // https://stackoverflow.com/questions/31381129/assign-new-id-attribute-to-each-element-created function guid() { function _p8(s) { var p = (Math.random().toString(16)+"000000000").substr(2,8); return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ; } return _p8() + _p8(true) + _p8(true) + _p8(); } // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ COURT var initialStateCourt = { leftBorder: 0, // svgHeight: 400, // svgWidth: 600, // keys: [], keysEvents: {}, notice: 'auto lanes', currentMode: 'autoMode', currentView: 'ringsView', arrowKeysStarted: false, keybKeyEventsStarted: false, tickerStarted: false, lastTick: 0, mousePos: [200, 300], } function reducerCourt(state = initialStateCourt, action) { if (action == null) return state var ActionTypes = d3ringsActions.ActionTypes switch (action.type) { case ActionTypes.START_KEYBKEY_EVENTS: // startKeybKeyEvents // console.log('START_KEYBKEY_EVENTS') return Object.assign({}, state, { keybKeyEventsStarted: true }) case ActionTypes.SET_KEYBKEY: // setKeybkey // console.log('SET_KEYBKEY') var ks = state.keys ks[action.keyCode] = true return Object.assign({}, state, { keys: ks }) case ActionTypes.RELEASE_KEYBKEY: // releaseKeybkey // console.log('RELEASE_KEYBKEY') var ks = state.keys ks[action.keyCode] = false return Object.assign({}, state, { keys: ks }) case ActionTypes.PROCESS_KEYB_KEYS: // processKeybKeys // console.log('PROCESS_KEYB_KEYS state keys', state.keys) var keyEvents = Object.assign({}, state.keyEvents) var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = state.keys if (keys[ctrlKeyCode] !== true && keys[altKeyCode] == true && keys[vKeyCode] == true) { // alt-v keyEvents.altvKey = guid() } if (keys[ctrlKeyCode] !== true && keys[altKeyCode] !== true && keys[vKeyCode] == true) { // v keyEvents.vKey = guid() } if (keys[leftArrow] == true) { // leftArrow keyEvents.leftArrow = guid() } if (keys[rightArrow] == true) { // rightArrow keyEvents.rightArrow = guid() } if (keys[upArrow] == true) { // upArrow keyEvents.upArrow = guid() } if (keys[downArrow] == true) { // downArrow keyEvents.downArrow = guid() } return Object.assign({}, state, { keyEvents: keyEvents }) case ActionTypes.SET_MODE: // console.log('SET_MODE') var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var currentMode = state.currentMode var newMode = currentMode if (keys[leftArrow] == true) { // leftArrow newMode = 'walkMode' } if (keys[rightArrow] == true) { // rightArrow newMode = 'autoMode' } if (keys[upArrow] == true) { // upArrow if (currentMode == 'autoMode') { newMode = 'walkMode' } } if (keys[downArrow] == true) { // downArrow if (currentMode == 'autoMode') { newMode = 'walkMode' } } return Object.assign({}, state, { currentMode: newMode }) case ActionTypes.SET_VIEW: // setView // views currentView var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var views = action.payload.views var currentView = action.payload.currentView var currentViewIndex = views.indexOf(currentView) var newViewIndex = currentView if (keys[vKeyCode] == true && keys[altKeyCode] == true) { // alt-v newViewIndex = views[Math.abs(currentViewIndex + 1) % views.length] } return Object.assign({}, state, { currentView: newViewIndex, }); case ActionTypes.SET_NOTICE: // console.log('SET_NOTICE') return Object.assign({}, state, { notice: action.notice, }); case ActionTypes.START_TICKER: // console.log('START_TICKER') return Object.assign({}, state, { tickerStarted: true }); case ActionTypes.STOP_TICKER: // console.log('STOP_TICKER') return Object.assign({}, state, { tickerStarted: false }); case ActionTypes.UPDATE_MOUSE_POS: var coords = d3.mouse(action.svg) var x = coords[0] var y = coords[1] return Object.assign({}, state, { mousePos: [x, y] }); case ActionTypes.RESIZE_WIDTH: // console.log('RESIZE_WIDTH') var svgWidth = state.svgWidth var delta = 10 var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var newSvgWidth = svgWidth if (keys[rightArrow] == true && keys[ctrlKeyCode] == true) { // rightArrow-Ctrl newSvgWidth = svgWidth + delta } if (keys[leftArrow] == true && keys[ctrlKeyCode] == true) { // lefftArrow-Ctrl newSvgWidth = svgWidth - delta } return Object.assign({}, state, { svgWidth: newSvgWidth }) case ActionTypes.RESIZE_HEIGHT: // console.log('RESIZE_HEIGHT') var svgHeight = state.svgHeight var delta = 10 var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var newSvgHeight = svgHeight if (keys[upArrow] == true && keys[ctrlKeyCode] == true) { // upArrow-Ctrl newSvgHeight = svgHeight + delta } if (keys[downArrow] == true && keys[ctrlKeyCode] == true) { // downArrow-Ctrl newSvgHeight = svgHeight - delta } return Object.assign({}, state, { svgHeight: newSvgHeight }) default: return state; } } exports.reducerCourt = reducerCourt; })); /* */ /* d3rings-reducer-debug.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsActions = require('./d3rings-actions-debug.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducerDebug = global.d3ringsReducerDebug || {}))); }(this, function (exports) { 'use strict'; // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ DEBUG var initialStateDebug = { debugMode: true, debugTickerStarted: false, rfps: 60, fps: 0, fpsMax: 0, timeStamp: 0, timeLastFrame: 0, tickLastFrame: 0, } function reducerDebug(state = initialStateDebug, action) { if (action == null) return state var ActionTypes = d3ringsActions.ActionTypes switch (action.type) { case ActionTypes.SET_FPS: return setFps(state, action) case ActionTypes.SWITCH_DEBUGMODE: return switchDebugMode(state, action) default: return state; } } function setFps(state, action) { // tbc var timeLastFrame0 = state.timeLastFrame var tickLastFrame0 = state.tickLastFrame var timeLastFrame = performance.now() var tickLastFrame = tickLastFrame0 + 1 var timeDelta = timeLastFrame - timeLastFrame0 var fps0 = state.fps var fpsMax = state.fpsMax var fps = (timeLastFrame != 0) ? parseFloat(Math.round(1000 / timeDelta)).toFixed(0) : 0 var fpsMax = Math.max(fpsMax, fps) return Object.assign({}, state, { fps: fps, fpsMax: fpsMax, debugTickerStarted: true, timeLastFrame: timeLastFrame, tickLastFrame: tickLastFrame }) } function switchDebugMode(state, action) { var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var debugMode = state.debugMode var newdebugMode = debugMode if (keys[dKeyCode] == true && keys[altKeyCode] == true) { // alt-d newdebugMode = !state.debugMode } return Object.assign({}, state, { debugMode: newdebugMode }) } exports.reducerDebug = reducerDebug; })); /* */ /* d3rings-reducer-lanes.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsActions = require('./d3rings-actions-lanes.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducerLanes = global.d3ringsReducerLanes || {}))); }(this, function (exports) { 'use strict'; // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ LANES var initialStateLanes = { lanes: [], lanesIndex: 0, messages: [], records: [], keyEventsOnLanes: {}, recordsCollection: [], areRecordsFetched: false, messagesCursorLow: 0, messagesCursorHigh: 0, } function reducerLanes(state = initialStateLanes, action) { if (action == null) return state var ActionTypes = d3ringsActions.ActionTypes switch (action.type) { case ActionTypes.DELETE_LANE: // deleteLane var lanes = state.lanes var ls = lanes.filter(function( obj ) { return obj.id !== action.lane.id; }) var r = Object.assign({}, state, {lanes: ls}, {lanesIndex: ls.length} ) return r case ActionTypes.SET_LANE: // setLane var lanes = state.lanes var ls = {} var result = lanes.filter(function( obj ) { return obj.id == action.lane.id; }); if (result.length === 0) { // add ls = {lanes: [ { id: action.lane.id, name: action.lane.name, x: action.lane.x }, ...lanes ]} } else { // edit ls = {lanes: lanes.map(lane => lane.id === action.lane.id ? Object.assign({}, lane, { id: action.lane.id, name: action.lane.name, x: action.lane.x }) : lane )} } var r = Object.assign({}, state, ls, { lanesIndex: ls.lanes.length }) return r case ActionTypes.SET_LANES: // setLanes // console.log('SET_LANES') return Object.assign({}, state, { lanes: action.lanes, lanesIndex: Object.keys(action.lanes).length }) case ActionTypes.FETCH_RECORDS: // fetchRecords // console.log('FETCH_RECORDS') var processRecord = function processRecord(d) { d.amount = +d.amount; d.risk = +d.risk; d.valueOf = function value() { return this.amount; } return d; } var processData = function processData(error, dataCsv) { if (store.getState().court.currentMode == 0) { // _tbd_ ++timeTick ++vLast store.dispatch(actions.setMessages(store.getState().reducerConfig.recordsCollection.slice(0, store.getState().reducerConfig.recordsCollection.length))) } } d3.queue() .defer(d3.csv, action.src, processRecord) .await(processData) return Object.assign({}, state); case ActionTypes.SET_MESSAGES: // console.log('SET_MESSAGES') return Object.assign({}, state, { messages: action.messages, }) case ActionTypes.SET_RECORDS_FETCHED: // console.log('SET_RECORDS_FETCHED') return Object.assign({}, state, { areRecordsFetched: action.areRecordsFetched }) case ActionTypes.SET_RECORDS_COLLECTION: // setRecordsCollection var r = state if (state.areRecordsFetched == false) { // console.log('SET_RECORDS_COLLECTION') var r = Object.assign({}, state, { recordsCollection: action.recordsCollection, areRecordsFetched: true, }) } return r case ActionTypes.SET_RECORDS: // console.log('SET_RECORDS') var vLow = state.messagesCursorLow var vHigh = state.messagesCursorHigh var itemSpan = action.itemSpan var mode = action.mode var r = state if (mode == 'autoMode') { var records = state.recordsCollection var numRecords = records.length if (vHigh >= vLow) vHigh = vHigh + 1 // add one to upper border if (vHigh > numRecords) vHigh = -1 // upper border if (((vHigh - vLow) > itemSpan) // all spteps full || (vHigh == -1) // infinitum with vLow active || (vLow == -1) // get always from reset ) vLow = vLow + 1 // increase lower border if (vLow > numRecords) vLow = -1 // reset at end of cycle r = Object.assign({}, state, { records: state.recordsCollection.slice(vLow, vHigh), messagesCursorLow: vLow, messagesCursorHigh: vHigh, }) } return r case ActionTypes.WALK_UP_RECORDS: // walkUpRecords var keyEventsOnLanes = state.keyEventsOnLanes var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var vLow = state.messagesCursorLow var vHigh = state.messagesCursorHigh var itemSpan = action.payload.itemSpan var currentMode = action.payload.mode var r = state if (currentMode == 'walkMode') { if (keyEventsOnLanes.upArrow !== null && keyEventsOnLanes.upArrow !== action.payload.keyEvents.upArrow) { // upArrow keyEventsOnLanes.upArrow = action.payload.keyEvents.upArrow vLow = Math.max(0, --vLow) r = Object.assign({}, state, keyEventsOnLanes) r = Object.assign({}, state, { records: state.recordsCollection.slice(vLow, vHigh), messagesCursorLow: vLow, messagesCursorHigh: vHigh, }) } } return r case ActionTypes.WALK_DOWN_RECORDS: // walkDownRecords var keyEventsOnLanes = state.keyEventsOnLanes var altKeyCode = 18, ctrlKeyCode = 17 var vKeyCode = 86, dKeyCode = 68, fKeyCode = 70 var leftArrow = 37, rightArrow = 39, leftArrow = 37, upArrow = 38, downArrow = 40 var keys = action.payload.keys var vLow = state.messagesCursorLow var vHigh = state.messagesCursorHigh var itemSpan = action.payload.itemSpan var currentMode = action.payload.currentMode var r = Object.assign({}, state) if (currentMode == 'walkMode') { if (keyEventsOnLanes.downArrow !== null && keyEventsOnLanes.downArrow !== action.payload.keyEvents.downArrow) { // downArrow keyEventsOnLanes.downArrow = action.payload.keyEvents.downArrow r = Object.assign({}, state, keyEventsOnLanes) if ((vHigh - vLow) >= itemSpan) ++vLow ++vHigh r = Object.assign({}, state, { records: state.recordsCollection.slice(vLow, vHigh), messagesCursorLow: vLow, messagesCursorHigh: vHigh, }) } } return r default: return state } } exports.reducerLanes = reducerLanes; })); /* */ /* d3rings-reducer-particles.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsActions = require('./d3rings-actions-particles.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducerParticles = global.d3ringsReducerParticles || {}))); }(this, function (exports) { 'use strict'; // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ PARTICLES var initialStateParticles = { particles: [], particleIndex: 0, particlesGenerating: true, particlesIntroduced: false, particlesPerTick: 10, particleRadio: 9, } function reducerParticles(state = initialStateParticles, action) { if (action == null) return state var ActionTypes = d3ringsActions.ActionTypes switch (action.type) { case ActionTypes.START_PARTICLES: // startParticles // console.log("START_PARTICLES") return Object.assign({}, state, { particlesGenerating: true }) case ActionTypes.STOP_PARTICLES: // stopParticles // console.log("STOP_PARTICLES") return Object.assign({}, state, { // particlesGenerating: false }); case ActionTypes.INTRODUCE_PARTICLES: // introduceParticles var newParticles = state.particles.slice(0) var numberOfNewParticles = 5 * action.particlesPerTick var currentView = action.currentView var i if ((state.particlesIntroduced == false) && (currentView == 'lanesView')) { for (i = 0; i < numberOfNewParticles; i++) { var particle = {id: state.particleIndex+i, x: action.x, y: action.y, closestLaneDown: {id: 'init', x: action.xInit}, closestLaneUp: {id: 'end', x: action.xEnd}, } particle.vector = [particle.id%2 ? - action.randNormal() : action.randNormal(), - action.randNormal2() * 3.3]; newParticles.unshift(particle); } return Object.assign({}, state, { particles: newParticles, particleIndex: state.particleIndex+i+1, particlesIntroduced: true }) } else { return state } case ActionTypes.CREATE_PARTICLES: // createParticles var newParticles = state.particles.slice(0) var numberOfNewParticles = action.particlesPerTick var particlesGenerating = action.particlesGenerating var currentView = action.currentView if ((particlesGenerating == true) && (currentView == 'lanesView') ){ for (var i = 0; i < numberOfNewParticles; i++) { var ref = parseInt(action.x) var closestLaneUp = action.lanes .filter(function (d) {return d.x >= ref} ) .reduce(function (prev, curr) { return (Math.abs(curr.x - ref) < Math.abs(prev.x - ref) ? curr : prev); }, {id: 'end', x: action.xEnd}) var closestLaneDown = action.lanes .filter(function (d) {return d.x <= ref} ) .reduce(function (prev, curr) { return (Math.abs(curr.x - ref) < Math.abs(prev.x - ref) ? curr : prev); }, {id: 'init', x: action.xInit}) var particle = {id: state.particleIndex+i, x: action.x, y: action.y, closestLaneDown: closestLaneDown, closestLaneUp: closestLaneUp, }; particle.vector = [particle.id%2 ? - action.randNormal() : action.randNormal(), - action.randNormal2()*3.3]; newParticles.unshift(particle); } return Object.assign({}, state, { particles: newParticles, particleIndex: state.particleIndex+i+1 }) } else { return state } case ActionTypes.TICK_PARTICLES: // tickParticles var laneXs = action.lanes .map(function(l) { var x = parseInt(l.x) return x}) var svgWidth = action.width var svgHeight = action.height var gravity = action.gravity var movedParticles = state.particles .filter(function (p) { return (!(p.y > svgHeight)) }) .filter(function (p) { return (!(p.y < 0)) }) .map(function (p) { var vx = p.vector[0] var vy = p.vector[1] p.x += vx p.y += vy var ref = parseInt(p.x) var laneUp = action.lanes .filter(function(l) { return (l.id == p.closestLaneUp.id) }) p.closestLaneUp.x = (laneUp.length > 0 ) ? +laneUp[0].x : +p.closestLaneUp.x var laneDown = action.lanes .filter(function(l) { return (l.id == p.closestLaneDown.id) }) p.closestLaneDown.x = (laneDown.length > 0 ) ? +laneDown[0].x : +p.closestLaneDown.x if (ref < (p.closestLaneDown.x + state.particleRadio) || ref > (p.closestLaneUp.x - state.particleRadio)) { p.vector[0] = -p.vector[0] } p.vector[1] += gravity + 2 * gravity * (p.y - svgHeight) / svgHeight return p }); return Object.assign({}, state, { particles: movedParticles, particleIndex: movedParticles.length, }); default: return state; } } exports.reducerParticles = reducerParticles; })); /* */ /* d3rings-reducer-whirls.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsActions = require('./d3rings-actions-whirls.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducerWhirls = global.d3ringsReducerWhirls || {}))); }(this, function (exports) { 'use strict'; // https://stackoverflow.com/questions/31381129/assign-new-id-attribute-to-each-element-created function guid() { function _p8(s) { var p = (Math.random().toString(16)+"000000000").substr(2,8); return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ; } return _p8() + _p8(true) + _p8(true) + _p8(); } // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ RANGS var initialStateThis = { duration: 2500, n: 3, s0: 200, s: 200, rangs: [], rangsNow: 0, rangsAlways: 0, startRangs: true, rings: [], ringsNew: [], ringsIndex: 0, ringsHits: 0, rangsHitsIndex: 0, rangsHits: [], ringsIntroduced: false, ringsPerTick: 3, ringsRadio: 9, ringsGenerating: true, } function reducerThis(state = initialStateThis, action) { if (action == null) return state var ActionTypes = d3ringsActions.ActionTypes switch (action.type) { case ActionTypes.DELETE_RANG: var rangs = state.rangs var items = rangs.filter(function( obj ) { return obj.rid !== action.rang.rid; }); var r = Object.assign({}, state, {rangs: items}, {rangsNow: items.length} ); return r case ActionTypes.INIT_RANGS: return Object.assign({}, state, { startRangs: true }) case ActionTypes.STOP_RANGS: // console.log('STOP_RANGS') return Object.assign({}, state, { // startRangs: false }) case ActionTypes.SET_RANG: // setRang var rangs = state.rangs var s0 = state.s0 var rangsAlways = state.rangsAlways var items = {} var result = rangs.filter(function( obj ) { return obj.id == action.rang.id; }); if (result.length === 0) { // add rang items = {rangs: [ { id: action.rang.id, rid: action.rang.rid, grid: action.rang.grid, x: action.rang.x, y: action.rang.y, s: action.rang.s, t: action.rang.t, sn: action.rang.s, s: s0, }, ...rangs ]} rangsAlways = rangsAlways + 1 } else { // edit rang items = {rangs: rangs.map(rang => rang.rid === action.rang.rid ? Object.assign({}, rang, { rid: action.rang.rid, grid: action.rang.grid, x: action.rang.x, y: action.rang.y, s: action.rang.s, sn: rang.s, s0: s0, }) : rang )} } var r = Object.assign({}, state, items, {rangsNow: items.rangs.length, rangsAlways: rangsAlways} ) return r case ActionTypes.SET_RANGS: // setRangs // console.log('SET_RANGS') return Object.assign({}, state, { rangs: action.rangs, rangsNow: Object.keys(action.rangs).length }) case ActionTypes.UPDATE_RANGS_DURATION: // updateRangsDuration var duration = state.duration var hitsLostPct = Math.round(100 * (action.rangsAlways - action.rangsHitsIndex) / action.rangsAlways) || 0 if (hitsLostPct < 20) duration = Math.min(Math.max((50 - hitsLostPct) * 20, 1500), 2500) return Object.assign({}, state, { duration: duration, }) case ActionTypes.UPDATE_RANGS_NUMBER: // updateRangsNumber var n = state.n var hitsLostPct = Math.round(100 * (action.rangsAlways - action.rangsHitsIndex) / action.rangsAlways) || 0 var hitsPctBy10 = Math.floor((100 - hitsLostPct)/10) var rangsMax = Math.max(hitsPctBy10, 2) var rangsNumber = Math.min(rangsMax, 8) return Object.assign({}, state, { n: rangsNumber, }) case ActionTypes.CREATE_RINGS: // createRings var _duration = state.duration var _newRings = [] var _ringsHits = state.ringsHits var _rangsHits = state.rangsHits var _rangsHitsIndex = state.rangsHitsIndex if (action.ringsGenerating == true) { var ringsRadio = state.ringsRadio var idx = state.ringsIndex var i, j for (j = 0; j < action.rangs.length; ++j) { var cx = action.x var cy = action.y function inSquare (cx, cy, xl, yl, xh, yh) { if (cx > xl && cx < xh && cy > yl && cy < yh) return true else return false } var xl = action.rangs[j].x var yl = action.rangs[j].y var xh = action.rangs[j].x + action.rangs[j].s var yh = action.rangs[j].y + action.rangs[j].s if (inSquare (cx, cy, xl, yl, xh, yh)) { var rang = action.rangs[j] var rid = rang.id var grid = rang.grid var t = rang.t var s = rang.s var s0 = rang.s0 var r0 = (ringsRadio * s / s0) || 0 var r = (ringsRadio * s / s0) || 0 for (i = 0; i < action.ringsPerTick; i++) { var ring = { id: guid(), cx: cx, cy: cy, r0: r0, r: r, rid: rid, grid: grid, rang: rang, }; ring.vector = [ring.id%2 ? - action.randNormal() : action.randNormal(), - action.randNormal2()] _newRings.unshift(ring) } _ringsHits = _ringsHits + 1 if (_rangsHits.indexOf(grid) == -1) { _rangsHits.push(grid) } _rangsHitsIndex = _rangsHits.length } } var _ringsAll = state.rings.slice(0).concat(_newRings) return Object.assign({}, state, { rings: _ringsAll, ringsNew: _newRings, ringsIndex: _ringsAll.length, ringsHits: _ringsHits, rangsHits: _rangsHits, rangsHitsIndex: _rangsHitsIndex, }) } else { return state } case ActionTypes.DELETE_RING: // deleteRing var rings = state.rings var items = rings.filter(function( obj ) { return obj.id !== action.ring.id; }); var r = Object.assign({}, state, {rings: items}, {ringsIndex: items.length} ) return r case ActionTypes.SET_DURATION: // setDuration // console.log("SET_DURATION") return Object.assign({}, state, { duration: action.duration }) case ActionTypes.START_RINGS: // startRings // console.log("START_RINGS") return Object.assign({}, state, { ringsGenerating: true }) case ActionTypes.STOP_RINGS: // stopRings // console.log("STOP_RINGS") return Object.assign({}, state, { // ringsGenerating: false }); case ActionTypes.TICK_RING: // tickRing var duration = state.duration var ringsRadio = state.ringsRadio // init ring radio var rangs = state.rangs var ringsNew = [] var hitRangs = rangs .filter(function (d) { return (d.id == action.ring.rid) }) if (hitRangs.length > 0) { var rang = hitRangs[0] // rang by id var speed = rang.s0/duration var xe = rang.x + rang.s var xw = rang.x var yn = rang.y var ys = rang.y + rang.s var t = action.ring.t var tn = action.ring.tn var deltas = rang.s - rang.sn var deltat = t - tn var v = deltas/deltat || 0 ringsNew = state.rings // get other rings .reduce(function (a, d) { if (d.id == action.ring.id) { var randx = d.vector[0] var randy = d.vector[1] var dcx = d.cx var dcy = d.cy var dr = d.r var dr0 = d.r0 if (dr > deltas) { if (dcx - dr < xw) randx = - randx if (dcx + dr > xe) randx = randx + 2 * deltas if (dcy - dr < yn) randy = - randy if (dcy + dr > ys) randy = randy + 2 * deltas var xnp1 = dcx + randx var ynp1 = dcy + randy d.tn = t d.r = (1 - t) * dr0 d.vector[0] = randx d.vector[1] = randy var xpose = Math.max(xw, xnp1) var xpos = Math.min(xpose, xe) var yposn = Math.max(yn, ynp1) var ypos = Math.min(yposn, ys) d.cx = xpos d.cy = ypos a.push(d) } return a } else { a.push(d) return a } }, []) } return Object.assign({}, state, { rings: ringsNew, ringsIndex: ringsNew.length, }) default: return state; } } exports.reducer = reducerThis })); /* */ /* d3rings-reducer.js */ /* */ if (typeof require === "function") { var d3ringsReducerConfig = require('./d3rings-reducer-config.js') var d3ringsReducerCourt = require('./d3rings-reducer-court.js') var d3ringsReducerDebug = require('./d3rings-reducer-debug.js') var d3ringsReducerLanes = require('./d3rings-reducer-lanes.js') var d3ringsReducerParticles = require('./d3rings-reducer-particles.js') var d3ringsReducerWhirls = require('./d3rings-reducer-whirls.js') // var d3ringsReducerRangs = require('./d3rings-reducer-rangs.js') // var d3ringsReducerRings = require('./d3rings-reducer-rings.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsReducer = global.d3ringsReducer || {}))); }(this, function (exports) { 'use strict'; // _____________ adapted from redux combineReducers function combineReducers(reducers) { var reducerKeys = Object.keys(reducers) var finalReducers = {} for (var i = 0; i < reducerKeys.length; i++) { var key = reducerKeys[i] if (typeof reducers[key] === 'function') { finalReducers[key] = reducers[key] } } var finalReducerKeys = Object.keys(finalReducers) return function combination(state = {}, action) { var hasChanged = false var nextState = {} for (var i = 0; i < finalReducerKeys.length; i++) { var key = finalReducerKeys[i] var reducer = finalReducers[key] var previousStateForKey = state[key] var nextStateForKey = reducer(previousStateForKey, action) if (typeof nextStateForKey === 'undefined') { var errorMessage = getUndefinedStateErrorMessage(key, action) throw new Error(errorMessage) } nextState[key] = nextStateForKey hasChanged = hasChanged || nextStateForKey !== previousStateForKey } return hasChanged ? nextState : state } } // _____________ combined reducer var reducer = combineReducers({ reducerConfig: d3ringsReducerConfig.reducerConfig, reducerCourt: d3ringsReducerCourt.reducerCourt, reducerDebug: d3ringsReducerDebug.reducerDebug, reducerLanes: d3ringsReducerLanes.reducerLanes, reducerParticles: d3ringsReducerParticles.reducerParticles, reducerWhirls: d3ringsReducerWhirls.reducer, // reducerRangs: d3ringsReducerRangs.reducer, // reducerRings: d3ringsReducerRings.reducer, }) var r = reducer() exports.reducer = reducer; })); /* */ /* d3rings-renderer-court.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsRendererCourt = global.d3ringsRendererCourt || {}))); }(this, function (exports) { 'use strict'; function renderer(payload) { var store = payload.store var actions = payload.actions var newState = store.getState() var state doRender(newState) function doRender(newState) { if (state === newState) return state = newState var svgContainer = d3.select(state.reducerConfig.containerElem) .selectAll('svg') .data(['svg']) var svgContainerNew = svgContainer.enter() .append("svg") .attr("id", state.reducerConfig.containerId) .style('width', state.reducerCourt.svgWidth) .style('height', state.reducerCourt.svgHeight) .attr('class', 'bar-chart') // .style('border', '1px solid red') .style('color', 'blue') .attr('viewbox',"0 0 3 2") var svg = d3.select('svg') var itemsGroup = d3.select('svg') .selectAll('g.notices') // items .data(['items']) itemsGroup.enter() .append("g") .classed("notices", true) // items // _________________________________ render Notice Update var errorNotice = (state.reducerCourt.notice) ? state.reducerCourt.notice : "" var noticeToShow = " " var currentView = state.reducerCourt.currentView var labelMode = state.reducerConfig.modeLabels[state.reducerConfig.modes[state.reducerCourt.currentMode]] var size = parseInt(svg.style("width")) + " x " + parseInt(svg.style("height")) var rangsNow = state.reducerWhirls.rangsNow var particlesNow = state.reducerParticles.particleIndex var ringsNow = state.reducerWhirls.ringsIndex var startRangs = state.reducerWhirls.startRangs var rangsAlways = state.reducerWhirls.rangsAlways var ringsHits = state.reducerWhirls.ringsHits var rangsHitsIndex = state.reducerWhirls.rangsHitsIndex var framesPerSecond = state.reducerDebug.fps var framesPerSecondMax = state.reducerDebug.fpsMax var framesLostPct = (framesPerSecondMax == 0) ? 0 : Math.round(100 * (framesPerSecondMax - framesPerSecond) / framesPerSecondMax) var hitsLostPct = Math.round(100 * (rangsAlways - rangsHitsIndex) / rangsAlways) || 0 if (currentView == 'lanesView') { var cmdsLanes = "down-arrow, right-arrow, alt-v" noticeToShow = noticeToShow + cmdsLanes + " - " + currentView + " - n: " + particlesNow + " - fps: " + framesPerSecond } if (currentView == 'ringsView') { noticeToShow = noticeToShow + ((startRangs) ? '' : ' MOUSE PLEASE !!! ') + ' you already missed ' + hitsLostPct + ' % of your ' + rangsAlways + ' rings' + ' and ' + framesLostPct + ' % of your frames ' + '!!! ' + ' (' + 'try alt-v' + ')' } var winWidthPixels = parseInt(svg.style("width")) var winHeightPixels = parseInt(svg.style("height")) var fontSizeHw = 2 + "hw" var fontSize = winWidthPixels * 2/100 var fontname = 'sans-serif' var c=document.createElement('canvas'); var ctx=c.getContext('2d'); ctx.font = fontSize + 'px ' + fontname; var noticeLength = ctx.measureText(noticeToShow).width var vlocation = winHeightPixels - fontSize var hlocation = winWidthPixels - noticeLength // items elems var itemsElems = svgContainer .select("g.notices") .selectAll("g.notice") .data([noticeToShow]); // items elems enter var itemsElemsNew = itemsElems.enter() .append("g") .classed("notice", true) itemsElemsNew.each(function(d, i) { var itemElemNew = d3.select(this) .append("text") .classed("info", true) .style("font-family", fontname) .attr("x", function(d) { return hlocation; }) .attr("y", function(d) { return vlocation }) .style("font-size", function(d, i) { return fontSize }) .text(function(d) { return d }) .style("fill-opacity", 1) }) // items elems update itemsElems .select('text') .text(function(d) { return d }) .attr("x", function(d) { return hlocation; }) .attr("y", function(d) { return vlocation; }) // items elems exit itemsElems.exit() .select('text') .remove() } // render } exports.renderer = renderer; })); /* */ /* d3rings-renderer-lanes.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsRendererLanes = global.d3ringsRendererLanes || {}))); }(this, function (exports) { 'use strict'; // _____________ coordsUtils function coordsUtils () { function index_hcoord_pct(arr, index) { return (index+1) * (100/(arr.length+1)); } function index_hcoord_pct_with_symbol(arr, index) { return index_hcoord_pct(arr, index) + "%"; } function horizontal_center(x1, x2) { if (x1 > x2) return (x2 - x1)/2 + x1 else return (x1 - x2)/2 + x2 } function horizontal_percent_to_coord(svg, percent) { // https://bugzilla.mozilla.org/show_bug.cgi?id=874811 // _e_ if(navigator.userAgent.toLowerCase().indexOf('firefox') > -1) { var xScrollWidth = svg[0].parentNode.scrollWidth; } else { var xScrollWidth = svg.property("scrollWidth"); } return xScrollWidth * Number.parseFloat(percent)/100; } function horizontal_coord_to_percent(svg, length) { var xScrollWidth = svg.property("scrollWidth"); return Number.parseFloat(length) / xScrollWidth; } var publicAPI = { hcoord_tagged_pct: function hcoord_tagged_pct(arr, val) { return index_hcoord_pct_with_symbol(arr, arr.indexOf(val)); }, hcoord_pct: function hcoord_pct(arr, val) { return index_hcoord_pct(arr, arr.indexOf(val)); }, hcenter_tagged_pct: function hcenter_tagged_pct(x1, x2) { return horizontal_center(x1, x2) + "%"; } } return publicAPI } // _____________ arrayUtils function arrayUtils () { function flattenArrByObjProp(a, p) { return a.reduce(function(prevArr, currVal, i, a) { if (prevArr.indexOf(currVal[p]) < 0) var r = prevArr.push(currVal[p]) return prevArr }, []); } function union_arrays (x, y) { var obj = {}; for (var i = x.length-1; i >= 0; -- i) obj[x[i]] = x[i]; for (var i = y.length-1; i >= 0; -- i) obj[y[i]] = y[i]; var res = [] for (var k in obj) { if (obj.hasOwnProperty(k)) res.push(obj[k]); } return res; } function array_names_from_props (arr, props) { var r = props.reduce( function(prevArr, currVal, i, a) { var q1 = flattenArrByObjProp(arr, currVal) var q = union_arrays(prevArr, q1) return q }, []) return r } var publicAPI = { array_names_from_props: function array_names_from_props (arr, props) { var r = props.reduce( function(prevArr, currVal, i, a) { var q1 = flattenArrByObjProp(arr, currVal) var q = union_arrays(prevArr, q1) return q }, []) return r }, } return publicAPI } // _____________ context var stateLanes = { reducerLanes: {} } var intransition = false // _____________ renderer function renderer(payload) { var store = payload.store var actions = payload.actions var newState = store.getState() // return on transition if (intransition == true) return // return on same data if (JSON.stringify(stateLanes.reducerLanes.records) === JSON.stringify(newState.reducerLanes.records)) { return } // store previous - will not change during renderer var _runners0 = stateLanes.reducerLanes.records || [] var state = stateLanes = newState // hide on wrong views var _opacity = 1 var _currentView = state.reducerCourt.currentView if (_currentView !== 'lanesView') _opacity = 0 var _runners1 = state.reducerLanes.records var _fadeTime = state.reducerConfig.fadeFactor * state.reducerConfig.beatTime var _itemProps = state.reducerConfig.itemProps // SVG var svgContainer = d3.select('body') .selectAll('svg') .data(['lanes_svg'], function(d) { return 'lanes_svg' }) var newSvgContainer = svgContainer .enter() .append("svg") .attr("id", "lanes_svg") var laneGroup = svgContainer .selectAll('g.lane') .data(['lane']) .style('opacity', _opacity) laneGroup.enter() .append("g") .classed("lane", true) var runnersGroup = laneGroup .selectAll('g.runners') .data(['runners']) runnersGroup.enter() .append("g") .classed("runners", true) var lanesGroup = laneGroup .selectAll('g.lanes') .data(['lanes']) lanesGroup.enter() .append("g") .classed("lanes", true) var markerInstance = laneGroup.select(".runner-marker") if (markerInstance.node() == null) { laneGroup .append("marker") .attr("id", "runner-marker") .attr("class", "runner-marker") .attr("viewBox", "0 0 10 10") .attr("refX", "10") .attr("refY", "5") .attr("markerWidth", "5") .attr("markerHeight", "4") .attr("orient", "auto") .append("path") .attr("class", "runner-arrow") .attr("d", "M 0 0 L 10 5 L 0 10 z") } var _laneItems0 = arrayUtils() .array_names_from_props(_runners0, _itemProps) var _laneObjs0 = _laneItems0.map(function(d, i) { return ({id: d, name: d, x0: parseFloat(coordsUtils().hcoord_pct(_laneItems0, d) * parseInt(svgContainer.style("width")) / 100).toFixed(0)})}) var _lanesObj0 = _laneItems0.reduce(function(total,d,currentIndex,arr) { var o = {} o[d] = {name: d, x0: parseFloat(coordsUtils().hcoord_pct(_laneItems0, d) * parseInt(svgContainer.style("width")) / 100).toFixed(0)} return (Object.assign({}, total, o))}, {}) var _laneItems1 = arrayUtils() .array_names_from_props(_runners1, _itemProps) var _laneObjs1 = _laneItems1.map(function(d, i) { var x0 = 0 if ( _lanesObj0.hasOwnProperty( d) ) { x0 = _lanesObj0[d].x0 } return ({id: d, name: d, x0: x0})}) // laneElems trasition var d3ringsTransition = d3.transition() .duration(_fadeTime) .ease(d3.easeLinear) // laneElements DATA var laneElements = svgContainer .select("g.lanes") .selectAll("g.lane") .data(_laneObjs1, function(d) { return d.id }) // laneElements EXIT laneElements.exit() .transition(d3ringsTransition) .style("opacity", function(d) { store.dispatch(actions.deleteLane(d)) return 0 }) .remove(function(){}) // laneElements UPDATE texts var laneTexts = laneElements.select("text") .attr("text-anchor", "middle") .attr("alignment-baseline", "middle") .style("font-size", function(d, i) { return parseInt(svgContainer.style("width")) * 2/100 }) .text(function(d) { return d.name }) .attr("dy", "20") .transition(d3ringsTransition) .attr("x", function(d, i) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name) return r }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // laneElements UPDATE lines var laneLines = laneElements.select("line") .attr("x0", function(d, i) { var r = parseFloat(coordsUtils().hcoord_pct(_laneItems0, d.name) * parseInt(svgContainer.style("width")) / 100).toFixed(0) return r }) .attr("y1", function() { var text_bbox = this.parentNode.querySelector("text").getBBox(); return text_bbox.y + text_bbox.height; }) .attr("y2", "100%") .transition(d3ringsTransition) .attrTween("x1", function(d, i, a) { return function (t) { var r = parseFloat(coordsUtils().hcoord_pct(_laneItems1, d.name) * parseInt(svgContainer.style("width")) / 100).toFixed(0) var x = parseFloat(parseInt(d.x0) + t * (r - parseInt(d.x0))).toFixed(0) // dispatch lanes abscissa var l = {name: d.name, id: d.id, x: x } store.dispatch(actions.setLane(l)) return x } }) .attr("x2", function(d, i) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name) return r }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // newLaneElements ENTER var newLaneElements = laneElements .enter() .append("g") .classed("lane", true) // newLaneElements ENTER text newLaneElements.append("text") .attr("class", "lane") .attr("text-anchor", "middle") .attr("alignment-baseline", "middle") .style("font-family", "sans-serif") .style("fill", "transparent") .style("font-size", function(d, i) { return parseInt(svgContainer.style("width")) * 2/100 }) .text(function(d) { return d.name }) .attr("dy", "20") .attr("x", function(d, i, a) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name) return r }) .transition(d3ringsTransition) .style("fill", "black") .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // newLaneElements ENTER lines newLaneElements.append("line") .attr("class", "lane") .attr("stroke", "lightgray") .style("stroke-width", "1px") .attr("stroke-width", 1) .attr("x0", function(d, i) { var r = parseFloat(coordsUtils().hcoord_pct(_laneItems0, d.name) * parseInt(svgContainer.style("width")) / 100).toFixed(0) return r }) .attr("x1", function(d, i, a) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name) var x = parseFloat(coordsUtils().hcoord_pct(_laneItems1, d.name) * parseInt(svgContainer.style("width")) / 100).toFixed(0) var l = {name: d.name, id: d.id, x: x } store.dispatch(actions.setLane(l)) return r }) .attr("x2", function(d, i, a) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.name) return r }) .attr("y1", function(_d, i) { var text_bbox = this.parentNode.querySelector("text").getBBox(); return text_bbox.y + text_bbox.height; }) .attr("y2", function(d, i, a) { var r = "100%" return r }) // runnerElements var runnerElements = svgContainer .select("g.runners") .selectAll("g.runner") .data(_runners1, function(d, i) { return d.id || (d.id = ++i); }) // runner elems UPDATE texts runnerElements.select('text') .transition(d3ringsTransition) .attr("x", function(d, i) { var r1 = coordsUtils().hcoord_pct(_laneItems1, d.from) var r2 = coordsUtils().hcoord_pct(_laneItems1, d.to) var r = coordsUtils().hcenter_tagged_pct(r1, r2) return r }) .attr("y", function(d, i, s) { var r = (i + 2) * state.reducerConfig.vstep - 10 return r // (i+1)*10 }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // runnerElems UPDATE lines runnerElements.select('line') .transition(d3ringsTransition) .attr("x1", function(d, i, a) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.from) return r }) .attr("x2", function(d, i, a) { var r = coordsUtils().hcoord_tagged_pct(_laneItems1, d.to) return r }) .attr("y1", function(d, i) { var r = (i + 2) * state.reducerConfig.vstep; return r }) .attr("y2", function(d, i) { var r = (i + 2) * state.reducerConfig.vstep; return r }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // runnerElems UPDATE paths runnerElements.select("path") .transition(d3ringsTransition) .attr("d", function(d, i) { var x_pc = coordsUtils().hcoord_tagged_pct(_laneItems1, d.from) var xScrollWidth = parseInt(svgContainer.style("width")) var t = xScrollWidth * Number.parseFloat(x_pc)/100 var x = t var rx = 40 var ry = 20 var y = (i + 2)*50 - ry var sweep_flag = 1 var r = [ "M", x, y, "a", rx, ry, 0, 1, sweep_flag, 0, ry*2, ].join(" "); return r }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // runnerElems ENTER var newMessageElements = runnerElements .enter() .append("g") .classed("runner", true) // runnerElems ENTER TEXTs newMessageElements.each(function(d, i) { var new_runner = d3.select(this) .append("text") .attr("class", "runner") .style("fill", "transparent") .style("font-size", function(d, i) { return parseInt(svgContainer.style("width")) * 2/100 }) .attr("dy", ".15em") .attr("text-anchor", d.from == d.to ? "end" : "middle") .attr("alignment-baseline", d.from == d.to ? "middle" : "autoMode") .text(d.msg) .attr("y", (i + 2) * state.reducerConfig.vstep - 10) .attr("x", function() { var x1 = coordsUtils().hcoord_pct(_laneItems1, d.from) var x2 = coordsUtils().hcoord_pct(_laneItems1, d.to) var r = coordsUtils().hcenter_tagged_pct(x1, x2) return r }) .transition(d3ringsTransition) .style("fill", "grey") .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) }) // runnerElems ENTER PATHs newMessageElements.each(function(d, i) { var new_runner = d3.select(this) if (d.from == d.to) { new_runner.append("path") // new mPATHs .attr("fill-opacity", 0) .attr("stroke", "transparent") .each(function(d) { // this._current = d_to_arc(d, i); // store initial state }) .attr("d", function() { var x_pc_to = coordsUtils().hcoord_pct(_laneItems1, d.to) var xScrollWidth = parseInt(svgContainer.style("width")) var t = xScrollWidth * Number.parseFloat(x_pc_to)/100 var x = t var rx = 40 var ry = 20 var y = (i + 2)*50 - ry var sweep_flag = 1 var r = [ "M", x, y, "a", rx, ry, 0, 1, sweep_flag, 0, ry*2, ].join(" "); return r }) .transition(d3ringsTransition) .attr("stroke", "grey") .attr("fill", "grey") .attrTween("marker-end", function(d) { return function (t) { if (t != 1) { return null } else { return "url(#runner-marker)" } } }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) // runnerElems ENTER LINEs } else { var line = new_runner.append("line") .attr("class", "runner") .attr("stroke", "transparent") .attr("stroke-width", 1) .attr("y1", function() { var r = (i + 2) * state.reducerConfig.vstep ; return r }) .attr("y2", function() { var r = (i + 2) * state.reducerConfig.vstep ; return r }) .attr("x1", coordsUtils().hcoord_tagged_pct(_laneItems1, d.from)) .attr("x2", coordsUtils().hcoord_tagged_pct(_laneItems1, d.to)) .transition(d3ringsTransition) .attr("stroke", "gray") .attr("fill", "grey") .attrTween("marker-end", function() { return function (t) { if (t != 1) { return null } else { return "url(#runner-marker)" } } }) .on("start", function start() { intransition = true }) .on("end", function end() { intransition = false }) } }); // runnerElems EXIT runnerElements.exit() .transition() .style("opacity", 0) .remove() } exports.renderer = renderer; })); /* */ /* d3rings-renderer-particles.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsRendererParticles = global.d3ringsRendererParticles || {}))); }(this, function (exports) { 'use strict'; // _____________ context var stateParticles = { reducerParticles: {} } var rendering = false var intransition = false // _______________________ renderer function renderer(payload) { var store = payload.store var actions = payload.actions var newState = store.getState() if (rendering == true) return if (newState.reducerParticles.particles.length == 0) return rendering = true var state = stateParticles= newState var particleRadio = state.reducerParticles.particleRadio || 6.33 var svgContainer = d3.select('body') .selectAll('svg') .data(['svgContainer']) svgContainer .enter() .append("svg") .attr("id", state.reducerConfig.container) svgContainer .style('width', state.reducerCourt.svgWidth) .style('height', state.reducerCourt.svgHeight) var itemsGroup = d3.select('svg') .selectAll('g.particles') // items .data(['items']) itemsGroup.enter() .append("g") .classed("particles", true) // items // _________________________________ render Particles var color = d3.scalePlasma() .domain([0, 1]) var particleElements = svgContainer .select("g.particles") .selectAll("circle") .data(state.reducerParticles.particles) .attr('cx', function(d, i, a) { return d.x }) .attr('cy', function(d, i, a) { return d.y }) .attr('r', function(d, i, a) { return particleRadio }) .style("fill", function (d) { var r = d.closestLaneUp.x / (d.closestLaneUp.x - d.closestLaneDown.x) return color( ((3*r)%10 / 10) + (Math.random()* 3 /10)) }) .style("fill-opacity", 0.2) .style("stroke", "none") var newParticleElements = particleElements .enter() .append("circle") .attr('cx', function(d, i, a) { return d.x }) .attr('cy', function(d, i, a) { return d.y }) .attr('r', function(d, i, a) { return particleRadio }) .style("fill", function (d) { var r = d.closestLaneUp.x / (d.closestLaneUp.x - d.closestLaneDown.x) return color( ((3*r)%10 / 10) + (Math.random()/10)) }) .style("stroke", "none") particleElements.exit() .remove() rendering = false } // renderer exports.renderer = renderer; })); /* */ /* d3rings-renderer-whirls.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') } (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsRendererWhirls = global.d3ringsRendererWhirls || {}))); }(this, function (exports) { 'use strict'; // https://stackoverflow.com/questions/31381129/assign-new-id-attribute-to-each-element-created function guid() { function _p8(s) { var p = (Math.random().toString(16)+"000000000").substr(2,8); return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ; } return _p8() + _p8(true) + _p8(true) + _p8(); } // Adapted from https://github.com/tj/d3-dot var gen = function(n, l, h, s) { var data = [] for (var i = n; i; i--) { var grid = guid() data.push({ x: Math.random() * l | 0, y: Math.random() * h | 0, id: i, rid: i, grid: grid, s: s }) } return data } // _____________ context var stateWhirls = { reducerWhirls: {} } var intransition = false var intransition_newRang = false var intransition_updRang = false var intransition_newRing = false // _____________ renderer function renderer(payload) { var store = payload.store var actions = payload.actions var newState = store.getState() // return on transition if (intransition == true) return var state = stateWhirls = newState // return if not init - mouse hover var _startRangs = state.reducerWhirls.startRangs // hide on wrong views var _opacity = 1 var _currentView = state.reducerCourt.currentView if (_currentView !== 'ringsView') _opacity = 0 if (_startRangs == false) return var _fadeTime = state.reducerConfig.fadeFactor * state.reducerConfig.beatTime var _itemProps = state.reducerConfig.itemProps var _duration = state.reducerWhirls.duration var _n = state.reducerWhirls.n var _s = state.reducerWhirls.s var _width = state.reducerCourt.svgWidth var _height = state.reducerCourt.svgHeight var _svgid = state.reducerConfig.container var _currentView = state.reducerCourt.currentView // rings var ringsRadio = state.reducerWhirls.ringsRadio || state.reducerConfig.ringDefaultRadio // SVG var svgContainer = d3.select('body') .selectAll('svg') .data(['rangs_svg'], function(d) { return 'rangs_svg' }) var newSvgContainer = svgContainer .enter() .append("svg") .attr("id", 'rangs_svg') svgContainer .style('width', _width) .style('height', _height) d3.select('svg') .selectAll('g.rangs') // items .data(['items']) .style('opacity', _opacity) .enter() .append("g") .classed("rangs", true) // items // rings d3.select('svg') .selectAll('g.rings') // items .data(['items']) .enter() .append("g") .classed("rings", true) // items // https://bl.ocks.org/brattonc/b1abb535227b2f722b51. var dummyText = svgContainer.select(".dummyText") if (dummyText.node() == null) { dummyText = svgContainer .append("text") .attr("id", "dummyText") .attr("class", "dummyText") .text("N") } var textHeight = dummyText.node().getBBox().height // elems trasition var elemsTransition = d3.transition() .duration(_duration) .ease(d3.easeLinear) var rangsTransition = d3.transition() .duration(_duration) .ease(d3.easeLinear) var elemsTransition = d3.transition() .duration(_duration) .ease(d3.easeLinear) var colorScale = d3.scaleCubehelix() .domain([0, 1]) // _________________________________ render rangs var rangGroups = svgContainer.select("g.rangs") // data rang .selectAll("g.rang") .data(gen(_n, _width, _height, _s), function(d) { return d.rid }) var newRangGroups = rangGroups // enter rang .enter() .append("g") .attr("class", "rang") // .attr("id", function (d) { return d.id; }) .attr("rid", function (d) { return d.rid; }) var rectOnNewRang = newRangGroups.append('rect') // append rect .attr("rid", function (d) {return d.rid }) .attr("grid", function (d) {return d.grid }) .attr("class", "rect") .attr("x", function (d) { return d.x; }) .attr("y", function (d) { return d.y; }) .attr("s", function (d) { return d.s; }) .attr("t", function (d) { return d.t; }) .attr("stroke-width", 1) .attr("stroke", "grey") .style("fill", "transparent") if (intransition_updRang == false) { var rectOnExistingRang = rangGroups.select("rect") // update rect .attr("rid", function (d) { return d.rid }) .attr("x", function (d) { return d.x }) .attr("y", function (d) { return d.y }) .attr("s", function (d) { return d.s }) .transition('updRang') .duration(_duration) .ease(d3.easeLinear) .attrTween("height", function(d) { return function (t) { var r = parseInt((1 - t) * d.s) return r } }) .attrTween("width", function(d) { return function (t) { var r = parseInt((1 - t) * d.s) return r } }) .attrTween("s", function(d) { return function (t) { var r = parseInt((1 - t) * d.s) var item = { id: d.id, rid: d.rid, grid: d.grid, x: d.x, y: d.y, t: t, s: parseInt((1 - t) * d.s), } store.dispatch(actions.setRang(item)) return r } }) .on("start", function start() { intransition_updRang = true }) .on("end", function end(d) { store.dispatch(actions.deleteRang(d)) intransition_updRang = false }) rangGroups.exit() // delete rang .remove(function(){ store.dispatch(actions.deleteRang(d)) }) } // _________________________________ render rings var ringElements = svgContainer .select("g.rings") .selectAll("circle") .data(state.reducerWhirls.rings, function (d) { return d.id}) var updateItems = ringElements .attr('r', function(d, i, a) { return d.r }) .attr('cx', function(d, i, a) { return d.cx }) .attr('cy', function(d, i, a) { return d.cy }) .style("fill", function (d) { return colorScale( Math.random() / 2)}) .style("fill-opacity", 0.7) .style("stroke", "none") var newRingElements = ringElements .enter() .append("circle") .attr('class', 'ring') .attr('id', function(d, i, a) { return d.id }) newRingElements .transition('newRing') .duration(_duration) .ease(d3.easeLinear) .attrTween('t', function(d, i, a) { return function (t) { store.dispatch(actions.tickRing(Object.assign({}, d, {t: t}))) return t } }) var exitRingElements = ringElements.exit() .remove(function(){ store.dispatch(actions.deleteRing(d)) }) } // end render exports.renderer = renderer; })); /* */ /* d3rings-store.js */ /* */ /* adapted from REDUX https://redux.js.org/ */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.d3ringsStore = global.d3ringsStore || {}))); }(this, function (exports) { 'use strict'; var createStore = function createStore(reducer, initialState) { var currentReducer = reducer var currentState = initialState var currentListeners = [] var nextListeners = currentListeners var isDispatching = false // ______________________________ ensureCanMutateNextListeners function ensureCanMutateNextListeners() { if (nextListeners === currentListeners) { nextListeners = currentListeners.slice() } } // ______________________________ getState function getState() { return currentState } // ______________________________ redux compose function compose(...funcs) { if (funcs.length === 0) { return arg => arg } else { const last = funcs[funcs.length - 1] const rest = funcs.slice(0, -1) return (...args) => rest.reduceRight((composed, f) => f(composed), last(...args)) } } // ______________________________ subscribe function subscribe(listener) { if (typeof listener !== 'function') { throw new Error('Expected listener to be a function.') } var isSubscribed = true ensureCanMutateNextListeners() nextListeners.push(listener) return function unsubscribe() { if (!isSubscribed) { return } isSubscribed = false ensureCanMutateNextListeners() var index = nextListeners.indexOf(listener) nextListeners.splice(index, 1) } } // ______________________________ dispatch function dispatch(action) { if (typeof action.type === 'undefined') { throw new Error( 'Actions may not have an undefined "type" property. ' + 'Have you misspelled a constant?' ) } if (isDispatching) { throw new Error('Reducers may not dispatch actions.') } try { isDispatching = true currentState = currentReducer(currentState, action) } finally { isDispatching = false } var listeners = currentListeners = nextListeners for (var i = 0; i < listeners.length; i++) { listeners[i]() } return action } // ______________________________ return return { compose: compose, dispatch: dispatch, subscribe: subscribe, getState: getState, } } exports.createStore = createStore; })); /* */ /* index.js */ /* */ if (typeof require === "function") { var d3 = require('./d3.v4.0.0-alpha.44.js') var d3ringsRendererCourt = require('./d3rings-renderer-court.js') var d3ringsRendererLanes = require('./d3rings-renderer-lanes.js') var d3ringsRendererParticles = require('./d3rings-renderer-particles.js') var d3ringsRendererWhirls = require('./d3rings-renderer-whirls.js') var d3ringsReducer = require('./d3rings-reducer.js') var d3ringsStore = require('./d3rings-store.js') var d3ringsActions = require('./d3rings-actions.js') var d3ringsControls = require('./d3rings-controls.js') } /* actions */ var actions = d3ringsActions.ActionCreators /* store */ var store = d3ringsStore.createStore(d3ringsReducer.reducer, d3ringsReducer.reducer()) /* container */ var svgContainer = d3.select(store.getState().reducerConfig.containerElem) .selectAll('svg') .data(['svg']) .enter() .append("svg") .attr("id", store.getState().reducerConfig.containerId) .attr('class', 'chart') .style('width', store.getState().reducerCourt.svgWidth) .style('height', store.getState().reducerCourt.svgHeight) .style('background', 'oldlace') .style('border', '1px solid darkgrey') .attr('viewbox',"0 0 3 2") /* payloads renderers */ var logicAndData_Payload = function () { return { store: store, actions: actions }} var container_Payload = function () { return d3.select('svg') } /* payloads lanes */ var keyDownKeysLanes_Payload = function () { return { keyEvents: store.getState().reducerCourt.keyEvents, currentMode: store.getState().reducerCourt.currentMode, itemSpan: store.getState().reducerConfig.itemSpan, }} var keyUpKeysLanes_Payload = function () { return { keys: store.getState().reducerCourt.keys, currentMode: store.getState().reducerCourt.currentMode, itemSpan: store.getState().reducerConfig.itemSpan, }} var setRecords_Payload = function () { return { itemSpan: store.getState().reducerConfig.itemSpan, currentMode: store.getState().reducerCourt.currentMode }} var setRecordsCollection_Payload = function () { return { recordsCollection: store.getState().reducerConfig.recordsCollection }} /* payloads particles */ var createParticles_Payload = function () { return { particlesPerTick: store.getState().reducerParticles.particlesPerTick, x: store.getState().reducerCourt.mousePos[0], y: store.getState().reducerCourt.mousePos[1], xInit: store.getState().reducerCourt.leftBorder, xEnd: store.getState().reducerCourt.svgWidth, randNormal: store.getState().reducerConfig.randNormal, randNormal2: store.getState().reducerConfig.randNormal2, lanes: store.getState().reducerLanes.lanes, particlesGenerating: store.getState().reducerParticles.particlesGenerating, currentView: store.getState().reducerCourt.currentView, }} var introduceParticles_Payload = function () { return { particlesPerTick: store.getState().reducerParticles.particlesPerTick, x: store.getState().reducerCourt.mousePos[0], y: store.getState().reducerCourt.mousePos[1], xInit: store.getState().reducerCourt.leftBorder, xEnd: store.getState().reducerCourt.svgWidth, randNormal: store.getState().reducerConfig.randNormal, randNormal2: store.getState().reducerConfig.randNormal2, lanes: store.getState().reducerLanes.lanes, particlesGenerating: store.getState().reducerParticles.particlesGenerating, currentView: store.getState().reducerCourt.currentView, }} var tickParticles_Payload = function () { return { width: store.getState().reducerCourt.svgWidth, height: store.getState().reducerCourt.svgHeight, gravity: store.getState().reducerConfig.gravity, lanes: store.getState().reducerLanes.lanes }} /* payloads whirls */ var createRings_Payload = function () { return { ringsPerTick: store.getState().reducerWhirls.ringsPerTick, x: store.getState().reducerCourt.mousePos[0], y: store.getState().reducerCourt.mousePos[1], randNormal: store.getState().reducerConfig.randNormal, randNormal2: store.getState().reducerConfig.randNormal2, rings: store.getState().reducerWhirls.rings, rangs: store.getState().reducerWhirls.rangs, ringsGenerating: store.getState().reducerWhirls.ringsGenerating, }} var updateRangsDuration_Payload = function () { return { rangsAlways: store.getState().reducerWhirls.rangsAlways, rangsHitsIndex: store.getState().reducerWhirls.rangsHitsIndex, }} var updateRangsNumber_Payload = function () { return { rangsAlways: store.getState().reducerWhirls.rangsAlways, rangsHitsIndex: store.getState().reducerWhirls.rangsHitsIndex, }} /* payloads court */ var keyDown_Payload = function (e) { return e } var mouseMove_Payload = function (svg) { return (svg) } var keyDownKeys_Payload = function () { return { keys: store.getState().reducerCourt.keys, views: store.getState().reducerConfig.views, currentView: store.getState().reducerCourt.currentView, }} /* launchers particles*/ var createParticles_particles_Listener = store.compose( store.dispatch, actions.createParticles, createParticles_Payload ) var introduceParticles_particles_Listener = store.compose( store.dispatch, actions.introduceParticles, introduceParticles_Payload ) var tickParticles_particles_Listener = store.compose( store.dispatch, actions.tickParticles, tickParticles_Payload ) var startParticles_particles_Listener = store.compose( store.dispatch, actions.startParticles ) var stopParticles_particles_Listener = store.compose( store.dispatch, actions.stopParticles ) /* launchers lanes */ var keyDownArrow_lanes_Listener = store.compose( store.dispatch, actions.walkDownRecords, keyDownKeysLanes_Payload ) var keyUpArrow_lanes_Listener = store.compose( store.dispatch, actions.walkUpRecords, keyUpKeysLanes_Payload ) var setRecordsCollection_lanes_Listener = store.compose( store.dispatch, actions.setRecordsCollection, setRecordsCollection_Payload ) var setRecords_lanes_Listener = store.compose( store.dispatch, actions.setRecords, setRecords_Payload ) /* launchers rings */ var startRangs_rangs_Listener = store.compose( store.dispatch, actions.startRangs ) var stopRangs_rings_Listener = store.compose( store.dispatch, actions.stopRangs ) var updateRangsDuration_rings_Listener = store.compose( store.dispatch, actions.updateRangsDuration, updateRangsDuration_Payload ) var updateRangsNumber_rings_Listener = store.compose( store.dispatch, actions.updateRangsNumber, updateRangsNumber_Payload ) var createRings_rings_Listener = store.compose( store.dispatch, actions.createRings, createRings_Payload ) var startRings_rings_Listener = store.compose( store.dispatch, actions.startRings ) var stopRings_rings_Listener = store.compose( store.dispatch, actions.stopRings ) /* launchers debug */ var setFps_debug_Listener = store.compose( store.dispatch, actions.setFps ) /* launchers court */ var processKeybKeys_court_Listener = store.compose( store.dispatch, actions.processKeybKeys, keyDown_Payload ) var keyDown_court_Listener = store.compose( store.dispatch, actions.setKeybKey, keyDown_Payload ) var releaseKeybKey_court_Listener = store.compose( store.dispatch, actions.releaseKeybKey ) var updateMousePos_court_Listener = store.compose( store.dispatch, actions.updateMousePos, mouseMove_Payload ) var keyDownAltV_court_Listener = store.compose( store.dispatch, actions.setView, keyDownKeys_Payload ) var keyDownAltD_court_Listener = store.compose( store.dispatch, actions.switchDebugMode, keyDownKeys_Payload ) var keyLeftArrow_court_Listener = store.compose( store.dispatch, actions.setMode, keyDownKeys_Payload ) var keyRightArrow_court_Listener = store.compose( store.dispatch, actions.setMode, keyDownKeys_Payload ) var keyUpArrow_court_Listener = store.compose( store.dispatch, actions.setMode, keyDownKeys_Payload ) var keyDownArrow_court_Listener = store.compose( store.dispatch, actions.setMode, keyDownKeys_Payload ) var keyLeftArrowCtr_court_Listener = store.compose( store.dispatch, actions.resizeWidth, keyDownKeys_Payload ) var keyRightArrowCtrl_court_Listener = store.compose( store.dispatch, actions.resizeHeight, keyDownKeys_Payload ) var keyUpArrowCtrl_court_Listener = store.compose( store.dispatch, actions.resizeWidth, keyDownKeys_Payload ) var keyDownArrowCtrl_court_Listener = store.compose( store.dispatch, actions.resizeHeight, keyDownKeys_Payload ) var renderer_court_Listener = store.compose( d3ringsRendererCourt.renderer, logicAndData_Payload ) var renderer_lanes_Listener = store.compose( d3ringsRendererLanes.renderer, logicAndData_Payload ) var renderer_particles_Listener = store.compose( d3ringsRendererParticles.renderer, logicAndData_Payload ) var renderer_whirls_Listener = store.compose( d3ringsRendererWhirls.renderer, logicAndData_Payload ) /* launchers */ var mouseDown_Launcher = d3ringsControls.mouseDownControl(logicAndData_Payload()).start(d3.select('svg')) var touchStart_Launcher = d3ringsControls.touchStartControl(logicAndData_Payload()).start(d3.select('svg')) var mouseMove_Launcher = d3ringsControls.mouseMoveControl(logicAndData_Payload()).start(d3.select('svg')) var touchMove_Launcher = d3ringsControls.touchMoveControl(logicAndData_Payload()).start(d3.select('svg')) var mouseUp_Launcher = d3ringsControls.mouseUpControl(logicAndData_Payload()).start(d3.select('svg')) var touchEnd_Launcher = d3ringsControls.touchEndControl(logicAndData_Payload()).start(d3.select('svg')) var mouseLeave_Launcher = d3ringsControls.mouseLeaveControl(logicAndData_Payload()).start(d3.select('svg')) var mouseEnter_Launcher = d3ringsControls.mouseEnterControl(logicAndData_Payload()).start(d3.select('svg')) var ticker_Launcher = d3ringsControls.tickControls(logicAndData_Payload()).start() var d3timer_Launcher = d3ringsControls.timeControls(logicAndData_Payload()).start() var stepper_Launcher = d3ringsControls.stepControls(logicAndData_Payload()).start() var keyDown_Launcher = d3ringsControls.keyDownControl(logicAndData_Payload()).start() var keyRelease_Launcher = d3ringsControls.keyReleaseControl(logicAndData_Payload()).start() var keyRelease_Launcher = d3ringsControls.keyReleaseControl(logicAndData_Payload()).start() /* listeners */ store.subscribe(renderer_court_Listener) keyRelease_Launcher.subscribe(releaseKeybKey_court_Listener) keyDown_Launcher.subscribe(keyDown_court_Listener) keyDown_Launcher.subscribe(keyDownAltV_court_Listener) keyDown_Launcher.subscribe(keyDownAltD_court_Listener) keyDown_Launcher.subscribe(keyLeftArrow_court_Listener) keyDown_Launcher.subscribe(keyRightArrow_court_Listener) keyDown_Launcher.subscribe(keyUpArrow_court_Listener) keyDown_Launcher.subscribe(keyDownArrow_court_Listener) keyDown_Launcher.subscribe(keyLeftArrowCtr_court_Listener) keyDown_Launcher.subscribe(keyRightArrowCtrl_court_Listener) keyDown_Launcher.subscribe(keyUpArrowCtrl_court_Listener) keyDown_Launcher.subscribe(keyDownArrowCtrl_court_Listener) mouseMove_Launcher.subscribe(updateMousePos_court_Listener) mouseDown_Launcher.subscribe(updateMousePos_court_Listener) mouseUp_Launcher.subscribe(updateMousePos_court_Listener) mouseLeave_Launcher.subscribe(updateMousePos_court_Listener) mouseEnter_Launcher.subscribe(updateMousePos_court_Listener) touchStart_Launcher.subscribe(updateMousePos_court_Listener) touchMove_Launcher.subscribe(updateMousePos_court_Listener) touchEnd_Launcher.subscribe(updateMousePos_court_Listener) ticker_Launcher.subscribe(processKeybKeys_court_Listener) d3timer_Launcher.subscribe(setFps_debug_Listener) store.subscribe(renderer_lanes_Listener) stepper_Launcher.subscribe(setRecordsCollection_lanes_Listener) stepper_Launcher.subscribe(setRecords_lanes_Listener) stepper_Launcher.subscribe(keyUpArrow_lanes_Listener) stepper_Launcher.subscribe(keyDownArrow_lanes_Listener) store.subscribe(renderer_particles_Listener) mouseDown_Launcher.subscribe(startParticles_particles_Listener) touchStart_Launcher.subscribe(startParticles_particles_Listener) mouseDown_Launcher.subscribe(createParticles_particles_Listener) touchStart_Launcher.subscribe(createParticles_particles_Listener) mouseMove_Launcher.subscribe(createParticles_particles_Listener) touchMove_Launcher.subscribe(createParticles_particles_Listener) mouseUp_Launcher.subscribe(stopParticles_particles_Listener) touchEnd_Launcher.subscribe(stopParticles_particles_Listener) mouseLeave_Launcher.subscribe(stopParticles_particles_Listener) ticker_Launcher.subscribe(tickParticles_particles_Listener) ticker_Launcher.subscribe(createParticles_particles_Listener) stepper_Launcher.subscribe(introduceParticles_particles_Listener) store.subscribe(renderer_whirls_Listener) mouseDown_Launcher.subscribe(startRangs_rangs_Listener) mouseEnter_Launcher.subscribe(startRangs_rangs_Listener) mouseLeave_Launcher.subscribe(stopRangs_rings_Listener) mouseDown_Launcher.subscribe(startRings_rings_Listener) mouseDown_Launcher.subscribe(createRings_rings_Listener) mouseMove_Launcher.subscribe(createRings_rings_Listener) mouseUp_Launcher.subscribe(stopRings_rings_Listener) mouseLeave_Launcher.subscribe(stopRings_rings_Listener) stepper_Launcher.subscribe(updateRangsDuration_rings_Listener) stepper_Launcher.subscribe(updateRangsNumber_rings_Listener) </script> </body> </html>
https://d3js.org/d3.v4.0.0-alpha.44.min.js